最近、データベースのデッドロックの問題に遭遇しました。解決プロセスの記録をここに示します。
システム内の mysql にはいくつかのイベントがあり、統計データなどの関数のために数分ごとに実行され、このイベントはテーブルに追加されます。中のデータ。 一般的な内容: b から必須フィールドを選択してから a に置き換えます。 一般的な構造は次のとおりです。select from b で必要なフィールドはここでの略称です。実際には非常に複雑で、多くのテーブル結合操作が含まれます。データ量が多い場合、このイベントは 1 分ごとに実行されます。 1分では終わらないかもしれません。次に、テーブル b に対して他のさまざまな挿入および更新操作を実行します。この時点で、バックエンド ログにデッドロック エラーと待機ロック タイムアウト エラーが頻繁に記録されることがわかります。 最終テストでは、イベントをオフにすると問題が解消されることがわかり、問題はこのイベントにあることが基本的に確認されました。
実際、最も時間がかかるのは、それがイベントの問題であることを見つけることです。データをクエリして問題を解決するのにそれほど時間はかかりません。 。
1. まず、バックエンド ログのエラー情報に基づいて、デッドロックの原因となったテーブルと、ロック タイムアウトを待機したテーブルを特定します。次に、これらのテーブル名と出力された SQL に基づいて、デッドロックが発生した場所を見つけます。問題の原因はイベント
3 の SQL であることが大まかに確認されました。アイデアを再度検証してください。イベントをオフにした後、ログにロックの問題がないことがわかりました
4。確認してください。イベント内のステートメントを調べてみると、おそらく a from select requiredfields from b に置き換えられていることがわかります;
INSERT INTO T SELECT ... FROM S WHERE ... sets an exclusive index record lock (without a gap lock) on each row inserted into T. If the transaction isolation level is READ COMMITTED, or innodb_locks_unsafe_for_binlog is enabled and the transaction isolation level is not SERIALIZABLE, InnoDB does the search on S as a consistent read (no locks). Otherwise, InnoDB sets shared next-key locks on rows from S. InnoDB has to set locks in the latter case: During roll-forward recovery using a statement-based binary log, every SQL statement must be executed in exactly the same way it was done originally.复制代码つまり、INSERT INTO T SELECT ... FROM S WHERE ... この状況は最初に何よりも、T テーブルにどのレコード ロック (行レベルのロック) があるかがわかり、ギャップ ロックがありません。 テーブル S の場合、ロックが発生しない 2 つの状況があります:
1. トランザクション分離レベルが READ COMMITTED の場合
2. または、innodb_locks_unsafe_for_binlog が有効で、トランザクション分離レベルが SERIALIZABLE
1. パラメータ innodb_locks_unsafe_for_binlog は静的です。有効にするには、innodb_locks_unsafe_for_binlog = 1 行を my.cnf に追加し、データベースを再起動する必要があります。
mysql に次のコマンドを入力します:
show variables like "%innodb_locks_unsafe_for_binlog%"复制代码ON であることが確認できれば、正常にオンになっています。
2. トランザクションの分離レベルは比較的きめ細かく、特定のセッションに対して設定できます。セッションごとに異なる分離レベルを使用でき、このパラメーターは動的であり、mysql コマンド ラインで直接変更できます。
3. mysql5.7 のパラメータの導入では、パラメータ innodb_locks_unsafe_for_binlog が後続の mysql バージョンで廃止されると述べています。これは本当で、mysql8.0 のパラメータの詳細説明を確認したところ、このパラメータは存在しないことがわかりました。
#その他の関連する無料学習の推奨事項:mysql チュートリアル(ビデオ)
以上がmysql insert into...select のロックの問題を理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。