old post from wiznote
- 20180408 binlog新实例(20.29_3306)上线
- 20180409,19点左右,binlog 邮件报警,dumper进程挂掉
- 看控制台输出,
- 第一个错误,大量乱码
- 随后自动重启,提示max-allow_packet过小
- Fix-第一阶段:
- 猜测是大sql导致的错误,联系dba,调整mysql配置到1G,无效
- Fix-第二阶段
- 感觉主要是第一个错误引起的,但是是乱码,不好定位,感觉是解析出现的问题。猜测是大包引起的mysql压缩
- 查看代码和文档,主从都开启压缩才会生效,但代码内并没有开启,所以无解。
- 尝试找dba查看配置,看是否是因为某个配置不同而造成的,并没有,无解。
- Fix-第三阶段
- 只能走最原始的办法,拉下来出错的binlog文件,分析。
- 发现出错的event,有两个问题
- 表结构有外键
- 有longtext字段,大小20+M。
- 猜测是外键的原因,导致tablemap解析不完全,导致下一个update event解析失败。
- 或者是longtext读取失败。
- Fix-第四阶段
- 知道了出问题的库,表,拿到对应的定义,在本地重建。模拟,发现
- 外键的存在不影响正常使用。
- longtext字段不影响。
- longtext字段填充40M数据,挂掉!
- Fix-第五阶段
- 本地单步调试,
- 发现30m的数据,只读取了16M。但
- 拿到的eventSize确实是40M
- 拿到的packetSize确实是16M
以为是packatSize解析错误,看代码,三个字节。解析没错,但是3个字节能表示的最大值是16M!!
- 也就是mysql的一个包最大只有16M。
- 那对于超过16M的event怎么办呢,毕竟mysql支持的event可以有1G。
- 合理的解释只有1个event可能会被切割为多个packet!!!
- 查mysql文档,确实是。而原有代码没有考虑这种情况。
- 功能实现:
- 由于没找到文档,直接看原始数据理解格式
- 发现40M的event,被分成了3个packet。
- 正常情况,一个packet第一个字节直接是status字段,而分包的情况下,后面的包全部是数据,而没有status字节。(经过size对比发现。后查阅网络,验证猜测。)
- 代码开发。
- 本地测试。
- 测试环境测试
- 上线。
- done。
一句话概括:
- 旧代码bug,不支持大event(超过16M)。
- mysql单个event可支持最大到1G,但是网络传输的单个packet,最大16M。所以对于超过这个值的event,会被切割为多个packet发送。