为什么在尝试在MySQL上设置自动提交时Tomcat会挂起?

时间:2016-01-28 22:00:06

标签: java mysql tomcat

我有一个反复出现的间歇性问题,我的Spring JPA / Hibernate应用程序(在Tomcat 8上运行)在setAutoCommit阶段尝试从MySQL读取时会挂起5-30秒。这发生在我们运行MySQL 5.0时,并且在升级到最新的MariaDB之后仍然继续。

这个问题可能不会一次出现数天或数周,但一旦出现,通常会在下午,M-Th,在我们的高峰时期出现#34;小时。 (" Peak"这里真的相当轻,可能每秒10次请求。)奇怪的是,这个问题经常发生在14:50,尽管我找不到任何cronjobs或其他重复的任务会导致这个。

应用程序跨两个服务器集群,并且两个服务器在尝试连接到共享数据库服务器时同时挂起,因此它似乎是数据库端的东西。 db允许1000个max_connections,但是使用的数量远不及那么多。在Tomcat方面,我使用C3P0和100个最大连接。似乎没有任何特定的SQL会触发此问题,所有查询都会在发生此问题时挂起。

这是挂起线程的堆栈跟踪:

"ajp-nio-8010-exec-26" Id=1355 RUNNABLE (in native)
  java.lang.Thread.State: RUNNABLE
   at java.net.SocketInputStream.socketRead0(Native Method)
   at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
   at java.net.SocketInputStream.read(SocketInputStream.java:170)
   at java.net.SocketInputStream.read(SocketInputStream.java:141)
   at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:100)
   at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:143)
   at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:173)
   - locked com.mysql.jdbc.util.ReadAheadInputStream@33d807d4
   at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2911)
   at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3332)
   at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3322)
   at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3762)
   at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2435)
   at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2582)
   at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2531)
   - locked com.mysql.jdbc.JDBC4Connection@178ec6c
   at com.mysql.jdbc.ConnectionImpl.setAutoCommit(ConnectionImpl.java:4852)
   - locked com.mysql.jdbc.JDBC4Connection@178ec6c
   at com.intergral.fusionreactor.jdbc.ConnectionSurrogate.setAutoCommit(ConnectionSurrogate.java:368)
   at com.mchange.v2.c3p0.impl.NewProxyConnection.setAutoCommit(NewProxyConnection.java:1059)
   etc.....

同时,在MySQL的慢查询日志中:

# Time: 160128 14:50:38
# User@Host: user @ server1
# Thread_id: 77244  Schema: db_live  QC_hit: No
# Query_time: 7.621437  Lock_time: 0.000000  Rows_sent: 0  Rows_examined: 0
# Rows_affected: 0
SET timestamp=1454010638;
commit;
# User@Host: user @ server2
# Thread_id: 81339  Schema: db_live  QC_hit: No
# Query_time: 7.556022  Lock_time: 0.000000  Rows_sent: 0  Rows_examined: 0
# Rows_affected: 0
SET timestamp=1454010638;
commit;

我不太确定要做慢速日志 - 这里没有实际的SQL,但它对应于此时在Tomcat上观察到的7秒挂起。与两个服务器同时尝试连接并相互阻塞的服务器有什么关系?两个SET timestamp语句完全相同。请注意,两个Tomcat实例都使用相同的用户凭据登录,只来自两个不同的IP。在日志之前或之后,附近没有其他慢查询。

任何想法可能会导致这种情况或下一步发生的事情?

编辑:

其他可能值得注意的细节:表格是InnoDB,我们正在使用transaction-isolation = READ-COMMITTED。挂起的所有线程都在setAutoCommit上等待。

1 个答案:

答案 0 :(得分:0)

它没有。堆栈跟踪显示阻止试图从数据库服务器读取,这意味着它已经连接,并且它正在做的是设置{{1} },而不是连接阶段的任何事情。