如何找到死锁的两个线程?

5
我们正在使用经典的Spring/Hibernate/MySQL技术栈在Tomcat 5.5上运行。偶尔会出现死锁,当尝试锁定表格行时超时。某种死锁异常被抛出。
异常很清楚,堆栈跟踪指示出了问题所在。但它并没有显示持有实际锁的另一个线程。除非我知道那个线程在做什么,否则这就像大海捞针一样难以找到。
问题:有办法找到另一个线程吗?
谢谢!
Jan

2
异常来自哪里 - mysql?你能发布一个堆栈跟踪吗? - matt b
你怎么知道只有另一个线程?可能会涉及一长串线程死锁。 - Albin Sunnanbo
我当然不知道涉及的线程数量。但是该应用程序是一个典型的“一个请求=一个线程”的情况。我们没有使用线程。并且由于锁是互斥的,因此在同一时间只能有一个线程。 - Jan Goyvaerts
org.springframework.dao.CannotAcquireLockException: 无法插入集合:[com.customer.Site.siteLayoutSettingsRaw#48112];嵌套异常为org.hibernate.exception.LockAcquisitionException: 无法插入集合:[com.customer.Site.siteLayoutSettingsRaw#48112] 在org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:633)处 在org.springframework.orm.hibernate3.AbstractSessionFactoryBean.convertHibernateAccessException(AbstractSessionFactoryBean.java:303)处。 - Jan Goyvaerts
由于:java.sql.BatchUpdateException:尝试获取锁时发现死锁;请尝试重新启动事务 在com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:1998)处 在com.mysql.jdbc.PreparedStatement.executeBatch(PreparedStatement.java:1443)处 在com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)处 在org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)处 在org.hibernate.jdbc.BatchingBatcher.addToBatch(BatchingBatcher.java:56)处 - Jan Goyvaerts
4个回答

1

下次遇到死锁时,请尝试在MySQL中使用以下命令。这应该会显示最后一个死锁。

SHOW INNODB STATUS

通常情况下,当您在应用程序服务器上看到死锁时,日志仅显示受害线程(被回滚的线程)。由于其他线程已经完成,因此不会抛出任何异常。您需要返回到数据库以重新创建事务。
一旦您从数据库中捕获了死锁发生的位置,那么您就可以进一步调查。

这不会起作用,因为我没有访问数据库的权限(当然,它只存在于生产环境中)。即使我能够访问,我也无法快速地回溯到各种锁定对象背后的Java代码。在异常抛出后,我真的需要立即找到JVM内的其他线程。 - Jan Goyvaerts
管理生产数据库的人应该能够为您收集所需的信息。通常知道哪两个Java事务正在锁定是无用的。您需要查看数据库以了解情况。这将告诉您在事务中发生锁定的位置,如果它在索引、主键等中。通过访问此日志,可以获得很多好处。 - Sean
1
应该是:SHOW ENGINE INNODB STATUS吧? - Eidan Spiegel

0

不确定你是否已经解决了问题,但如果是死锁,线程转储将非常有帮助。根据应用程序运行的操作系统和您访问它的特权,您可以以多种方式生成它。

  • 在*nix上,向进程发送QUIT信号('kill -3 pid')即可完成
  • 使用jconsole/jvisualvm有一个选项可以获取它
  • 使用标准jdk jstack(考虑-F -l选项)即可完成
  • 如果您很幸运能够在solaris上使用pstack,那么将会有很大帮助

一旦您获得了它,请分析被锁定/等待的线程以查找死锁。您可以手动执行此操作,也可以使用一些现有的分析器来利用死锁检测算法。顺便说一句,jvm内置了一个算法,它可以在线程转储中直接给出想法。

如果我能提供更多帮助,请告诉我。

祝好运。

此致, baz


0
如果是代码问题,您可以尝试使用jconsole连接正在运行的进程并检测死锁。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接