代码之家  ›  专栏  ›  技术社区  ›  nightcoder

在这种情况下我怎么能死锁呢?

  •  2
  • nightcoder  · 技术社区  · 15 年前

    在我的客户机应用程序中,我有这样一个方法(实际上它更复杂,但我已经离开了主要部分):

    public void btnUpdate_Click(...)
    {
      ...
      dataAdapter.Update(...);
      ...
      dataAdapter.Fill(...); // here I got exception one time
    }
    

    我在日志中发现的异常是“尝试获取锁时发现死锁;尝试重新启动事务”。我只见过一次例外,所以没有重复。
    据我所知,dataadapter.fill()方法只执行select查询。我没有做一个明确的交易,我已经启用了自动提交。
    那么,我怎样才能对一个不属于更大事务的简单select查询死锁呢?
    据我所知,要得到一个死锁,两个事务应该相互等待。如果一个select不在事务中,这怎么可能呢?可能是MySQL中的一个bug?

    提前谢谢你。

    4 回复  |  直到 15 年前
        1
  •  1
  •   Charles Bretana    15 年前

    你说得对,两个事务会造成死锁。也就是说,单个事务中的一个或多个语句都不能与 同一笔交易 .

    但只需一个事务就可以注意到死锁的报告。您如何知道您所看到的死锁报告的事务是数据库中正在执行的唯一事务?数据库中没有其他活动吗?

    也。你的陈述” 我不做明确的交易 “和” …这不是更大交易的一部分 “这意味着您不理解执行的每个sql语句总是在隐式事务中,即使您没有显式地启动一个事务。

    大多数数据库都有专门设计的报告机制,用于跟踪、报告和/或记录死锁实例,以便进行诊断。在SQL Server中,有一个跟踪标志,它会导致一个日志条目,其中包含有关发生的每个死锁的详细信息,包括有关所涉及的两个事务中每一个事务的详细信息,例如正在执行的SQL语句、正在锁定的数据库中的对象以及为什么无法锁定被扣押的我猜MySQL也有类似的诊断工具。找出它是什么,然后打开它,以便下次发生这种情况时,您可以查看并找出到底发生了什么。

        2
  •  0
  •   Remus Rusanu    15 年前

    您可以死锁一个简单的select 其他 语句,比如更新。在我的博客上,我举了一个例子来解释两个经过深思熟虑的语句之间的死锁: Read/Write deadlock . 虽然该示例是特定于SQL Server的,但其原理是通用的。我对mysql的了解还不够,不知道这是不是必然的,特别是考虑到mysql可以部署的各种引擎,但是一个简单的选择也会成为死锁的牺牲品。

        3
  •  0
  •   Guffa    15 年前

    我还没有研究mysql事务是如何工作的,但这是基于mssql事务是如何工作的:

    如果不使用事务,则每个查询都有自己的事务。否则,每次中间更新失败时,都会一团糟。

    死锁的原因可能是锁升级。数据库尝试尽可能少地为每个查询锁定,因此它首先只锁定受影响的单行。当页面中的大多数行被查询锁定时,它可能会决定将锁定升级为锁定整个页面会更好,这可能会产生副作用,即锁定一些不受查询影响的行。

    如果A select 查询与AN update 查询正在尝试升级同一表上的锁,如果只涉及一个表,它们可能会导致死锁事件。

        4
  •  0
  •   Chris Travers    8 年前

    我同意,在这个问题上,这不太可能是问题,但这是对其他答案的补充,限制了它们的范围,为后人记录,以防有人发现它有用。

    在极少数情况下,mysql可以有针对自身的周期性死锁。这似乎特别发生在大容量插入上,而且问题几乎肯定是与操作相关的不同线程之间的死锁。我希望批量更新也会遇到同样的问题。在过去,当遇到这种问题时,我通常只会减少在单个语句中插入(或更新)的行数。在这种情况下,尝试获取锁时通常不会出现死锁,而是会出现其他消息。

    我和我的一个同事在讨论ms sql server中的类似问题(所以这不是mysql独有的!)他指出,解决方案是告诉服务器不要并行插入或更新。这里的问题是与spinlock相关的死锁,而不是rdbms中的逻辑锁死锁。