推奨学習: mysql ビデオ チュートリアル
ロックを使用する場合、注意が必要な問題があります。排他ロックには相互に排他的な特性があることがわかっています。トランザクションまたはスレッドがロックを保持すると、他のスレッドがロックを取得できなくなり、ブロック待ちが発生し、ループ内で待機するとデッドロックが発生する可能性があります。
この問題をいくつかの側面から分析する必要があります。1 つはロックが解放されない理由、2 つ目はロックがブロックされた場合の対処方法、3 つ目はデッドロックがどのように発生するか、およびその回避方法です。
レビュー: ロックはいつ解放されますか?
トランザクションが終了します (コミット、ロールバック);
クライアント接続が切断されます。
トランザクションがロックを解放していない場合、他のトランザクションはどのくらいブロックされますか?永久に待機しますか?
そうである場合、同時アクセスが比較的多いとき、トランザクション数が多い場合必要なロックをすぐに取得できないためブロックされており、ハングすると多くのコンピュータ リソースが占有され、重大なパフォーマンス上の問題が発生し、さらにはデータベース全体に影響を及ぼします。
オンラインでのこの間違いが怖いですか?
[Err] 1205 - Lock wait timeout exceeded; try restarting transaction
MySQL には、ロックを取得するまでの待ち時間を制御するパラメータがあり、デフォルトは 50 秒です。
show VARIABLES like "innodb_lock_wait_timeout";
デッドロックの場合、いくら待ってもロックが取得できません。この場合、50秒待つ必要がありますか?その50秒は無駄ではありませんか?
デモンストレーション、2 つのセッションを開く:
タイムラインの撤回を容易にします。ここでは写真が使用されています。興味のある方は真似してください。
栗 1:
## 栗 2:
最初のトランザクションでは、デッドロックが検出され、すぐに終了しました。2 番目のトランザクションは、50 秒も待たずにロックを取得しました:
[Err] 1213 - Deadlock found when trying to get lock; try restarting transactionなぜ直接検出できるのでしょうか?これは、特定の条件を満たしている必要があるためです。私たちプログラマーにとって、明確な条件があるということは、判断できることを意味するため、デッドロックが発生した場合、通常、InnoDB はアルゴリズム (待機グラフ) を通じて自動的にそれを検出できます。
それでは、デッドロックが発生するにはどのような条件を満たす必要があるのでしょうか? ロック自体は相互に排他的であるため、デッドロックが発生する条件は次のとおりです:
トニーが誰かの髪を切っているとき、彼に立ち止まって髪を切るように頼むことはできません。これを
無理に奪うことはできません
トニーのクライアントがケルビンに言った場合: あなたが洗ってくれないなら、どうやって髪を切ることができますか? ケルビンのクライアントがトニーに言った場合: あなたが髪を切らないなら、どうやって髪を洗えますか? これは呼ばれます 待機ループを形成します。
。
実際にはデッドロックが発生する状況は数多くありますが、それらはすべて上記の 3 つの条件を満たしています。 これは、テーブル ロックのリソースが一度にすべて取得されるため
テーブル ロックによってデッドロックが発生しない理由でもあります。
ロックが解放されていない場合、大量のブロッキングやデッドロックが発生し、システムのスループットが低下する可能性があるため、どのトランザクションがロックを保持しているかを確認する必要があります。 ロック情報の表示 (ログ)
show status like 'innodb_row_lock_%';
##lnnodb_row_lock_current_waits: 現在待機しているロックの数;
lnnodb_row_lock_time: システムの起動から現在のロックまでの合計時間 (ミリ秒単位); Innodb_row_lock_time_avg: 毎回の待機に費やされる平均時間。
Innodb_row_lock_time_max: システムの起動から現在までの最長待機時間;lnnodb_row_lock_waits: システムの起動から現在までの待機の合計数。
SHOW コマンドは概要情報です。 InnoDB には、トランザクションとロックを分析するための 3 つのテーブルも用意されています:select * from information_schema.INNODB_TRX; --当前运行的所有事务﹐还有具体的语句
select* from information_schema.INNODB_LOCKS; --当前出现的锁
select * from information_schema.INNODB_LOCK_WAITS; --锁等待的对应关系
更加详细的锁信息,开启标准监控和锁监控:
额外的监控肯定会消耗额外的性能
set GLOBAL innodb_status_output=ON; set GLOBAL innodb_status_output_locks=ON;
通过分析锁日志,找出持有锁的事务之后呢?
如果一个事务长时间持有锁不释放,可以kill事务对应的线程ID,也就是INNODB_TRX表中的trx_mysql_thread_id,例如执行kill 4,kill 7, kill 8。
当然,死锁的问题不能每次都靠kill线程来解决,这是治标不治本的行为。我们应该尽量在应用端,也就是在编码的过程中避免。
有哪些可以避免死锁的方法呢?
推荐学习:mysql视频教程
以上がMySQLのデッドロックの使い方と検出・回避方法を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。