MySQL的8小时

一个关于MySQL的8小时问题在项目中的出现。

最近在项目测试过程中出现了数据库连接被close的问题。

现象:
早上一来测试前几条的订单时,就会报连接close,之后一天都是正常的。

初探:
用了C3P0,很自然的就想到了C3P0为什么会把close的连接给项目使用,因为C3P0本身会有检查连接是否有效的机制。自然就想到是不是配置有问题,结果配置了所有的选项,在本地测试都有问题。
本地测试测场景:
1,MySQL的8小时连接无效改成2分钟。
2,C3P0把与检查连接相关的配置全部配置上。
结果让人失望的是,全部不行。

进一步:是不是触发了C3P0的BUG,换阿里的连接池?,不过这个想法只是一闪而过。

最后:没有办法,回过头来一句一句的研读代码,分析业务,最后发现一句和数据库没有关系的代码上发现了问题。

原因:在一个线程中,获取了C3P0的一个连接。在业务代码中向缓存队列取数据时,如果队列中没有数据,该线程阻塞了!这样在队列中长期没有数据的情况下(测试环境下同事在下班后没有进行订单提交),这个数据点就超过了MySQL的8小时设置,超过8小时,MySQL检查机制检查到该连接没有任何数据交互。就会把该连接close。这个是MySQL的行为不会通知连接池。而在我们的系统中因为该连接是一直被线程占用,所以C3P0不会去检查它是否有效(因为C3P0认为你一直在使用该连接)。这样C3P0认为可以用,MySQL其实已经close。当早上来测试同事向队列发送数据的时候,线程解除阻塞,后面再使用持有的连接来操作数据库的时候,这个时候就会报close的错误了。

总结:1,不要轻易怀疑你使用的开源工具,因为遇到的问题99.99%都是自己代码的问题。
      2,万不得已不要使线程阻塞,即使使用了阻塞的方法,也一定要加上超时时间。

猜你喜欢

转载自jishuaige.iteye.com/blog/2366860