

# 比较 Babelfish 与 SQL Server 隔离级别
<a name="babelfish-transaction.examples"></a>

 以下是一些关于 SQL Server 和 Babelfish 如何实现 ANSI 隔离级别的细微差别的示例。

**注意**  
隔离级别 `REPEATABLE READ` 和 `SNAPSHOT` 在 Babelfish 中相同。
隔离级别 `READ UNCOMMITTED` 和 `READ COMMITTED` 在 Babelfish 中相同。

以下示例显示了如何为下面提到的所有示例创建基表：

```
CREATE TABLE employee (
    id sys.INT NOT NULL PRIMARY KEY,
    name sys.VARCHAR(255)NOT NULL,
    age sys.INT NOT NULL
);
INSERT INTO employee (id, name, age) VALUES (1, 'A', 10);
INSERT INTO employee (id, name, age) VALUES (2, 'B', 20);
INSERT INTO employee (id, name, age) VALUES (3, 'C', 30);
```

**Topics**
+ [Babelfish `READ UNCOMMITTED` 与 SQL Server `READ UNCOMMITTED` 隔离级别的比较](#babelfish-transaction.examples.unc)
+ [Babelfish `READ COMMITTED` 与 SQL Server `READ COMMITTED` 隔离级别的比较](#babelfish-transaction.examples.com)
+ [Babelfish `READ COMMITTED` 与 SQL Server `READ COMMITTED SNAPSHOT` 隔离级别的比较](#babelfish-transaction.examples.snapshot)
+ [Babelfish `REPEATABLE READ` 与 SQL Server `REPEATABLE READ` 隔离级别的比较](#babelfish-transaction.examples.read)
+ [Babelfish `SERIALIZABLE` 与 SQL Server `SERIALIZABLE` 隔离级别的比较](#babelfish-transaction.examples.serialize)

## Babelfish `READ UNCOMMITTED` 与 SQL Server `READ UNCOMMITTED` 隔离级别的比较
<a name="babelfish-transaction.examples.unc"></a>

下表详细介绍了执行并发事务时的脏读。它显示了与 Babelfish 实现相比，在 SQL Server 中使用 `READ UNCOMMITTED` 隔离级别时观察到的结果。


| 事务 1 | 事务 2 | SQL Server `READ UNCOMMITTED` | Babelfish `READ UNCOMMITTED` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;` | `SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;` | 无 | 无 | 
| 空闲事务 | `UPDATE employee SET age=0;` | 更新成功。 | 更新成功。 | 
| 空闲事务 | `INSERT INTO employee VALUES (4, 'D', 40);` | 插入成功。 | 插入成功。 | 
| `SELECT * FROM employee;` | 空闲事务 | 事务 1 可以看到事务 2 中未提交的更改。 | 与 Babelfish 中的 `READ COMMITTED` 相同。事务 2 中未提交的更改对事务 1 不可见。 | 
| 空闲事务 | `COMMIT` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 看到事务 2 提交的更改。 | 看到事务 2 提交的更改。 | 

## Babelfish `READ COMMITTED` 与 SQL Server `READ COMMITTED` 隔离级别的比较
<a name="babelfish-transaction.examples.com"></a>

下表详细介绍了执行并发事务时的读取-写入阻止行为。它显示了与 Babelfish 实现相比，在 SQL Server 中使用 `READ COMMITTED` 隔离级别时观察到的结果。


| 事务 1 | 事务 2 | SQL Server `READ COMMITTED` | Babelfish `READ COMMITTED` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL READ COMMITTED;` | `SET TRANSACTION ISOLATION LEVEL READ COMMITTED;` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `UPDATE employee SET age=100 WHERE id = 1;` | 更新成功。 | 更新成功。 | 
| `UPDATE employee SET age = 0 WHERE age IN (SELECT MAX(age) FROM employee);` | 空闲事务 | 在事务 2 提交之前，步骤被阻止。 | 事务 2 的更改尚不可见。更新 id=3 的行。 | 
| 空闲事务 | `COMMIT` | 事务 2 成功提交。事务 1 现已解除阻止，并且可以看到事务 2 的更新。 | 事务 2 成功提交。 | 
| `SELECT * FROM employee;` | 空闲事务 | 事务 1 更新 id = 1 的行。 | 事务 1 更新 id = 3 的行。 | 

## Babelfish `READ COMMITTED` 与 SQL Server `READ COMMITTED SNAPSHOT` 隔离级别的比较
<a name="babelfish-transaction.examples.snapshot"></a>

下表详细介绍了执行并发事务时新插入行的阻止行为。它显示了与 `READ COMMITTED` Babelfish 实现相比，在 SQL Server 中使用 `READ COMMITTED SNAPSHOT` 隔离级别时观察到的结果。


| 事务 1 | 事务 2 | SQL Server `READ COMMITTED SNAPSHOT` | Babelfish `READ COMMITTED` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL READ COMMITTED;` | `SET TRANSACTION ISOLATION LEVEL READ COMMITTED;` | 无 | 无 | 
| `INSERT INTO employee VALUES (4, 'D', 40);` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `UPDATE employee SET age = 99;` | 在事务 1 提交之前，步骤会被阻止。插入的行被事务 1 锁定。 | 更新了三行。新插入的行尚不可见。 | 
| `COMMIT` | 空闲事务 | 提交成功。事务 2 现已解除阻止。 | 提交成功。 | 
| 空闲事务 | `SELECT * FROM employee;` | 所有 4 行都具有 age=99。 | id = 4 的行具有年龄值 40，因为在更新查询期间，事务 2 看不到该行。其他行更新为 age=99。 | 

## Babelfish `REPEATABLE READ` 与 SQL Server `REPEATABLE READ` 隔离级别的比较
<a name="babelfish-transaction.examples.read"></a>

下表详细介绍了执行并发事务时的读取-写入阻止行为。它显示了与 `REPEATABLE READ` Babelfish 实现相比，在 SQL Server 中使用 `REPEATABLE READ` 隔离级别时观察到的结果。


| 事务 1 | 事务 2 | SQL Server `REPEATABLE READ` | Babelfish `REPEATABLE READ` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 无 | 无 | 
| `UPDATE employee SET name='A_TXN1' WHERE id=1;` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `SELECT * FROM employee WHERE id != 1;` | 无 | 无 | 
| 空闲事务 | `SELECT * FROM employee;` | 在事务 1 提交之前，事务 2 将被阻止。 | 事务 2 正常进行。 | 
| `COMMIT` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `SELECT * FROM employee;` | 事务 1 中的更新可见。 | 事务 1 中的更新不可见。 | 
| `COMMIT` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `SELECT * FROM employee;` | 看到事务 1 中的更新。 | 看到事务 1 中的更新。 | 

下表详细介绍了执行并发事务时的写入-写入阻止行为。它显示了与 `REPEATABLE READ` Babelfish 实现相比，在 SQL Server 中使用 `REPEATABLE READ` 隔离级别时观察到的结果。


| 事务 1 | 事务 2 | SQL Server `REPEATABLE READ` | Babelfish `REPEATABLE READ` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | 无 | 无 | 
| `UPDATE employee SET name='A_TXN1' WHERE id=1;` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `UPDATE employee SET name='A_TXN2' WHERE id=1;` | 事务 2 已阻止。 | 事务 2 已阻止。 | 
| `COMMIT` | 空闲事务 | 提交成功且事务 2 已解除阻止。 | 提交成功，事务 2 失败并出现错误，原因是由于并发更新而导致无法序列化访问。 | 
| 空闲事务 | `COMMIT` | 提交成功。 | 事务 2 已中止。 | 
| 空闲事务 | `SELECT * FROM employee;` | id=1 的行具有 name='A\_TX2'。 | id=1 的行具有 name='A\_TX1'。 | 

下表详细介绍了执行并发事务时的幻读行为。它显示了与 `REPEATABLE READ` Babelfish 实现相比，在 SQL Server 中使用 `REPEATABLE READ` 隔离级别时观察到的结果。


| 事务 1 | 事务 2 | SQL Server `REPEATABLE READ` | Babelfish `REPEATABLE READ` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `INSERT INTO employee VALUES (4, 'NewRowName', 20);` | 事务 2 在没有任何阻止的情况下继续进行。 | 事务 2 在没有任何阻止的情况下继续进行。 | 
| 空闲事务 | `SELECT * FROM employee;` | 新插入的行可见。 | 新插入的行可见。 | 
| 空闲事务 | `COMMIT` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 事务 2 插入的新行可见。 | 事务 2 插入的新行不可见。 | 
| `COMMIT` | 空闲事务 | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 新插入的行可见。 | 新插入的行可见。 | 

下表详细介绍了执行并发事务时的情景，以及与 `REPEATABLE READ` Babelfish 实现相比，在 SQL Server 中使用 `REPEATABLE READ` 隔离级别时的不同最终结果。


| 事务 1 | 事务 2 | SQL Server `REPEATABLE READ` | Babelfish `REPEATABLE READ` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | 无 | 无 | 
| `UPDATE employee SET age = 100 WHERE age IN (SELECT MIN(age) FROM employee);` | 空闲事务 | 事务 1 更新 id 为 1 的行。 | 事务 1 更新 id 为 1 的行。 | 
| 空闲事务 | `UPDATE employee SET age = 0 WHERE age IN (SELECT MAX(age) FROM employee);` | 由于 SELECT 语句尝试读取事务 1 中由 UPDATE 查询锁定的行，因此事务 2 被阻止。 | 事务 2 在没有任何阻止的情况下继续进行，因为读取从不会被阻止，SELECT 语句执行，最后更新了 id = 3 的行，因为事务 1 更改尚不可见。 | 
| 空闲事务 | `SELECT * FROM employee;` | 此步骤在事务 1 提交后执行。id = 1 的行在上一步中由事务 2 更新，此处可见。 | id = 3 的行由事务 2 更新。 | 
| `COMMIT` | 空闲事务 | 事务 2 现已解除阻止。 | 提交成功。 | 
| 空闲事务 | `COMMIT` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 两个事务都对 id = 1 的行执行更新。 | 事务 1 和 2 更新不同的行。 | 

## Babelfish `SERIALIZABLE` 与 SQL Server `SERIALIZABLE` 隔离级别的比较
<a name="babelfish-transaction.examples.serialize"></a>

下表详细介绍了执行并发事务时的范围锁。它显示了与 `SERIALIZABLE` Babelfish 实现相比，在 SQL Server 中使用 `SERIALIZABLE` 隔离级别时观察到的结果。


| 事务 1 | 事务 2 | SQL Server `SERIALIZABLE` | Babelfish `SERIALIZABLE` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `INSERT INTO employee VALUES (4, 'D', 35);` | 在事务 1 提交之前，事务 2 将被阻止。 | 事务 2 在没有任何阻止的情况下继续进行。 | 
| 空闲事务 | `SELECT * FROM employee;` | 无 | 无 | 
| `COMMIT` | 空闲事务 | 事务 1 成功提交。事务 2 现已解除阻止。 | 事务 1 成功提交。 | 
| 空闲事务 | `COMMIT` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 新插入的行可见。 | 新插入的行可见。 | 

下表详细介绍了执行并发事务时的情景，以及与 `SERIALIZABLE` Babelfish 实现相比，在 SQL Server 中使用 `SERIALIZABLE` 隔离级别时的不同最终结果。


| 事务 1 | 事务 2 | SQL Server `SERIALIZABLE` | Babelfish `SERIALIZABLE` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | 无 | 无 | 
| 空闲事务 | `INSERT INTO employee VALUES (4, 'D', 40);` | 无 | 无 | 
| `UPDATE employee SET age =99 WHERE id = 4;` | 空闲事务 | 在事务 2 提交之前，事务 1 将被阻止。 | 事务 1 在没有任何阻止的情况下继续进行。 | 
| 空闲事务 | `COMMIT` | 事务 2 成功提交。事务 1 现已解除阻止。 | 事务 2 成功提交。 | 
| `COMMIT` | 空闲事务 | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 可以看到新插入的年龄值 = 99 的行。 | 可以看到新插入的年龄值 = 40 的行。 | 

下表详细介绍了当您对具有唯一约束的表执行 `INSERT` 时的情景。它显示了与 `SERIALIZABLE` Babelfish 实现相比，在 SQL Server 中使用 `SERIALIZABLE` 隔离级别时观察到的结果。


| 事务 1 | 事务 2 | SQL Server `SERIALIZABLE` | Babelfish `SERIALIZABLE` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | 无 | 无 | 
| 空闲事务 | `INSERT INTO employee VALUES (4, 'D', 40);` | 无 | 无 | 
| `INSERT INTO employee VALUES ((SELECT MAX(id)+1 FROM employee), 'E', 50);` | 空闲事务 | 在事务 2 提交之前，事务 1 将被阻止。 | 在事务 2 提交之前，事务 1 将被阻止。 | 
| 空闲事务 | `COMMIT` | 事务 2 成功提交。事务 1 现已解除阻止。 | 事务 2 成功提交。事务 1 中止，出现错误，原因是重复键值违反了唯一约束。 | 
| `COMMIT` | 空闲事务 | 事务 1 成功提交。 | 事务 1 提交失败，原因是由于事务之间的读取或写入依赖关系，无法序列化访问。 | 
| `SELECT * FROM employee;` | 空闲事务 | 插入行 (5, 'E', 50)。 | 仅存在 4 行。 | 

在 Babelfish 中，如果这些事务的执行与这些事务的所有可能的串行（一次一个）执行不一致，则以隔离级别 Serializable 运行的并发事务将失败，并出现序列化异常错误。

下表详细介绍了执行并发事务时的序列化异常。它显示了与 `SERIALIZABLE` Babelfish 实现相比，在 SQL Server 中使用 `SERIALIZABLE` 隔离级别时观察到的结果。


| 事务 1 | 事务 2 | SQL Server `SERIALIZABLE` | Babelfish `SERIALIZABLE` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 无 | 无 | 
| `UPDATE employee SET age=5 WHERE age=10;` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `SELECT * FROM employee;` | 在事务 1 提交之前，事务 2 将被阻止。 | 事务 2 在没有任何阻止的情况下继续进行。 | 
| 空闲事务 | `UPDATE employee SET age=35 WHERE age=30;` | 无 | 无 | 
| `COMMIT` | 空闲事务 | 事务 1 成功提交。 | 事务 1 首先提交，并且能够成功提交。 | 
| 空闲事务 | `COMMIT` | 事务 2 成功提交。 | 事务 2 提交失败并出现序列化错误，整个事务已回滚。重试事务 2。 | 
| `SELECT * FROM employee;` | 空闲事务 | 这两个事务的更改都是可见的。 | 事务 2 已回滚。只能看到事务 1 更改。 | 

在 Babelfish 中，只有当所有并发事务都以 `SERIALIZABLE` 隔离级别执行时，才可能出现序列化异常。在下表中，我们以上面的示例为例，但将事务 2 改为隔离级别 `REPEATABLE READ`。


| 事务 1 | 事务 2 | SQL Server 隔离级别 | Babelfish 隔离级别 | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | 无 | 无 | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | 无 | 无 | 
| `SELECT * FROM employee;` | 空闲事务 | 无 | 无 | 
| `UPDATE employee SET age=5 WHERE age=10;` | 空闲事务 | 无 | 无 | 
| 空闲事务 | `SELECT * FROM employee;` | 在事务 1 提交之前，事务 2 将被阻止。 | 事务 2 在没有任何阻止的情况下继续进行。 | 
| 空闲事务 | `UPDATE employee SET age=35 WHERE age=30;` | 无 | 无 | 
| `COMMIT` | 空闲事务 | 事务 1 成功提交。 | 事务 1 成功提交。 | 
| 空闲事务 | `COMMIT` | 事务 2 成功提交。 | 事务 2 成功提交。 | 
| `SELECT * FROM employee;` | 空闲事务 | 这两个事务的更改都是可见的。 | 这两个事务的更改都是可见的。 | 