-3

假设我们尝试同时运行以下两个事务:

T1:
BEGIN
  UPDATE place
  SET state_code=5
  WHERE state_code=6
  AND type='town'
COMMIT

T2:
BEGIN
  UPDATE place
  SET state_code=6
  WHERE state_code=5
  AND type='town'
COMMIT

在 Postgres 9.0 上,事务成功完成。但是,当在 SQLServer 2005 T1 上运行时,T1 会中止,因此所有状态都以 state_code=5 结束。

  1. 哪个 DBMS 遵守/不遵守严格的事务序列化,为什么?
  2. 每个 DBMS 中可能设置或未设置哪些设置会导致此行为?
4

2 回答 2

2

MS SQL 使用事务语句作为:

BEGIN transaction
  UPDATE place
  SET state_code=5
  WHERE state_code=6
  AND type='town'
COMMIT
于 2012-11-12T14:26:36.220 回答
1

在 PostgreSQL 中,您可以通过使用表级锁来测试这一点,以确保竞争事务同时运行。设置:

CREATE TABLE place (id serial primary key, state_code integer, type text);
INSERT INTO place (state_code, type) VALUES (5, 'town'), (6, 'town');

然后在会话 T0 中:

BEGIN; LOCK TABLE place;

在两个新会话中,发出 T1 和 T2 的命令。

现在回到 T0 问题:

ROLLBACK;

释放表级锁并允许 T1 和 T2 竞争。

隔离(默认)两者都将被转置......尽管在READ COMMITTED现实世界中这将取决于交易的确切顺序并且不能依赖。

REPEATABLE READ, 中(在 PostgreSQL 9.0 中称为SERIALIZABLE隔离),它们都将被转置,与 with 相同的警告,READ COMMITTED因为两者对于单语句事务本质上是等效的;快照是在运行第一条语句时拍摄的,而不是在BEGIN.

SERIALIZABLE孤立地,通过 GUC 或 设置,default_transaction_isolation一个BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE事务将无法提交并出现序列化失败,而另一个事务将成功,导致所有行有state_code5,或所有行有state_code6,具体取决于哪个事务获胜。

如果 SQL Server 也中止了其中一个事务,那么它正在执行正确的序列化。

SQL Server 遵循正确的序列化(当要求严格序列化时,就像当前版本的 PostgreSQL 一样),而 PostgreSQL 的测试版本设置为READ COMMITTED隔离(不应该序列化)或 9.1 之前的SERIALIZABLE隔离(无法检测到此异常)并且遵守严格的事务序列化语义。

如果default_transaction_isolation设置为除 之外的任何内容,则在 PostgreSQL 9.2 中可能会遇到这种情况SERIALIZABLE,并且是 PostgreSQL 9.1 之前的规范。

看起来 SQL Server 使用SET TRANSACTION ISOLATION LEVEL. 在 PostgreSQL 中,您使用default_transaction_isolationGUCSET TRANSACTION ISOLATION LEVEL. 尚不清楚 SQL Server 是否允许您在全局范围内设置默认事务隔离级别。

于 2012-11-13T00:38:03.463 回答