Atomikos + druid 多数据源数据库连接超时回收问题怎么解决

Atomikos + druid 多数据源数据库连接超时回收问题怎么解决,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

异常表现

一段时间不查询数据,通常是过一夜第二天一早发起第一次连接时会出现数据库无法连接异常:

//通常会出现下面错误,异常情况一:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was 37,350,882 milliseconds ago.  The last packet sent successfully to the server was 37,350,882 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.

//异常情况二:
ERROR [com.alibaba.druid.pool.DruidPooledStatement:357] - CommunicationsException, druid version 1.1.10, jdbcUrl : jdbc:mysql://XX.XX.XX.XX:3306/txsmarthome?useUnicode=true&characterEncoding=utf8&useSSL=false&allowMultiQueries=true&noAccessToProcedureBodies=true&autoReconnect=true&failOverReadOnly=false&pinGlobalTxToPhysicalConnection=true, testWhileIdle true, idle millis 39540140, minIdle 50, poolingCount 0, timeBetweenEvictionRunsMillis 60000, lastValidIdleMillis 39540140, driver com.mysql.jdbc.Driver, exceptionSorter com.alibaba.druid.pool.vendor.MySqlExceptionSorter

//异常情况三:
java.sql.SQLException: connection holder is null

druid 异常

出现上述前两个异常是由于数据库连接超过mysql配置的 wait_timeout 时间,连接被mysql回收,但是 druid 连接池并不知道连接已被回收,因此报错。

连接池都有失败重连功能,druid的做法是在下一次请求连接数据库时,重连上一个异常的连接,所以之后的每次请求都是异常,直到池中所有连接都重连一次。即连续失败次数就是 minIdle 配置的数量。

如果连接多数据库情况,每个数据库的请求都会连接失败 minIdle 次。

连接池配置

spring:
    datasource:
        druid:
            db1:
                # 每隔1小时检查数据库连接是否有效,连接成功1分钟后开始计时
                removeAbandonedTimeout: 3600
                # 如果连接失效就删重连
                removeAbandoned: true
                # 删除时输出日志
                logAbandoned: true
                # 测试查询查询结果
                testOnReturn: true

上述配置可保证限时删除无效连接。

数据库配置

命令行连接数据库后,执行:show global variables like "%timeout%";

mysql> show global variables like "%timeout%";
+-----------------------------+----------+
| Variable_name               | Value    |
+-----------------------------+----------+
| connect_timeout             | 10       |
| delayed_insert_timeout      | 300      |
| have_statement_timeout      | YES      |
| innodb_flush_log_at_timeout | 1        |
| innodb_lock_wait_timeout    | 7200     |
| innodb_rollback_on_timeout  | OFF      |
| interactive_timeout         | 3600     |
| lock_wait_timeout           | 31536000 |
| net_read_timeout            | 30       |
| net_write_timeout           | 60       |
| rpl_stop_slave_timeout      | 31536000 |
| slave_net_timeout           | 60       |
| wait_timeout                | 3600     |
+-----------------------------+----------+

上述数据库的链接有效时间是1小时,mysql默认为8小时,可使用命令修改,无须重启mysql:

# 修改为12小时,注意下面两个配置项要一致才能生效
mysql> set global interactive_timeout=43200;
Query OK, 0 rows affected

mysql> set global wait_timeout=43200;
Query OK, 0 rows affected

需要注意 链接池 removeAbandonedTimeout <= 数据库 wait_timeout。

atomikos 异常

异常情况三的场景更复杂一些, atomikos 工作在 druid 上层,当druid检测到超时链接并重连后,并不会通知 atomikos,所以下次sql执行时仍然会报错。

atomikos 资料较少,看源码太费时,有空了再研究。

解决方案
  1. 尽量增大数据库 wait_timeout 的时间(需要注意过大的 wait_timeout 会影响数据回收无效链接)。

  2. 可关闭druid removeAbandoned 功能。

  3. 配置一个定时器,在 min(wait_timeout,removeAbandonedTimeout) 时间内至少执行 minIdle 次,每次都在所有数据源中执行一个简单的查询。

三种方式可结合使用

升级 mysql-jdbc-driver 到6以上据说也可以解决,没有测试过。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注蜗牛博客行业资讯频道,感谢您对蜗牛博客的支持。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

评论

有免费节点资源,我们会通知你!加入纸飞机订阅群

×
天气预报查看日历分享网页手机扫码留言评论电报频道链接