ホームページ  >  記事  >  データベース  >  MySQL のデッドロック問題を解決するコードの詳細な紹介

MySQL のデッドロック問題を解決するコードの詳細な紹介

黄舟
黄舟オリジナル
2017-03-04 14:47:351557ブラウズ

MySQL のデッドロック問題が解決されました

1. 環境

  • CentOS、MySQL 5.6.21-70、JPA

  • 問題のシナリオ: システムには、スケジュールされたデータ ステータスのバッチ更新操作があり、毎回数千のレコードが更新されます。 , テーブルの合計レコード数は約500Wです。

2. エラーログ

2017-2-25 17:38:41 org.hibernate.util.JDBCExceptionReporter logExceptions
严重: Lock wait timeout exceeded; try restarting transaction
2017-2-25 17:39:05 org.hibernate.util.JDBCExceptionReporter logExceptions
警告: SQL Error: 1213, SQLState: 40001
2017-2-25 17:39:05 org.hibernate.util.JDBCExceptionReporter logExceptions
严重: Deadlock found when trying to get lock; try restarting transaction

3. トラブルシューティング

Check InnoDB status for locks
mysql> SHOW ENGINE InnoDB STATUS;

Check MySQL open tables
mysql> SHOW OPEN TABLES WHERE In_use > 0;

Check pending InnoDB transactions
mysql> SELECT * FROM `information_schema`.`innodb_trx` ORDER BY `trx_started`; 

Check lock dependency - what blocks what
mysql> SELECT * FROM `information_schema`.`innodb_locks`;

のようなステートメントを実行すると問題が発生することが分かりました:

update t_task_tel set state='iok', update_date='2017-02-27 11:03:02' where tel_id=66042 and task_id=350199;

4. 関連情報を検索した結果、 MySQL InnoDB には必ずしも行レベルのロックがあるわけではないことが判明しました。

関連する参考資料の断片は以下のとおりです:

MySQL InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析
http://www.php.cn/

4、锁选择
1)、如果更新条件没有走索引,例如执行”update from t1 set v2=0 where v2=5;” ,此时会进行全表扫描,扫表的时候,要阻止其他任何的更新操作,所以上升为表锁。
2)、如果更新条件为索引字段,但是并非唯一索引(包括主键索引),例如执行“update from t1 set v2=0 where v1=9;” 
那么此时更新会使用Next-Key Lock。使用Next-Key Lock的原因:
a)、首先要保证在符合条件的记录上加上排他锁,会锁定当前非唯一索引和对应的主键索引的值;
b)、还要保证锁定的区间不能插入新的数据。
3)、如果更新条件为唯一索引,则使用Record Lock(记录锁)。
 
InnoDB根据唯一索引,找到相应记录,将主键索引值和唯一索引值加上记录锁。但不使用Gap Lock(间隙锁)。
MySQL InnoDB 锁表与锁行
http://www.php.cn/

由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,否则MySQL将会执行Table Lock (将整个资料表单给锁住)。

分析の結論によれば、_task_tel テーブルを更新する際に、Tel_id と task_id が Where 条件で UNIQUE (ユニークなインデックス) を確立しなかった理由が推測されます。解決策

この分析によると、これは、tel_id と task_id の 2 つのフィールドを使用して UNIQUE (固有のインデックス) を確立することで解決されます。 (テーブル内の大量のデータがオンライン ビジネスに影響を及ぼさないように、最初にクエリを実行してから主キー ID に基づいて更新することもできます)。

この方法で解決した後、問題は再発しませんでした。

あなたの問題が私が遭遇したものと似ている場合は、それに応じて解決してみてください。

上記は、MySQL のデッドロック問題を解決するためのコードの詳細な紹介です。その他の関連コンテンツについては、PHP 中国語 Web サイト (www.php.cn) に注目してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。