【发布时间】:2011-10-27 02:12:02
【问题描述】:
在我的应用程序中,我有两个不时发生的查询(来自不同的进程),这会导致死锁。
查询 #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,我认为我有几个选择:
- 在 tblA.varcharfield 上设置索引。不幸的是,我认为这将需要一个非常大的索引来存储 varchar(512) 的字段。 (请参阅下面的编辑...这不起作用。)
- 使用
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;禁用锁定。我不明白这意味着什么,并且担心数据损坏。我目前没有在我的应用程序中使用显式事务,但我可能会在未来的某个时候使用。 - 将耗时的查询拆分成小块,以便它们可以在 MySQL 中排队和运行,而不会达到 30 秒超时。这并不能真正解决问题的核心,而且我担心当我的数据库服务器繁忙时,问题会再次发生。
- 只是一遍又一遍地重试查询...这不是我希望的选择。
我应该如何进行?我应该考虑其他方法吗?
编辑:我已尝试在 varcharfield 上设置索引,但表仍处于锁定状态。我怀疑锁定发生在UPDATE 部分实际执行时。还有其他解决此问题的建议吗?
【问题讨论】:
标签: mysql locking innodb deadlock