

# 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 の変更はまだ表示されていません。Updates row with 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 によってロックされます。 | 3 行を更新しました。新しく挿入された行はまだ表示されません。 | 
| `COMMIT` | トランザクションでのアイドル状態 | コミットは成功しました。トランザクション 2 のブロックが解除されました。 | コミットは成功しました。 | 
| トランザクションでのアイドル状態 | `SELECT * FROM employee;` | All 4 rows have age=99. | id = 4 の行は、更新クエリ中にトランザクション 2 に表示されなかったため、保持時間の値は 40 です。その他の行は 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;` | トランザクション 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 の行に 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 ステートメントが実行され、トランザクション 1 の変更がまだ表示されないため、id = 3 の行が最終的に更新されます。 | 
| トランザクションでのアイドル状態 | `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);` | トランザクション 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 では、分離レベルでシリアル化可能な同時トランザクションは、これらのトランザクションの実行がそれらのトランザクションの可能なすべてのシリアル (一度に 1 つ) 実行と一致しない場合、シリアル化異常エラーで失敗します。

次の表は、同時トランザクションの実行時におけるシリアル化の異常の詳細を示しています。これは、`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;` | トランザクションでのアイドル状態 | 両方のトランザクションからの変更が表示されます。 | 両方のトランザクションからの変更が表示されます。 | 