一个可以解决大多数僵局的简单技巧就是按特定顺序对操作进行排序。
当两个事务试图以相反的顺序锁定两个锁时,会出现死锁,即:
- 连接1:锁定键(1),锁定键(2);
- 连接2:锁定键(2),锁定键(1);
如果两个都同时运行,则连接1将锁定键(1),连接2将锁定键(2),每个连接将等待另一个释放键->死锁。
现在,如果您更改查询以使连接以相同的顺序锁定键,即:
- 连接1:锁定键(1),锁定键(2);
- 连接2:锁键( 1 ),锁键( 2 );
陷入僵局是不可能的。
所以这是我的建议:
确保除了delete语句外,没有其他一次锁定访问多个键的查询。如果您这样做(我怀疑您这样做),请按升序在(k1,k2,.. kn)中订购他们的WHERe。
修复您的delete语句以升序工作:
更改
DELETE FROM onlineusers WHERe datetime <= now() - INTERVAL 900 SECOND
至
DELETe FROM onlineusers WHERe id IN (SELECt id FROM onlineusers WHERe datetime <= now() - INTERVAL 900 SECOND order by id) u;
要记住的另一件事是,mysql文档建议在发生死锁的情况下,客户端应自动重试。您可以将此逻辑添加到客户代码中。(说,在放弃之前,3个重试此特定错误)。



