我有一个在数据库中进行一些操作的服务,在我尝试并行发出两个请求之前,一切都正常工作。
下面看sql调试日志:
Executing (2c4cb493-7090-4a83-942a-1b3078a96a7b): START TRANSACTION;
Executing (f49986af-9741-4f20-94ba-0644fbafea05): START TRANSACTION;
Executing (2c4cb493-7090-4a83-942a-1b3078a96a7b): INSERT INTO `history` (`id`,`value`) VALUES (DEFAULT,'value data');
Executing (f49986af-9741-4f20-94ba-0644fbafea05): INSERT INTO `history` (`id`,`value`) VALUES (DEFAULT,'value data');
Executing (2c4cb493-7090-4a83-942a-1b3078a96a7b): UPDATE `table_2` SET `count`=count + 1 WHERE `id` = 1
Executing (f49986af-9741-4f20-94ba-0644fbafea05): UPDATE `table_2` SET `count`=count + 1 WHERE `id` = 1
Executing (2c4cb493-7090-4a83-942a-1b3078a96a7b): COMMIT;
Executing (f49986af-9741-4f20-94ba-0644fbafea05): ROLLBACK;
Deadlock found when trying to get lock; try restarting transaction
我不明白为什么一个事务不等待另一个事务结束,而是抛出死锁异常?
谢谢。
数据库旨在支持多个并发用户。“等待其他交易完成”与该要求互斥。支持多个并发用户的能力是您使用数据库而不是平面文件的原因。
您必须相应地设计您的算法。
在您的示例中,您想序列化此过程。(注意:序列化与设置配置参数相同
SLOW=TRUE
)您可以通过首先放置行锁来序列化此过程
Table_2
。在MySQL(和其他 RDBMS)中,您可以通过SELECT ... FOR UPDATE
在事务开始时使用语法来做到这一点。该过程应如下所示:
有时 InnoDB 采取悲观的方法。做“正确”的事情可能非常复杂,以至于不值得这样做。忍受它。
当遇到死锁时,重新运行事务。这通常是“正确”的解决方案。这只是处理事务的一部分。