Programmingデータエンジニア

SQLにおけるトランザクション隔離(アイソレーションレベル)の使用原則を説明し、アプリケーションに適切な隔離レベルを選択する方法を説明してください。各レベルの異常の例を挙げてください。

Hintsage AIアシスタントで面接を突破

回答

トランザクションの隔離は、同時実行トランザクションがお互いの変更をどのように見るかに影響します。これはACID特性の重要な部分です。ANSI SQLには四つの基本的な隔離レベルがあります:

  • READ UNCOMMITTED — 他のトランザクションの未コミットの変更も見ることができる(ダーティリード)。
  • READ COMMITTED — コミットされた変更のみを見ることができる; ダーティリードは防止されるが、非再現可能なリードを許可する。
  • REPEATABLE READ — 同じトランザクション内で同じデータが変更されないことが保証される。ダーティリードと非再現可能なリードを避けられるが、ファントムリードが発生する可能性がある。
  • SERIALIZABLE — 最も厳格で、トランザクションは完全に隔離され、順番に実行されるかのように見える; すべての種類の異常を排除する。

レベルの選択はアプリケーションの要件に依存します:

  • レポートにはREPEATABLE READ以上で十分であることが多い;
  • 高負荷システムには最適な妥協点はREAD COMMITTED;
  • 財務にはSERIALIZABLEが必要ですが、パフォーマンスは低下します。

例:

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN; -- 今後のSELECTは「凍結」された値を見ることになります

ひねりのある質問

「REPEATABLE READレベルはすべてのDBでファントムリードから保護することを保証しますか?」

いいえ。PostgreSQLや他のいくつかのDBMSでは、REPEATABLE READレベルはダーティリードと非再現可能なリードを防止しますが、ファントムリードから必ずしも保護するわけではありません。MySQL/InnoDBではREPEATABLE READは実質的にSERIALIZABLEですが、他のDBMSではそうではありません。

例:
-- 1つのトランザクションでSELECT * FROM orders WHERE amount > 100を読み取る; -- 別のトランザクションでamount > 100の新しい値が挿入されてコミットされる -- 最初のトランザクションは再度SELECTした際に「ファントム」の行を見ることになります、隔離がSERIALIZABLEより低い場合

知識の不足による実際のエラーの例


ストーリー

金融サービスがパフォーマンスのためにREAD COMMITTEDのみをブロック — ユーザーは他のプロセスによってすでに変更された金額を見て、残高に不一致が生じました。


ストーリー

ホテル予約システムで同じ部屋の二重予約が発生 — トランザクションは現在の予約の出力を隔離せず、レベルはREAD COMMITTED。


ストーリー

MySQLからPostgreSQLへの移行: 開発者はREPEATABLE READがファントムから保護されることに慣れていましたが、移行後に同じトランザクション内で再度のクエリで期待していない「保留中」の注文が表示されました。