如何排查mysql并发插入导致的死锁问题

分类:编程技术 时间:2024-02-20 15:44 浏览:0 评论:0
0
小编给大家分享一下如何排查MySQL并发插入导致的死锁问题。相信大多数人对此还不是很了解,所以分享这篇文章供大家参考。希望您读完这篇文章后能有所收获。我们一起来了解一下吧!

我挂了VPN来排查问题,但当时没有找到原因

上班后发现是客户端的bug。我应该发送一个请求,但是却发送了大量的请求。应用层面没有幂等设计,所以所有请求都落到数据库层面。
数据库是一个进程

环境
MySQL 5.6.14
事务隔离级别读提交

导致问题的逻辑是大致如下:

CREATE TABLE t1 (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;

现在假设三个会话执行按顺序执行以下操作:

会话 1:

START TRANSACTION;插入 t1 值(1);

会话 2:

开始事务;插入 t1 值(1);

会话 3:

START TRANSACTION;INSERT INTO t1 VALUES(1);

会话 1:

ROLLBACK;

会话 1 的第一个操作获取一个该行的独占锁。会话 2 和 3 的操作都会导致重复键错误,并且它们都请求该行的共享锁。当会话 1 回滚时,它会释放该行上的排他锁,并且会话 2 和 3 的排队共享锁请求将被授予。此时,会话 2 和会话 3 发生死锁:由于对方持有共享锁,双方都无法获取该行的独占锁。

如果表中已经包含具有键值的行,也会出现类似的情况1和三个会话按顺序执行以下操作:

会话1:

START TRANSACTION;DELETE FROM t1 WHERE i = 1;

会话2:< /p>

开始事务;插入 t1 VALUES(1);

会话3:

START TRANSACTION;INSERT INTO t1 VALUES(1);

Session 1:

COMMIT;

第一个操作会话 1 获取该行的独占锁。会话 2 和 3 的操作都会导致重复键错误,并且它们都请求该行的共享锁。当会话 1 提交时,它会释放其对该行的独占锁,并且会话 2 和 3 的排队共享锁请求将被授予。此时,会话 2 和会话 3 发生死锁:由于对方持有共享锁,双方都无法获取该行的独占锁。


可以看到,在插入时,记录会被加排他锁和插入意向锁。
在并发的情况下,如果记录已经加了排他锁,则会尝试对该记录加共享锁。
如果并发线程超过三个,
第一个线程有排他锁,第二个和第三个线程,看到记录有ex独占锁,尝试对记录应用共享锁。
一旦第一个线程回滚,第二个和第三个线程将在拥有共享锁的同时申请排它锁。

注意,如果第一个线程提交,第二个和第三个线程会报重复主键错误,但此时第二个和第三个线程会报主键重复错误。线程仍然拥有该记录的共享锁。第二、第三个线程必须回滚。否则,自己拥有的共享锁不会被释放。

回到原来的问题。
三个线程同时插入award_free_firecracker_watch_common表,其中一个线程成功获取排它锁,则其他两个线程共享锁。
当获取排它锁的线程提交时,共享锁的两个线程最后一步更新了award_free_firecracker_watch_common表,导致死锁。
他们都申请了独家LO

以上是《如何排查mysql并发插入导致的死锁问题》》感谢您阅读本文全部内容!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果您想了解更多知识,请关注行业资讯频道!

1. 本站所有资源来源于用户上传或网络,仅作为参考研究使用,如有侵权请邮件联系站长!
2. 本站积分货币获取途径以及用途的解读,想在本站混的好,请务必认真阅读!
3. 本站强烈打击盗版/破解等有损他人权益和违法作为,请各位会员支持正版!
4. 编程技术 > 如何排查mysql并发插入导致的死锁问题

用户评论