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

2022-09-03 03:00:14

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

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

另外,我不认为“transation”是一个词,所以有那个......


答案 1

很抱歉在旧线程上发帖,

正如堆栈跟踪所说

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

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

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

因此,我怀疑

  1. 您正在程序未返回(等待某些内容)
  2. JDBC 连接已被防火墙/代理禁用

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

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


答案 2

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

您是否具有此MySQL服务器的管理员权限?如果这样做,则应尝试设置

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

作为重现错误的测试。只是为了警告您,此命令使您的数据库不可写,因此在还原此配置之前,您将无法在其中添加数据,显然

SET GLOBAL READ_ONLY=0;
UNLOCK TABLES;

如果此测试的结果是阳性(已重现相同的错误),则应尝试隔离在数据库中存储数据的应用程序,以找出哪个应用程序与 Quartz 冲突。

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


推荐