一个导致查询结果错的MySQL bug

ywz888
发布于 2022-10-10 16:11
浏览
0收藏

现象

有业务系统反应,通过主键条件查询用户表,得到的一行结果与条件中的主键值不一致,这是什么鬼啊?


结论

设置JDBC参数不合理(queryTimeout=10s,socketTimeout=10s),导致在异常情况下,第二条get获得了第一条get的结果,得到错误的数据,数据库表现正常;

详细的出错流程

(1) 应用设置queryTimeout=10s,socketTimeout=10s;

(2) 在JDBC代码中,socketTimeout是利用fd超时实现的,而queryTimeout是另外起一个任务(cancel线程),监听request是否完成,如果在queryTimeout内未完成,则新建一个连接发kill query,将主线程的query干掉;

(3) 执行流程中,queryTimeout先被schedule,socektTimeout后被enable到fd上,但由于这个两个timeout的时间相同,因此queryTimeout先生效;

(4) queryTimeout生效后,将发送kill query,希望将主线程的请求干掉;当时的情况是,单条get在server上执行很快,由于网络问题,回包在网络上fly了很长时间(10s+),因此实际上发送的那条kill query没有干任何事情;

(5) 而后socektTimeout生效,主线程获取异常(CommunicationsException),继续执行,但JDBC会check一下请求是否被cancel掉了,如果被cancel掉了就会抛出MySQLTimeoutException,原来的CommunicationsException被覆盖掉了;

(6) 最终应用得到的异常是MySQLTimeoutException,注意,此时请求的数据还在网络上fly;中间件对于CommunicationsException的异常会断连接,而MySQLTimeoutException异常认为是普通错误,将连接重新放回连接池中;

(7) 放回连接池的连接被应用其它线程获得,又发送一个get请求,等待接收response;

(8) 而此时第一个get请求的response到了,JDBC返回给应用,这样就收到了错误的数据;

网络问题

在出问题时间点附近,网络抖动比较厉害:

一个导致查询结果错的MySQL bug-鸿蒙开发者社区

复现

在mysql(5.6.23)和JDBC(5.1.34)复现,利用iptables将网络包阻塞在网络中一定时间;

测试代码:

一个导致查询结果错的MySQL bug-鸿蒙开发者社区

测试结果

一个导致查询结果错的MySQL bug-鸿蒙开发者社区

建议

MySQL很好用,使用要慎重!没有踩坑的准备和填坑的能力,那就只能呵呵哒了!


文章转载自公众号:OceanBase

分类
标签
已于2022-10-10 16:11:25修改
收藏
回复
举报
回复
    相关推荐