一个可以帮助大多数死锁的简单技巧是以特定顺序对操作进行排序。
当两个事务试图以相反的顺序锁定两个锁时,您会遇到死锁,即:
>连接1:锁定键(1),锁定键(2);
>连接2:锁定键(2),锁定键(1);
如果两者同时运行,则连接1将锁定键(1),连接2将锁定键(2),并且每个连接将等待另一个释放键 – >僵局。
现在,如果您更改了查询,以便连接将按相同的顺序锁定键,即:
>连接1:锁定键(1),锁定键(2);
>连接2:锁定键(1),锁定键(2);
它将不可能得到一个死锁。
所以这是我的建议:
>确保没有其他查询,一次锁定访问多个键,除了delete语句。如果你这样做(我怀疑你这样做),请按照升序排列它们的(WHERE in)(k1,k2,… kn)。
>修复您的删除语句以升序工作:
更改
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次)。