🐱 うさねこ教室 Python と可観測性の教室

トランザクションと一貫性

🐱 この章の目次

ACID の意味

トランザクションは、複数の読み書き操作を 1 つの論理単位としてまとめる仕組みです。 ACID はその保証を表す頭字語で、Atomicity(原子性)・Consistency(一貫性)・Isolation(分離性)・Durability(永続性)を意味します。 『データ指向アプリケーションデザイン』第 7 章では、特に Isolation の実装バリエーションに焦点を当てています。

分離レベル

分離レベルは、同時実行されるトランザクション間でどの程度の干渉を許容するかを定めます。 レベルが高いほど安全ですが、性能やスケーラビリティとのトレードオフがあります。

分離レベル防げる問題許容される問題
Read Uncommittedダーティリード、反復不能読み取り、ファントム
Read Committedダーティリード反復不能読み取り、ファントム
Snapshot Isolationダーティリード、反復不能読み取り書き込みスキュー、ファントム
Serializableすべて

PostgreSQL のデフォルトは Read Committed で、SET TRANSACTION ISOLATION LEVEL で変更できます。

-- Snapshot Isolation(PostgreSQL では REPEATABLE READ)での実行例
BEGIN;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

SELECT balance FROM accounts WHERE id = 1;  -- 読み取りスナップショット時点の値
UPDATE accounts SET balance = balance - 100 WHERE id = 1;

COMMIT;

書き込みスキューとファントム

書き込みスキュー(write skew) は、2 つのトランザクションがそれぞれ異なる行を更新するが、全体として不変条件を壊すパターンです。 たとえば「最低 1 人はオンコール当番にいる」という制約を、2 人が同時に自分を外すことで違反します。 ファントムは、あるトランザクションの検索条件に一致する行が、別のトランザクションによって挿入・削除される現象です。

直列化の実装方式

完全な Serializable 分離を実現する代表的な手法は 2 つあります。

二相ロック(2PL: Two-Phase Locking) は、読み取りに共有ロック・書き込みに排他ロックを取得し、トランザクション終了まで保持します。 安全ですがデッドロックが発生しやすく、スループットが低下します。

直列化スナップショット分離(SSI: Serializable Snapshot Isolation) は、楽観的に実行し、コミット時にコンフリクトを検出してアボートする方式です。 PostgreSQL 9.1 以降の SERIALIZABLE レベルは SSI で実装されており、2PL より高いスループットを実現しています。