CREATE TABLE `t` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`age` int(11) DEFAULT NULL,
`msg` varchar(10) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uniq_age` (`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into t (age, msg) values (1,'aaa'),(2,'bbb'),(3,'ccc');
id 为自增主键、age 为 唯一键
尝试在主数据库执行 replace into
replace into t (age, msg) values (1, '111');
因为 age 为 1 已经存在了
所以这里会先执行 delete 然后再执行 insert 、那么则会导致 AUTO_INCREMENT=5 了
但是对于 binlog 来说、仅仅是产生了一条 update 语句。
这样子的话、会导致从数据库那边的 AUTO_INCREMENT 还是 4
主从切换、新主插入失败
我们现在直接看下最新的数据
我们可以看到主数据现在的 AUTO_INCREMENT 的值为 18 、是符合预期的
我们再看看从数据库
可以看到从数据库现在的 AUTO_INCREMENT 为 13 、是比主数据看落后的
现在我们直接将主数据库杀掉、从数据库成为新主、然后尝试 replace into 或者 insert into (不设置 id 的值)
那么会报错主键冲突、插入失败、AUTO_INCREMENT 变为 14
一直直到 AUTO_INCREMENT 的值为 18
正常情况下、insert 失败 AUTO_INCREMENT 是不会变化的
如果在这个过程中、我们指定 id 的值、那么 AUTO_INCREMENT 就会变成 id + 1(这个跟正常情况是一样的)
小结一下
- insert 成功 AUTO_INCREMENT 会取当前 insert 的 id 的值 +1
- 正常情况下 insert 失败不会导致 AUTO_INCREMENT 变化
- 新主 AUTO_INCREMENT 落后于表中最大值时、即使是失败也会导致 AUTO_INCREMENT+1
生产上试过主从切换后、replace into 一直插入失败 、最终的结果是 DBA 手动指定自增列的值、该值为当前表中的最大值、才将 AUTO_INCREMENT 的值回归到正常的值。因为新主当时 AUTO_INCREMENT 的值已经落后很多了、插入一直失败、业务受到影响。
当然重启新主也可以重置 AUTO_INCREMENT
建表时可以指定 AUTO_INCREMENT值,不指定时默认为1,这个值表示当前自增列的起始值大小,如果新插入的数据没有指定自增列的值,那么自增列的值即为这个起始值。对于InnoDB表,这个值没有持久到文件中。而是存在内存中(dict_table_struct.autoinc)。那么又问,既然这个值没有持久下来,为什么我们每次插入新的值后, show create table t1看到AUTO_INCREMENT值是跟随变化的。其实show create table t1是直接从dict_table_struct.autoinc取得的(ha_innobase::update_create_info)。
以上测试对insert into … on duplicate key update语句同样效果
insert into … on duplicate key update 会产生死锁问题(看下面的链接)、没有验证过
replace into 这个 bug 在 Mysql 5.7 中存在、但是在 mysql 8.0 的时候已经被修复了
在mysql8.0版本中不仅将AUTO_INCREMENT值做了持久化,且在做更新操作时,如果表上的自增列被更新为比auto_increment更大的值,auto_increment值也将被更新。
神奇的是 inert into … on duplicate key update AUTO_INCREMENT 的问题还是没有被修复
https://mckobe23.github.io/2016/07/22/replace-autoincrement/
https://yangwuyuan.com/2019/05/10/REPLACE%E6%93%8D%E4%BD%9C%E5%AF%BC%E8%87%B4%E4%B8%BB%E4%BB%8E%E5%BA%93AUTO-INCREMENT%E4%B8%8D%E4%B8%80%E8%87%B4%E7%9A%84%E5%88%86%E6%9E%90/#REPLACE%E6%93%8D%E4%BD%9C%E5%AF%BC%E8%87%B4AUTO-INCREMENT%E5%80%BC%E4%B8%8D%E4%B8%80%E8%87%B4
https://www.cnblogs.com/better-farther-world2099/articles/11737376.html
本文由mdnice多平台发布