在我的应用程序中,我有两个不时发生的查询(来自不同的进程),这会导致死锁。
查询#1
UPDATE tblA, tblB SET tblA.varcharfield=tblB.varcharfield WHERE tblA.varcharfield IS NULL AND [a few other conditions];
查询#2
INSERT INTO tmp_tbl SELECT * FROM tblA WHERE [various conditions];
这两个查询都需要很长时间,因为这些表有数百万行。当查询#2正在运行时,似乎tblA
被锁定在模式S
中。查询#1似乎需要X
锁定。由于这与S
锁不兼容,因此查询#1等待最多30秒,此时我遇到了死锁:
序列化失败:1213尝试锁定时发现死锁;尝试重新启动交易
根据我所读的in the documentation,我想我有几个选择:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
禁用锁定。我不明白这个含义,我担心数据损坏。我目前在我的应用程序中不使用显式事务,但我可能在将来的某个时候使用。我该怎么办?我应该考虑其他方法吗?
编辑:我已尝试在varcharfield上设置索引,但该表仍处于锁定状态。我怀疑当UPDATE
部分实际执行时会发生锁定。还有其他建议可以解决这个问题吗?
答案 0 :(得分:1)
一个。如果我们假设索引varcharField
占用了大量磁盘空间并且添加新列不会让您感到困难,我可以建议以下方法:
varcharField
为空,则此字段将存储0,否则为1 - 希望它有所帮助。
答案 1 :(得分:1)
您只能索引varchar列的一部分,它仍然可以工作,并且需要的空间更少。只需指定索引大小:
CREATE INDEX someindex ON sometable (varcharcolumn(32))
答案 2 :(得分:0)
我能够通过在两个查询周围添加显式LOCK TABLE
语句来解决问题。事实证明这是一个更好的解决方案,因为每个查询都会影响很多记录,而且这两个记录都是后台进程。他们现在互相等待。
http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html
虽然这对我来说是一个不错的解决方案,但显然不是每个人的答案。使用WRITE
锁定意味着您无法READ
。只有READ
锁定允许其他人READ
。