我在中高负荷情况下遇到死锁。以下是详细信息。
的MySQL-5.5.21-55
引擎:InnoDB
表:订单
# Field, Type, Null, Key, Default, Extra
id, bigint(20) unsigned, NO, PRI, , auto_increment
sno, varchar(32), NO, MUL, ,
misc1, int, NO, , 0,
表:OrderItem
# Field, Type, Null, Key, Default, Extra
id, bigint(20) unsigned, NO, PRI, , auto_increment
order_id, bigint(20), YES, MUL, ,
f1, varchar(50), YES, , ,
f2, varchar(100), YES, , ,
misc2, int, NO, , 0,
USECASE:
多个线程将执行此操作;但他们会在不同的记录集上工作。我一次在25个订单上运行
我尝试了什么:
上述所有方法都导致了一些或其他时间的deat锁定。 没有其他线程或进程在这些表上工作。
观察:
通过以下链接
发现更新/删除多条记录会导致MySQL在REPEATABLE_READ隔离级别(这是默认值)获取 Next Key 锁定。在我看来,这会导致问题。
感谢你能否就解决这个问题提供一些指导。
答案 0 :(得分:1)
既然你没有提到它,我会试一试,你试过“FOR UPDATE”吗?
将连接自动提交设置为false。
在程序开头,使用它来锁定所有相关数据。
SELECT o.* , oi.*
FROM order o
INNER JOIN orderitem oi ON (o.id=oi.order_id)
WHERE o.id = <order id to update>
FOR UPDATE;
然后你可以对这些条目做任何你想做的事情。 然后提交。
编辑:我认为问题的根本原因是多线程(显然),我在想如果从等式中删除该元素会更好。
想象一下你有多个接收器接收请求的系统。那些接收器只会做类似的事情:
//select to check if there is a existing record(no need to lock), if no, return fail as response
SELECT o.* , oi.*
FROM order o
INNER JOIN orderitem oi ON (o.id=oi.order_id)
WHERE o.sno = <sno to update>;
insert into request_buffer (request_id, sno, new_order_item,create_date .......)
values
(1, abc , orderitem1......);
//return success after inserting buffer.
你有一个单独的单线程程序,它汇集了这个表并处理那些缓冲区条目。
在这种情况下,它将从DB更新过程中分离多线程元素。我不确定传入请求的数量,但我认为如果您在每个周期/查询中处理更多请求,那么性能不会有太大差异吗?
答案 1 :(得分:0)
最后,(也许是一种解决方法,与@ JackyCheng的建议一致),Im,
总体而言,25个订单的交易执行时间仍然低于30毫秒。