Mysql 带锁模式S和X的InnoDB死锁

Mysql 带锁模式S和X的InnoDB死锁,mysql,locking,innodb,deadlock,Mysql,Locking,Innodb,Deadlock,在我的应用程序中,我有两个查询(来自不同的进程),它们会导致死锁 查询#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]; 这两个查询都需要很长时间,因为这些表

在我的应用程序中,我有两个查询(来自不同的进程),它们会导致死锁

查询#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
锁不兼容,query#1最多会等待30秒,此时我会出现死锁:

序列化失败:尝试获取锁时发现1213死锁;尝试重新启动事务

根据我所读到的,我想我有几个选择:

  • 在tblA.varcharfield上设置索引。不幸的是,我认为这需要一个非常大的索引来存储varchar(512)字段。(请参见下面的编辑…这不起作用。)
  • 使用
    设置会话事务隔离级别READ UNCOMMITTED禁用锁定;
    
    。我不明白这意味着什么,我担心数据会被破坏。我目前在应用程序中不使用显式事务,但将来可能会使用
  • 将耗时的查询拆分成小块,这样它们就可以在MySQL中排队并运行,而不会达到30秒的超时时间。这并不能真正解决问题的核心,我担心当我的数据库服务器变得繁忙时,问题会再次出现
  • 只需一次又一次地重试查询。。。这不是我所希望的选择
  • 我应该如何继续?是否有其他的方法我应该考虑?< /强>



    编辑:我已尝试在varcharfield上设置索引,但表仍处于锁定状态。我怀疑当
    更新
    部分实际执行时会发生锁定。有没有其他解决此问题的建议?

    A.如果我们假设索引
    varcharField
    占用大量磁盘空间,并且添加新列不会对您造成太大影响,我可以建议以下方法:

  • 创建数据类型为“tinyint”的新字段
  • 索引它
  • 如果
    varcharField
    为空,则此字段将存储0,否则为1
  • 重写第一个查询以根据新字段进行更新。在这种情况下,它不会导致整个表锁定

  • 希望有帮助。

    您只能索引varchar列的一部分,它仍然可以工作,并且需要的空间更少。只需指定索引大小:

    CREATE INDEX someindex ON sometable (varcharcolumn(32))
    

    我能够通过在两个查询周围添加显式的
    locktable
    语句来解决这个问题。这原来是一个更好的解决方案,因为每个查询都会影响很多记录,而且这两个都是后台进程。他们现在互相伺候


    虽然这对我来说是个不错的解决方案,但显然不是每个人都能找到的答案。用
    WRITE
    锁定意味着您无法
    读取
    。只有
    读取
    锁定才允许其他人
    读取

    谢谢您的建议。我昨晚试过了,但还是遇到了僵局。我在
    SELECT
    查询中运行了
    EXPLAIN
    ,它们都使用了预期的索引。我怀疑必须先运行
    更新
    ,然后我的
    选择
    才能工作。@Brad你能为问题添加解释吗?我想看看它们。我非常感谢你的帮助。通过显式锁定表,我可以绕过这个问题。我认为这个问题是由于保密协议我不能透露的问题的一部分,我在问题中的简化并没有充分说明这个问题。再次感谢您的帮助!谢谢你的建议。我曾尝试使用Darhazer建议的索引,但没有效果。我怀疑必须先运行
    更新
    ,然后才能允许运行我的
    选择
    。您还有其他建议吗?如果仍然存在问题,请将
    显示innodb状态的结果放入“死锁”部分,谢谢您的帮助。我通过显式锁定表解决了这个问题。不幸的是,我认为死锁一定是由查询的其他部分引起的,由于保密协议的原因,我不能透露。我对这个问题的简化是不够的。不过,我非常感谢你在解决这个问题上的帮助。