MySQL ERROR 1213 (Deadlock Found When Trying to Get Lock) の解決方法

intermediate🗄️ MySQL2026-04-12| MySQL 5.7+、MySQL 8.0+、MariaDB、Linux (Ubuntu/CentOS)、Docker、AWS RDS、Google Cloud SQL

Error Message

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
#mysql#デッドロック#データベース最適化#innodb#sqlパフォーマンス

エラーメッセージ

トラフィックの多いアプリケーションでは、データベース操作が突然失敗し、次の特定のメッセージが表示されることがあります。

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

デッドロックとは一体何か?

デッドロックとは、本質的にデータベースプロセス間での「にらみ合い(メキシカン・スタンドオフ)」の状態を指します。これは、トランザクションAが「行1」のロックを保持しながら「行2」を要求し、同時にトランザクションBが「行2」のロックを保持しながら「行1」を要求する場合に発生します。どちらも先に進むことができません。

MySQLは単に永久にハングアップするわけではありません。この膠着状態を検出し、一方のトランザクション(「犠牲者」)を強制終了させることで、もう一方が処理を完了できるようにします。これはInnoDBエンジンのバグではありません。データベースの応答性を維持するための保護策ですが、デッドロックが頻発する場合は、通常、アプリケーションロジックに欠陥があることを示しています。

ステップバイステップの解決策

1. アプリケーションレベルでのリトライロジックの実装

エラーメッセージは文字通り、*「トランザクションの再試行」*を促しています。同時実行性の高いシステムでは、デッドロックは避けられない場合があります。コードはこのエラーを想定し、短い一時停止の後に操作を再試行する必要があります。

以下は、エクスポネンシャル・バックオフ(指数関数的後退)を使用した実用的なリトライパターンの例です(Node.js/Pythonスタイル):

max_retries = 3
retries = 0

while retries  100` をロックすることは、`WHERE id IN (101, 102, 103)` をロックするよりもはるかに危険です。
  - **バッチ処理:** 10,000行を更新する必要がある場合は、100行または500行ずつのチャンクに分けて行ってください。これにより、ロックがより速く解放され、単一の巨大なトランザクションがシステム全体をブロックするのを防ぐことができます。

Related Error Notes