InnoDBは2つの仕組みを組み合わせます。MVCCにより、通常のSELECTはロックせずに一貫したスナップショットを読めるため、読み手が書き手をブロックすることはありません。ロックは書き込みを保護します。UPDATE/DELETE/は行ロックを取得し、InnoDBはさらに(行+その前のギャップ)を用いて、REPEATABLE READ下でphantomを防ぎます。
InnoDBは2つの仕組みを組み合わせます。MVCCにより、通常のSELECTはロックせずに一貫したスナップショットを読めるため、読み手が書き手をブロックすることはありません。ロックは書き込みを保護します。UPDATE/DELETE/は行ロックを取得し、InnoDBはさらに(行+その前のギャップ)を用いて、REPEATABLE READ下でphantomを防ぎます。
SELECT ... FOR UPDATEデッドロックは循環です。T1はロックAを保持してBを求め、T2はBを保持してAを求めます。どちらも先へ進めません。InnoDBは循環を検出し、一方のトランザクションをロールバックします(コストの低い方を犠牲にする)。error 1213を返し、もう一方が完了します。
-- T1 -- T2
BEGIN; BEGIN;
UPDATE acct SET bal=bal-1 UPDATE acct SET bal=bal-1
WHERE id=1; -- locks row 1 WHERE id=2; -- locks row 2
UPDATE acct SET bal=bal+1 UPDATE acct SET bal=bal+1
WHERE id=2; -- waits for T2 WHERE id=1; -- waits for T1 => DEADLOCK
-- ERROR 1213: Deadlock found; transaction rolled back
WHEREにインデックスを張り、InnoDBが範囲や(インデックスなしで)実質的にスキャンした全行ではなく、特定の行だけをロックするようにする。SHOW ENGINE INNODB STATUS\G -- LATEST DETECTED DEADLOCK explains who waited on what
実際の並行処理下では、ロック競合とデッドロックが、スケールするデータベースと停滞するデータベースの分かれ目になります。読み手はMVCCを使う(だからブロックしない)こと、デッドロックは想定内でリトライ可能であること、そして一貫したロック順序がその大半を防ぐことを知っていることは、まさにシニアのオンコール業務が求めるものです。
ジュニアからシニアまで、詳細な回答付きのIT面接質問ライブラリ。
寄付する