MySQLのトランザクションにおける三大並行処理問題を、実際のSQL例と内部メカニズムで徹底解説。MVCC(マルチバージョン同時実行制御)とロック機構の組み合わせによって、各隔離レベルがどのように問題を回避するかを明らかにします。
ダーティリードが許容されない典型的なケース
ダーティリードは未コミットのデータを読むため、すべての業務ロジックで避けるべきです。
-- 転送処理中の残高確認(危険な例)
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- トランザクションA: 100円転送中(未コミット)
UPDATE accounts SET amount = amount - 100 WHERE id = 'userA';
UPDATE accounts SET amount = amount + 100 WHERE id = 'userB';
-- トランザクションB: 残高照会(ダーティリード発生)
SELECT amount FROM accounts WHERE id = 'userA'; -- 900円と表示される
-- トランザクションAがROLLBACK → 実際の残高は1000円
-- ユーザーは誤った情報に基づいて行動してしまう
並行問題の解決アプローチ
| 問題 | 解決隔離レベル | 主な仕組み |
|---|---|---|
| ダーティリード | READ COMMITTED以上 | MVCCによる未コミット排除 |
| ノンリピータブルリード | REPEATABLE READ以上 | 固定Read View |
| ファントムリード | REPEATABLE READ + 間隙ロック | Next-Key Lock |
REPEATABLE READでの可視性の違い
通常のSELECTとFOR UPDATEでは挙動が異なります。
-- トランザクションB開始
START TRANSACTION;
SELECT balance FROM users WHERE id = 1; -- 結果: 1000(スナップショット)
-- 別トランザクションでUPDATE & COMMIT後
SELECT balance FROM users WHERE id = 1; -- 依然として1000(MVCC)
SELECT balance FROM users WHERE id = 1 FOR UPDATE; -- 900(最新値)
ファントムリード対策の二重構造
- スナップショット読み取り:MVCCにより新規挿入レコードを不可視化
- 現在読み取り:Next-Key Lockで挿入自体をブロック
-- 間隙ロックの例
START TRANSACTION;
SELECT * FROM products WHERE price BETWEEN 1000 AND 5000 FOR UPDATE;
-- この範囲へのINSERTは他のトランザクションでブロックされる
SERIALIZABLEの動作原理
すべてのSELECTに自動的に共有ロックを付与し、完全な直列実行を強制します。
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- 通常のSELECTでもLOCK IN SHARE MODE相当の動作
SELECT * FROM inventory WHERE item_id = 123;
-- 他のトランザクションのUPDATE/DELETEは待機状態になる
MVCCの核心コンポーネント
- 隠しフィールド:DB_TRX_ID(最終更新トランザクションID)、DB_ROLL_PTR(UNDOログへのポインタ)
- バージョンチェーン:UNDOログを通じた過去バージョンの連鎖
- Read View:m_ids(アクティブトランザクションリスト)、min_trx_id/max_trx_id
UPDATE文の原子性に関する誤解
単一UPDATE文は原子的ですが、複数文の組み合わせでは競合が発生します。
-- 危険なパターン(非原子的)
SELECT current_balance INTO @bal FROM accounts WHERE id = 1;
UPDATE accounts SET balance = @bal - 100 WHERE id = 1;
-- 安全なパターン(原子的)
UPDATE accounts
SET balance = balance - 100
WHERE id = 1 AND balance >= 100;
隔離レベル選択ガイド
| レベル | 推奨用途 | パフォーマンス |
|---|---|---|
| READ COMMITTED | 集計クエリ、分析処理 | ★★★★☆ |
| REPEATABLE READ | 標準的な業務アプリ(デフォルト) | ★★★☆☆ |
| SERIALIZABLE | 極めて厳密な整合性が必要な特殊ケース | ★☆☆☆☆ |