mysql|MySQL 的这个 BUG,坑了多少人?( 二 )
error = innobase_set_max_autoinc(auto_inc)
……
}
从我们的实际业务流程来看 , 我们的错误只可能涉及insert及update流程 。
BUG 76872 / 88321: "InnoDB AUTO_INCREMENT produces same value twice"
(1)bug概述:当autoinc_lock_mode大于0 , 且auto_increment_increment大于1时 , 系统刚重启后多线程同时对表进行insert操作会产生“duplicate key”的错误 。
(2)原因分析:重启后innodb会把autoincrement的值设置为max(id) + 1 。 此时 , 首次插入时 , write_row流程会调用handler::update_auto_increment来设置autoinc相关的信息 。 首先通过ha_innobase::get_auto_increment获取当前的autoincrement的值(即max(id) + 1) , 并根据autoincrement相关参数修改下一个autoincrement的值为next_id 。
当auto_increment_increment大于1时 , max(id) + 1 会不大于next_id 。 handler::update_auto_increment获取到引擎层返回的值后为了防止有可能某些引擎计算自增值时没有考虑到当前auto increment参数 , 会重新根据参数计算一遍当前行的自增值 , 由于Innodb内部是考虑了全局参数的 , 因此handle层对Innodb返回的自增id算出的自增值也为next_id , 即将会插入一条自增id为next_id的行 。
handler层会在write_row结束的时候根据当前行的值next_id设置下一个autoincrement值 。 如果在write_row尚未设置表的下一个autoincrement期间 , 有另外一个线程也在进行插入流程 , 那么它获取到的自增值将也是next_id 。 这样就产生了重复 。
(3)解决办法:引擎内部获取自增列时考虑全局autoincrement参数 , 这样重启后第一个插入线程获取的自增值就不是max(id) + 1 , 而是next_id , 然后根据next_id设置下一个autoincrement的值 。 由于这个过程是加锁保护的 , 其他线程再获取autoincrement的时候就不会获取到重复的值 。
通过上述分析 , 这个bug仅在autoinc_lock_mode > 0 并且auto_increment_increment > 1的情况下会发生 。 实际线上业务对这两个参数都设置为1 , 因此 , 可以排除这个bug造成线上问题的可能性 。
现场分析及复现验证
既然官方bug未能解决我们的问题 , 那就得自食其力 , 从错误现象开始分析了 。
(1) 分析max id及autoincrement的规律 由于用户的表设置了ON UPDATE CURRENT_TIMESTAMP列 , 因此可以把所有的出错的表的max id、autoincrement及最近更新的几条记录抓取出来 , 看看是否有什么规律 。 抓取的信息如下:
乍看起来 , 这个错误还是很有规律的 , update time这一列是最后插入或者修改的时间 , 结合auto increment及max id的值 , 现象很像是最后一批事务只更新了行的自增id , 没有更新auto increment的值 。
【mysql|MySQL 的这个 BUG,坑了多少人?】
联想到【官方文档】中对auto increment用法的介绍 , update操作是可以只更新自增id但不触发auto increment推进的 。 按照这个思路 , 我尝试复现了用户的现场 。 复现方法如下:
本文插图
同时在binlog中 , 我们也看到有update自增列的操作 。 如图:
本文插图
不过 , 由于binlog是ROW格式 , 我们也无法判断这是内核出问题导致了自增列的变化还是用户自己更新所致 。 因此我们联系了客户进行确认 , 结果用户很确定没有进行更新自增列的操作 。
那么这些自增列到底是怎么来的呢?
(2) 分析用户的表及sql语句 继续分析 , 发现用户总共有三种类型的表(hz_notice_stat_sharding, hz_notice_group_stat_sharding,hz_freeze_balance_sharding) , 这三种表都有自增主键 。
推荐阅读
- 智趣科技|放心,这个扎手真不疼!糖护士血糖尿酸测试仪测评
- AMD,英特尔|又一批第十代酷睿CPU来了 这个全新i9价格有点香
- 三星手机|三星手机的oneui2系统真的很垃圾吗?
- 中年|历史上被称作用情最专一的皇帝,却死于不测,这个人是谁?
- 群众网|这个国产科技品牌连续十年蝉联全球第一,却很低调,甚至被人误解
- 小米手机|小米10Pro跳水700,这个价位随便买吧
- 新智元|两图生万物!这个超强图像转换神器,小样本一秒猫狗合体变新物种
- 雷科技|查岗抓奸新工具?高德地图这个新功能,让你的行踪无所遁形
- 数据库|面试官:说说MySQL数据库分库分表,并且会有哪些问题?
- 滋补|猪身上就这个部位最贵夏天应该多吃点,比牛羊肉更滋补