MySQLトランザクションの並行処理問題:ダーティリード、ノンリピータブルリード、ファントムリードの解決策

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の核心コンポーネント

  1. 隠しフィールド:DB_TRX_ID(最終更新トランザクションID)、DB_ROLL_PTR(UNDOログへのポインタ)
  2. バージョンチェーン:UNDOログを通じた過去バージョンの連鎖
  3. 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極めて厳密な整合性が必要な特殊ケース★☆☆☆☆

タグ: MySQL トランザクション mvcc 隔離レベル 並行制御

6月6日 16:07 投稿