mybatis mysql wait_timeout_Mybatis破MySql8小时断线问题

当MySQL的wait_timeout超时后,数据库会单方面关闭连接,引发异常。解决方法包括增大闲置时间(不推荐)或启用Mybatis连接池的ping机制,通过设置poolPingEnabled、poolPingQuery和poolPingConnectionsNotUsedFor属性来定期检查连接有效性,避免长时间未使用的连接导致的问题。
摘要由CSDN通过智能技术生成

MySql有一个系统变量,如图:

8d2c21846a55f2ebb7a212b2c56bf40c.png

以上数值,单位为秒。

mysql的连接允许的闲置时间。当超过闲置时间以后,database端就会将此连接单方面废弃。这时如果使用jdbc继续使用之前的连接,则会收到以下异常:

### Cause: java.sql.SQLException: Could not retrieve transation read-only status server

at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:26)

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:111)

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:102)

at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:119)

at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:63)

at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:52)

at com.sun.proxy.$Proxy8.getMonthlyChart(Unknown Source)

at com.lux.rcc.kpi.bo.ChartABo.getMonthlyChart(ChartABo.java:46)

at com.lux.rcc.kpi.servlets.ChatAServlet.doGet(ChatAServlet.java:70)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:620)

at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)

at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)

at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)

at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)

at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:170)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)

at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)

at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)

at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)

at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:315)

at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

at java.lang.Thread.run(Thread.java:722)

Caused by: java.sql.SQLException: Could not retrieve transation read-only status server

at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1086)

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:3972)

at com.mysql.jdbc.ConnectionImpl.isReadOnly(ConnectionImpl.java:3943)

at com.mysql.jdbc.PreparedStatement.checkReadOnlySafeStatement(PreparedStatement.java:1258)

at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1278)

at sun.reflect.GeneratedMethodAccessor54.invoke(Unknown Source)

at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

at java.lang.reflect.Method.invoke(Method.java:601)

at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:62)

at com.sun.proxy.$Proxy10.execute(Unknown Source)

at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:59)

at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:73)

at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:60)

at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:267)

at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:137)

at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:96)

at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:77)

at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:108)

... 28 more

Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 85,659,759 milliseconds ago.  The last packet sent successfully to the server was 85,659,775 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

at sun.reflect.GeneratedConstructorAccessor24.newInstance(Unknown Source)

at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)

at java.lang.reflect.Constructor.newInstance(Constructor.java:525)

at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)

at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:1129)

at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3988)

at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2598)

at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2778)

at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2828)

at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2777)

at com.mysql.jdbc.StatementImpl.executeQuery(StatementImpl.java:1651)

at com.mysql.jdbc.ConnectionImpl.isReadOnly(ConnectionImpl.java:3966)

... 44 more

Caused by: java.net.SocketException: Software caused connection abort: socket write error

at java.net.SocketOutputStream.socketWrite0(Native Method)

at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:109)

at java.net.SocketOutputStream.write(SocketOutputStream.java:153)

at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)

at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)

at com.mysql.jdbc.MysqlIO.send(MysqlIO.java:3969)

... 50 more

mysql允许设置闲置时间,默认是8小时,最大是1年。

大部分客户端都使用连接池以提高性能,如果用户访问量不大,连接池中的连接可能闲置时间超过数据库允许时间,数据库单方面断掉连接,而客户端却不知情。当下一个用户访问时,使用连接池中的连接,则会抛出上述异常。

解决方法可以是增大闲置时间。但这不是一个好方法。闲置时间是有上限的,在极端情况下,还是可能发生异常。此外,长时间保留闲置的连接,会降低数据库性能,消耗内存,最终耗尽数据库的连接数。所以不推荐增大闲置时间。

一般常用的解决方法是在使用一个长时间闲置的连接之前,对它ping一下,确保它还在正常工作。在mybatis自带连接池配置中,是这样做的:

配置连接池时,需要声明三个属性:

poolPingEnabled - 默认值是false,当值为true的时候,将开启ping机制。

poolPingQuery - 对数据库进行ping时所使用的sql。

poolPingConnectionsNotUsedFor - 默认值是0,单位是毫秒。我们不能在每次使用连接池之前,都使用ping机制,这会使每一条sql的执行,都要额外执行一次ping语句。所以使用此属性来避免这种不合理做法。我们只针对闲置时间超过某个时间的连接,进行ping。本例中的值为1小时,当从连接池中拿出的连接闲置超过1小时,才会对它进行ping。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值