0

在我的数据库中运行某个查询时,我经常收到以下错误(所有表都使用 InnoDB 存储引擎):“尝试获取锁定时发现死锁;尝试重新启动事务”

查询是DELETE FROM sessions WHERE userid != 0 AND lastactivity < 1289594761 AND admin = 1 AND userid NOT IN (SELECT userid FROM users WHERE (userflags & 1048576))

当我将 NOT IN 部分添加到 WHERE 语句中时,错误开始发生。为什么这会引起问题,我能做些什么来防止这种情况发生?

4

2 回答 2

2

一个简单的解决方案是将其分成两个连续的查询。IE,:

SELECT userid into #tmptable FROM users WHERE (userflags & 1048576);

从会话中删除 userid != 0 AND lastactivity < 1289594761 AND admin = 1 AND userid NOT IN(从 #tmptable 中选择 userid);

这样,您就可以使用第二个表中的值的本地会话副本,并且不会导致读取锁定。但是,这只是一个快速而肮脏的解决方案。更好的解决方案是分析涉及这两个表的所有活动的事务锁定设置并重写查询,如果您将定期重用它。

于 2010-11-12T21:14:03.313 回答
2

大概您会更频繁地收到错误,因为现在这是一个慢得多的查询。

&op on使userflags子查询不可索引。标志词通常不是很好的模式设计,因为它们需要计算而不是索引。如果您经常进行位测试查询,那么小数据类型(例如 )的单独列TINYINT可能会更好。

如果您的模式按其看起来的方式工作,您应该能够使用简单的 JOIN 来执行此操作,它通常比子查询执行得更好:

DELETE sessions
FROM sessions
JOIN users ON users.userid=sessions.userid
WHERE sessions.lastactivity<1289594761 AND admin=1
AND (users.userflags&1048576)=0

(joins onDELETE是 MySQL 中的非 ANSI SQL 扩展。)

于 2010-11-12T21:27:32.933 回答