奇怪的 SQLException - 无法检索事务只读状态服务器

Posted

技术标签:

【中文标题】奇怪的 SQLException - 无法检索事务只读状态服务器【英文标题】:odd SQLException - Could not retrieve transation read-only status server 【发布时间】:2014-03-06 06:38:50 【问题描述】:

我有一个Quartz 作业,它每 5 分钟在我的 mysql 数据库中执行一次存储过程,由于某种原因,三分之一的执行失败并给出了这个奇怪的异常。我已经搜索并搜索了此异常的含义,但找不到解决方案。这是完整的堆栈跟踪:

java.sql.SQLException: Could not retrieve transation read-only status server
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:989)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:975)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:920)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:951)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:941)
    at com.mysql.jdbc.ConnectionImpl.isReadOnly(ConnectionImpl.java:3939)
    at com.mysql.jdbc.ConnectionImpl.isReadOnly(ConnectionImpl.java:3910)
    at com.mysql.jdbc.PreparedStatement.checkReadOnlySafeStatement(PreparedStatement.java:1258)
    at com.mysql.jdbc.CallableStatement.checkReadOnlySafeStatement(CallableStatement.java:2656)
    at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1278)
    at com.mysql.jdbc.CallableStatement.execute(CallableStatement.java:920)
    at com.mchange.v2.c3p0.impl.NewProxyCallableStatement.execute(NewProxyCallableStatement.java:3044)
    at org.deadmandungeons.website.tasks.RankUpdateTask.execute(RankUpdateTask.java:30)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 1,198,219 milliseconds ago.  The last packet sent successfully to the server was 950,420 milliseconds ago.
    at sun.reflect.GeneratedConstructorAccessor43.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1121)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3673)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3562)
    at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4113)
    at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2812)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2761)
    at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1612)
    at com.mysql.jdbc.ConnectionImpl.isReadOnly(ConnectionImpl.java:3933)
    ... 9 more
Caused by: java.net.SocketException: Connection timed out
    at java.net.SocketInputStream.socketRead0(Native Method)
    at java.net.SocketInputStream.read(SocketInputStream.java:150)
    at java.net.SocketInputStream.read(SocketInputStream.java:121)
    at com.mysql.jdbc.util.ReadAheadInputStream.fill(ReadAheadInputStream.java:114)
    at com.mysql.jdbc.util.ReadAheadInputStream.readFromUnderlyingStreamIfNecessary(ReadAheadInputStream.java:161)
    at com.mysql.jdbc.util.ReadAheadInputStream.read(ReadAheadInputStream.java:189)
    at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3116)
    at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3573)
    ... 17 more

所以我认为它正在超时,因为它认为 MySQL 服务器处于只读状态? 这只发生在这个石英作业中,而不是我与数据库通信的任何其他时间。这个执行当然是在另一个线程中发生的,但我认为这与它没有任何关系。 为什么它会认为服务器处于只读模式?

另外,我不认为“翻译”是一个词,所以就是这样......

【问题讨论】:

您使用的是哪个 MySQL 版本?见这里:bugs.mysql.com/bug.php?id=70290 如果你用谷歌搜索确切的消息,你会发现其他页面也与这条消息相关。 @peter.petrov MySQL 版本是 5.6.10-log,相对较新。此外,在那个线程中,他们的问题是不支持某个变量。这个堆栈跟踪显示了一些不同的东西。我已尝试搜索确切的消息。 好的,也可以在这里查看:toadworld.com/products/toad-extension-for-eclipse/f/42/t/… 他们只是直接说 5.6 尚未完全测试或支持。但这是从 2013 年 10 月开始的。我想你应该用 MySQL 打开一个错误,看看他们怎么说。 你检查过这个吗? ***.com/questions/6865538/… 之前看过Java写的通信;这通常意味着客户端正在尝试使用服务器已关闭的连接。自成功数据包以来已经快 1000 秒了,所以 MySQL 服务器上可能存在 15 分钟的连接超时?我不买它是因为版本问题,可能是,但这些东西的网络协议并没有发展得太快。 【参考方案1】:

很抱歉在旧帖子上发帖,

正如堆栈跟踪所说

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

这意味着 JDBC 和 DB 之间的链接已断开。根据您的观察,您说 3 个作业调用中有 1 个失败。

您每 5 分钟安排一次这些作业,并且根据跟踪,最后一次成功发送到服务器的消息大约在 15 分钟之前。

因此我怀疑

    您的程序没有返回(等待某事) JDBC 连接已被防火墙/代理失效

看看如何管理连接会很有趣,根据我看到的日志,我看到你正在使用 c3p0。

您可以尝试设置unreturnedConnectionTimeoutdebugUnreturnedConnectionStackTraces。这将使您更深入地了解需要很长时间的连接泄漏或数据库调用。

【讨论】:

【参考方案2】:

正如你们所说,研究无处可去,但错误显示数据库似乎同时被两个应用程序填充。

你有这个 MySQL 服务器的管理员权限吗?如果你这样做,你应该尝试设置

FLUSH TABLES WITH READ LOCK;
SET GLOBAL READ_ONLY=ON;

作为重现错误的测试。警告您,此命令使您的数据库不可写,因此您将无法在其中添加数据,直到您恢复此配置,显然与

SET GLOBAL READ_ONLY=0;
UNLOCK TABLES;

如果这个测试的结果是肯定的(同样的错误已经重现),你应该尝试隔离在你的数据库中存储数据的应用程序,找出哪个与 Quartz 冲突。

很抱歉含糊其辞,但我希望它能给你一些帮助......

【讨论】:

以上是关于奇怪的 SQLException - 无法检索事务只读状态服务器的主要内容,如果未能解决你的问题,请参考以下文章

网页显示无法打开JDBC连接事务;嵌套异常java.sql.SQLException:无法连接、 如何处理这种问题

SPRING BATCH:嵌套异常是java.sql.SQLException:ORA-08177:无法序列化此事务的访问权限

来自实体框架的 SqlException - 不允许新事务,因为会话中正在运行其他线程

来自实体框架的 SqlException - 不允许新事务,因为会话中正在运行其他线程

解决spring 事务管理默认不支持SQLException等运行时异常

SharePoint "System.Data.SqlClient.SqlException (0x80131904): Parameter '@someColumn' wa