MeWrite Docs

MySQL: Deadlock found when trying to get lock

MySQLデッドロックエラーの解決方法

概要

2つ以上のトランザクションが互いにロックを待ち、進行できない状態です。

エラーメッセージ

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

原因

  1. ロック順序の不一致: トランザクション間で異なる順序でロック
  2. 長時間トランザクション: ロック保持時間が長い
  3. ギャップロック: InnoDB特有のロック
  4. インデックス不足: テーブルスキャンによる広範囲ロック

解決策

1. 一貫したロック順序

1
2
3
4
5
-- トランザクションAとBで同じ順序
BEGIN;
SELECT * FROM accounts WHERE id = 1 FOR UPDATE;
SELECT * FROM accounts WHERE id = 2 FOR UPDATE;
COMMIT;

2. リトライロジック

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
async function executeWithRetry(fn, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.code === 'ER_LOCK_DEADLOCK' && i < maxRetries - 1) {
        await sleep(100 * Math.pow(2, i));
        continue;
      }
      throw error;
    }
  }
}

3. トランザクション分離レベル

1
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

4. デッドロック情報確認

1
SHOW ENGINE INNODB STATUS;

よくある間違い

  • 不要なFOR UPDATEの使用
  • トランザクション内での外部API呼び出し

MySQL の他のエラー

最終更新: 2025-12-09