MySQL引发的监控问题
浏览量: 次 发布日期:2023-10-11 19:28:35
MySQL引发的监控问题
一个线上的小案例
微信公众号:DBA随笔
今天在线上发现一个问题,挺有意思的,这里简单记录下。问题的背景是查看一个Grafana监控的时候,发现监控没有数据了:
从图中可以看到4月1日之后,监控就没有输出数据了。
于是决定排查一下这个问题。排查思路如下:
1、监控数据源配置是否准确;
2、监控数据是否采集完整;
连云港数据恢复3、监控数据所在数据库是否可以访问;
经过查看,监控数据从4月开始就缺失了,由于监控数据采集程序的日志不够全面,所以花了很长时间才定位到根本原因:监控数据写入数据库的时候,报错了。
其实报错信息也比较简单,如下:
这个明眼人一看,就是主键冲突了,冲突的id值是4294967295。那就开始排查主键冲突的问题吧。1、表结构查看
首先查看表结构,看着似乎没什么异样,如下:
2、查看数据
这里找到上面的报出冲突的自增id值,发现是4294967295 ,然后使用select语法来查看这个id对应的数据是否存在:
发现这条数据也在表里面。
于此同时,发现这个表结构里面的auto_increment值也是4294967295
这就比较奇怪了,自增id一般都会是当前表中id最大值的下一个id值,例如表中最大id是10,自增id的值应该是11.
为什么这个自增id和表里面的最大id值一样?(可能有的小伙伴已经知道答案了,但是排查的时候,我确实没反应过来)3、数据修复
先尝试手动delete这条id=4294967295冲突的数据,再重新插入id=4294967295新的数据,看看能不能恢复吧。
结果是:
删除后重新插入id=4294967295不报错,但是后续的新数据插入时候又报如下错误:
似乎没解决问题。
既然id=4294967295的数据冲突,那我们把这个id加1,看看手工插入一条数据能不能行:
不得不说,这个输出的结果有很大的误导意义
注意,我们插入的数据是id=4294967296,但是报错还是显示id=4294967295,死活就跟这条数据过不去了!!!
(这里我以为我发现了什么惊天大bug,喊来两个同事,一起看看这个问题。)
再次删除id=4294967295的数据,插入id=4294967296的数据:
我去,没有了那个坏id的数据,后面的id终于也能插入了???等等,有个warning(同事提醒),看下:
好吧,MySQL已经给出了答案了:id是int 类型的,这个自增值溢出了。
找个测试表试试
到这里,这个问题的原因就算找到了,也能稳定复现这个问题。
使用alter table语句,将这个线上表的主键id列改为bigint类型的即可。
测试环境看一发:
从结果中不难看出来,这个操作不能online,会拷贝表里面所有的数据。
线上重要表的操作最好使用pt-osc工具或者gh-ost工具执行。
这里再给一个不同类型的id范围的表:
说实话,这些范围边缘数据,平时不注意的话,看到了可能也反应不过来,如果你够细心,对它们很敏感,可能这个问题一分钟就解决了,根本不需要排查。
最终,监控数据也回来了。
修复前:
修复后:
上述情况是在MySQL 5.5 版本上操作的,MySQL8.0中会不会有所改善。
看来MySQL8.0对于这种情况,支持的友好一点。
当表里面有最大id的情况下,插入一个更大的id:MySQL5.5会报最大的id冲突,有一定的误导;MySQL8.0直接报错,更严谨;
当表里没有最大id值,但是自增id为最大id值,插入一个更大的id,MySQL5.5会插入成功,但是发生数据截断,提示warning;MySQL8.0会直接报错,更严谨。
综上,升级MySQL8.0吧。
今天就这么多,睡觉了。