

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 比較 Babelfish 和 SQL Server 隔離層級
<a name="babelfish-transaction.examples"></a>

 以下是一些範例，示範 SQL Server 和 Babelfish 如何實作 ANSI 隔離層級的細微差異。

**注意**  
Babelfish 中的隔離層級 `REPEATABLE READ`和 `SNAPSHOT` 是相同的。
Babelfish 中的隔離層級 `READ UNCOMMITTED`和 `READ COMMITTED` 是相同的。

下列範例示範如何為以下提及所有範例建立基礎資料表：

```
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` 相同。交易 1 看不到來自交易 2 的未遞交變更。 | 
| 交易閒置 | `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 列都具有存留期=99。 | id = 4 之列的存留期值為 40，因為更新查詢期間交易 2 看不到此值。其他列會更新為存留期=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;` | 交易 2 遭封鎖，直到交易 1 遞交為止。 | 交易 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 的列名稱為='A\_TX2'。 | id=1 的列名稱為='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 更新，於此處是可見的。 | 交易 2 會更新 id = 3 的列。 | 
| `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);` | 交易 2 遭封鎖，直到交易 1 遞交為止。 | 交易 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;` | 交易閒置 | 交易 1 遭封鎖，直到交易 2 遞交為止。 | 交易 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);` | 交易閒置 | 交易 1 遭封鎖，直到交易 2 遞交為止。 | 交易 1 遭封鎖，直到交易 2 遞交為止。 | 
| 交易閒置 | `COMMIT` | 交易 2 已成功遞交。交易 1 現已解除封鎖。 | 交易 2 已成功遞交。因錯誤重複索引鍵值而中止的交易 1 違反唯一限制條件。 | 
| `COMMIT` | 交易閒置 | 交易 1 已成功遞交。 | 交易 1 遞交失敗，因為交易之間的讀取或寫入相依性而無法序列化存取。 | 
| `SELECT * FROM employee;` | 交易閒置 | 列 (5、'E'、50) 已插入。 | 只有 4 個列存在。 | 

在 Babelfish 中，以可序列化隔離層級執行的並行交易，若其執行結果與那些交易執行結果所有可能的序列 (一次一個) 不一致，則會因可序列化異常錯誤而失敗。

下表提供執行並行交易時，序列化異常的詳細資訊。與 `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;` | 交易 2 遭封鎖，直到交易 1 遞交為止。 | 交易 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;` | 交易 2 遭封鎖，直到交易 1 遞交為止。 | 交易 2 繼續進行，而沒有任何封鎖。 | 
| 交易閒置 | `UPDATE employee SET age=35 WHERE age=30;` | 無 | 無 | 
| `COMMIT` | 交易閒置 | 交易 1 已成功遞交。 | 交易 1 已成功遞交。 | 
| 交易閒置 | `COMMIT` | 交易 2 已成功遞交。 | 交易 2 已成功遞交。 | 
| `SELECT * FROM employee;` | 交易閒置 | 兩個交易的變更都是可見的。 | 兩個交易的變更都是可見的。 | 