在上一期的月报中,我们在 中提到,InnoDB 自增列在重启后会丢失,因为MySQL没有持久化自增值,平时是存在内存表对象中的。如果实例重启的话,内存值丢失,其初始化过程是做了一个类似 select max(id) + 1 操作。实际上存在另外一种场景,实例即使不重启,也会导致自增值丢失。

    问题说明

    实例运行过种中,InnoDB表自增值是存储在表对象中的,表对象又是放在缓存中的,如果表太多而不能全部放在缓存中的话,老的表就会被置换出来,这种被置换出来的表下次再使用的时候,就要重新打开一遍,对自增列来说,这个过程就和实例重启类似,需要 select max(id) + 1 算一下自增值。

    下面我们用testcase的方式来给出InnoDB表对象对置换出的场景:

    可以看到自增值确实和重启场景一样,本应是100,却变成了 2(select max(id) + 1)了。

    问题分析

    将老的table置换出:

    尝试从缓存加载表对象:

    缓存加载不到表对象,用select maxt 逻辑初始化自增:

    对于这个问题,一种解决方法是从源码改进,将自增值持久化,可以参考上期的月报给出的思路;如果不想改代码的话,可以这样绕过:在设定auto_increment值后,主动插入一行记录,这样不论在重启还是缓存淘汰的情况下,重新打开表仍能得到预期的值。