トランザクションは、複数のステートメントを1つの原子的な単位にまとめます。すべてコミットするか、すべてロールバックするかのどちらかで、ACIDのA、C、I、Dを実現します。isolation levelは「I」を調整します。すなわち、同時実行のトランザクションが互いの未コミットまたは変化中のデータをどこまで見られるかです。
トランザクションは、複数のステートメントを1つの原子的な単位にまとめます。すべてコミットするか、すべてロールバックするかのどちらかで、ACIDのA、C、I、Dを実現します。isolation levelは「I」を調整します。すなわち、同時実行のトランザクションが互いの未コミットまたは変化中のデータをどこまで見られるかです。
| レベル | dirty read | non-repeatable read | phantom |
|---|
| READ UNCOMMITTED | あり | あり | あり |
| READ COMMITTED | なし | あり | あり |
| REPEATABLE READ(InnoDBのデフォルト) | なし | なし | ほぼなし* |
| SERIALIZABLE | なし | なし | なし |
*InnoDBのREPEATABLE READはMVCC(各トランザクションが一貫したスナップショットを読む)とnext-key lockを併用するため、ほとんどのphantomも防ぎます。SQL標準が要求するより強力です。
SELECT @@transaction_isolation; -- REPEATABLE-READ by default
START TRANSACTION;
SELECT balance FROM accounts WHERE id = 1; -- snapshot taken here
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT; -- both updates apply, or ROLLBACK undoes both
理由がない限り、InnoDBのデフォルト(REPEATABLE READ)のままにします。READ COMMITTED(Postgres/Oracleのデフォルト)は書き込みの多いシステムでロック競合を減らします。SERIALIZABLEは正しいものの、競合する処理を直列化し、デッドロックが増えることがあります。
isolationは、正しさと並行性のあいだのダイヤルです。これらの異常を理解していれば、「負荷時に合計が合わなかった」といったバグを説明でき、スループットを不必要に絞ることなく、お金を動かすトランザクションを正しく保つレベルを選べます。
ジュニアからシニアまで、詳細な回答付きのIT面接質問ライブラリ。
寄付する