美文网首页
MySQL:5.7 自增字段的3个主键冲突问题

MySQL:5.7 自增字段的3个主键冲突问题

作者: 重庆八怪 | 来源:发表于2021-08-25 10:12 被阅读0次

注意:这些问题在8.0修复了。


1、主从replace语句,主键冲突

更新(update)主键自增值不会增加,导致主键冲突。这个问题同样存在于replace到从库上的更新因为row格式的binlog在从库应用的时候使用的是update,导致主键更新丢失自增,replace在主库是delete insert。
https://bugs.mysql.com/bug.php?id=73563

2、重启问题,主键冲突

重启数据库后innodb没有持久化,自增从表的最大记录开始,从而丢失自增值。并且5.7.17(第一次修复)/5.7.27(第二次修复)之前,可能导致重启后主键冲突的问题(auto_increment_increment大于1,)这个问题主要在于重启后初始化的时候
自增值在Innodb 体现为auto_increment+1,自增值的获取主要分为2个部分

  • ha_innobase::innobase_get_autoinc
    这个操作主要是在innodb层获取自增值,每个自增值保存在各自表的数据字典中,从获取到更改然后回写到表结构中增加的mutex保护,用于控制并发访问的问题。
    重启后初始化的值为auto_increment+1,那么第一次获取的是一个奇数值。第二次
    获取为偶数值(修复为在本函数中考虑auto_increment_increment的值)
  • handler::update_auto_increment
    mysql层拿到这个值后会根据自己的算法再次进行自增值的计算(某些引擎可能不会计算自增值), 调用为compute_next_insert_id,这个地方考虑auto_increment_increment,因此在Innodb层获取的一个奇数值和一个偶数值(比如5和6)都会返回6,因此造成了主键冲突。
  • ha_innobase::innobase_lock_autoinc
    这个函数就是我们的innodb_autoinc_lock_mode参数实现。

https://bugs.mysql.com/bug.php?id=76872
https://bugs.mysql.com/bug.php?id=67526

3、修改auto_increment_increment,主键冲突

在线修改auto_increment_increment可能导致BUG,如下测试(5.7.27之前),同时修复也是在5.7.27中。

drop table t;
CREATE TABLE t(
  a tinyint AUTO_INCREMENT PRIMARY KEY,
  b VARCHAR(200)) ENGINE=InnoDB;
SET SESSION auto_increment_increment=100;
INSERT INTO t(b) VALUES('S0');
INSERT INTO t(b) VALUES('S1');
-- SELECT a,b FROM t;
-- SHOW CREATE TABLE t;
INSERT INTO t(a,b) VALUES(28,'S2');
-- SELECT a,b FROM t;
SET SESSION auto_increment_increment=1;
-- result primary error
INSERT INTO t(b) VALUES('S3');

这里修复主要是在ha_innobase::innobase_get_autoinc删除了部分代码。
https://bugs.mysql.com/bug.php?id=76872

自增读取栈:

#0  ha_innobase::innobase_lock_autoinc (this=0x7fff91915db0) at /opt/percona-server-locks-detail-5.7.22/storage/innobase/handler/ha_innodb.cc:8126
#1  0x000000000198c3ed in ha_innobase::innobase_get_autoinc (this=0x7fff91915db0, value=0x7fffec14ca18)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/handler/ha_innodb.cc:17689
#2  0x000000000198c634 in ha_innobase::get_auto_increment (this=0x7fff91915db0, offset=2, increment=2, nb_desired_values=1, first_value=0x7fffec14cab0, nb_reserved_values=0x7fffec14caa8)
    at /opt/percona-server-locks-detail-5.7.22/storage/innobase/handler/ha_innodb.cc:17759
#3  0x0000000000f5a353 in handler::update_auto_increment (this=0x7fff91915db0) at /opt/percona-server-locks-detail-5.7.22/sql/handler.cc:3895
#4  0x000000000197a9e9 in ha_innobase::write_row (this=0x7fff91915db0, record=0x7fff90bec3f0 "\376") at /opt/percona-server-locks-detail-5.7.22/storage/innobase/handler/ha_innodb.cc:8308
#5  0x0000000000f640b6 in handler::ha_write_row (this=0x7fff91915db0, buf=0x7fff90bec3f0 "\376") at /opt/percona-server-locks-detail-5.7.22/sql/handler.cc:8466
#6  0x000000000178fb3e in write_record (thd=0x7fff90000b70, table=0x7fff91253690, info=0x7fffec14d000, update=0x7fffec14d080)
    at /opt/percona-server-locks-detail-5.7.22/sql/sql_insert.cc:1881
#7  0x000000000178cca0 in Sql_cmd_insert::mysql_insert (this=0x7fff90006ed8, thd=0x7fff90000b70, table_list=0x7fff90006820) at /opt/percona-server-locks-detail-5.7.22/sql/sql_insert.cc:773
#8  0x0000000001793615 in Sql_cmd_insert::execute (this=0x7fff90006ed8, thd=0x7fff90000b70) at /opt/percona-server-locks-detail-5.7.22/sql/sql_insert.cc:3121
#9  0x000000000156bc46 in mysql_execute_command (thd=0x7fff90000b70, first_level=true) at /opt/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:3746
#10 0x0000000001571bed in mysql_parse (thd=0x7fff90000b70, parser_state=0x7fffec14e5b0) at /opt/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:5901
#11 0x000000000156673d in dispatch_command (thd=0x7fff90000b70, com_data=0x7fffec14ed90, command=COM_QUERY) at /opt/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:1490
#12 0x00000000015655c5 in do_command (thd=0x7fff90000b70) at /opt/percona-server-locks-detail-5.7.22/sql/sql_parse.cc:1021
#13 0x00000000016a635c in handle_connection (arg=0x3bfe830) at /opt/percona-server-locks-detail-5.7.22/sql/conn_handler/connection_handler_per_thread.cc:312
#14 0x00000000018ce0ca in pfs_spawn_thread (arg=0x4007280) at /opt/percona-server-locks-detail-5.7.22/storage/perfschema/pfs.cc:2190
#15 0x00007ffff7bc6ea5 in start_thread () from /lib64/libpthread.so.0
#16 0x00007ffff66748dd in clone () from /lib64/libc.so.6

相关文章

网友评论

      本文标题:MySQL:5.7 自增字段的3个主键冲突问题

      本文链接:https://www.haomeiwen.com/subject/lossiltx.html