为啥这个事务会产生死锁?
Posted
技术标签:
【中文标题】为啥这个事务会产生死锁?【英文标题】:Why does this transaction produce a deadlock?为什么这个事务会产生死锁? 【发布时间】:2018-08-07 12:46:51 【问题描述】:我的应用程序使用主-主 Galera 复制设置在 Maria DB 上运行。
该应用程序可以处理死锁,但我一直在努力尽量减少在填满我的日志文件时发生的死锁。仍然有一个事务经常出现死锁,我不知道如何避免它。
该过程从一个表中删除一条记录,对其他表执行一些操作,然后最后将一条记录插入到原始表中。 交易大致如下所示:
1. DELETE FROM table_a WHERE `id` = 'Foo'
2. REPLACE INTO table_b ( ... )
3. UPDATE table_c SET ....
4. INSERT INTO table_a (id,...) VALUES ('Bar',...)
尽管重试事务会修复它,但最终插入经常会出现死锁。这种模式导致死锁的原因是什么?我能做些什么来减少这种情况的发生?
【问题讨论】:
请在innodb状态监视器中查看mariadb提供的关于死锁的信息。它告诉您哪些事务的哪些语句导致死锁以及这些语句设置的锁。 我已经启用了 innodb_status_output 和 innodb_status_output_locks 虽然 log_error 中配置的文件不存在。我会看看下一个死锁发生时会发生什么SHOW ENGINE INNODB STATUS;
是否说 INSERT
与 INSERT
冲突?
【参考方案1】:
问题:您正在写入的节点中是否存在“死锁”?或者直到COMMIT
才会出现死锁;也就是说,在尝试跨集群进行协调时?
如果在写入节点上...
尽快在事务中做
SELECT id FROM table_a WHERE ... FOR UPDATE;
表示您将在第 4 步中插入哪些行。
另外,考虑将REPLACE
更改为等效的INSERT .. ON DUPLICATE KEY UPDATE ..
。我不知道它是否会直接帮助解决僵局,但至少它(可能)更有效。
如果在集群上...
您是否触摸了许多不同的行?您是否使用循环法来选择要写入哪个节点?
无论如何,加快交易速度都会有所帮助。有什么可以从交易中拉出来的。有一些想法:
规范化通常可以在它自己的事务中完成。 如果您在事务中有“如果”,那么事先进行试探性测试可能是值得的。 (但您可能需要在事务中保留“如果”。)【讨论】:
感谢您的回复。我将尝试从应用程序中记录SHOW ENGINE INNODB STATUS
。至于节点选择。是师父。每个应用程序服务器都读取和写入其自己的配对数据库节点。我会接受你关于 ON DUPLICATE KEY 的建议。谢谢你的想法。我想要效率,我会密切关注它是否会减少死锁。
我希望你只写给这对大师中的一个。
Galera 集群允许写入任何节点。
加莱拉-好的。我被“master-master”误导了。
啊是的。它称自己为多主 :) 无论如何,我使用的是 ON DUPLICATE... 而不是替换,并且会看到会发生什么。以上是关于为啥这个事务会产生死锁?的主要内容,如果未能解决你的问题,请参考以下文章
事务 ( 进程 ID 60) 与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品。请重新运行 该事务。