Bug #73563 | Replace result in auto_incrment value less or equal than max value in row-based | ||
---|---|---|---|
Submitted: | 13 Aug 2014 12:45 | Modified: | 13 Jul 2018 11:47 |
Reporter: | zhang yingqiang (OCA) | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Row Based Replication ( RBR ) | Severity: | S3 (Non-critical) |
Version: | 5.5.18 5.6.16, 5.6.21 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | auto_increment, duplicate key, replace into |
[13 Aug 2014 12:45]
zhang yingqiang
[14 Aug 2014 1:40]
liu hickey
It's a known issue for the effect of auto_increment in replace into. Though it's suggested to bypass with insert into ... on duplicate key, but why not just solve it if not too hard?
[14 Aug 2014 13:01]
MySQL Verification Team
Hello Zhang, Thank you for the bug report and test case. Verified as described. Thanks, Umesh
[14 Aug 2014 13:07]
MySQL Verification Team
// with 5.6.21 mysql-test]$ ./mysql-test-run.pl 73563 Logging: ./mysql-test-run.pl 73563 2014-08-16 05:42:33 13770 [Warning] Buffered warning: Changed limits: max_open_files: 1024 (requested 5000) 2014-08-16 05:42:33 13770 [Warning] Buffered warning: Changed limits: table_cache: 431 (requested 2000) 2014-08-16 05:42:33 13770 [Note] Plugin 'FEDERATED' is disabled. 2014-08-16 05:42:33 13770 [Note] Binlog end 2014-08-16 05:42:33 13770 [Note] Shutting down plugin 'CSV' 2014-08-16 05:42:33 13770 [Note] Shutting down plugin 'MyISAM' MySQL Version 5.6.21 Checking supported features... - SSL connections supported Collecting tests... Removing old var directory... Creating var directory '/data/ushastry/server/mysql-advanced-5.6.21/mysql-test/var'... Installing system database... ============================================================================== TEST RESULT TIME (ms) or COMMENT -------------------------------------------------------------------------- worker[1] Using MTR_BUILD_THREAD 300, with reserved ports 13000..13009 include/master-slave.inc Warnings: Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. [connection master] set global binlog_format = 'ROW'; set session binlog_format = 'ROW'; show global variables like '%binlog%'; Variable_name Value binlog_cache_size 32768 binlog_checksum CRC32 binlog_direct_non_transactional_updates ON binlog_format ROW binlog_max_flush_queue_time 0 binlog_order_commits ON binlog_row_image FULL binlog_rows_query_log_events OFF binlog_stmt_cache_size 32768 binlogging_impossible_mode IGNORE_ERROR innodb_api_enable_binlog OFF innodb_locks_unsafe_for_binlog OFF max_binlog_cache_size 18446744073709547520 max_binlog_size 1073741824 max_binlog_stmt_cache_size 18446744073709547520 sync_binlog 0 flush logs; include/stop_slave.inc set global binlog_format = 'ROW'; set session binlog_format = 'ROW'; show global variables like '%binlog%'; Variable_name Value binlog_cache_size 32768 binlog_checksum CRC32 binlog_direct_non_transactional_updates ON binlog_format ROW binlog_max_flush_queue_time 0 binlog_order_commits ON binlog_row_image FULL binlog_rows_query_log_events OFF binlog_stmt_cache_size 32768 binlogging_impossible_mode IGNORE_ERROR innodb_api_enable_binlog OFF innodb_locks_unsafe_for_binlog OFF max_binlog_cache_size 18446744073709547520 max_binlog_size 1073741824 max_binlog_stmt_cache_size 18446744073709547520 sync_binlog 0 include/start_slave.inc create table t1(a int auto_increment primary key, b int not null, c int not null, unique key uk_b(b)) engine=innodb; insert into t1 values(1,1,1),(2,2,2),(3,3,3); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL AUTO_INCREMENT, `b` int(11) NOT NULL, `c` int(11) NOT NULL, PRIMARY KEY (`a`), UNIQUE KEY `uk_b` (`b`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 select * from t1; a b c 1 1 1 2 2 2 3 3 3 show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL AUTO_INCREMENT, `b` int(11) NOT NULL, `c` int(11) NOT NULL, PRIMARY KEY (`a`), UNIQUE KEY `uk_b` (`b`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 select * from t1; a b c 1 1 1 2 2 2 3 3 3 replace into t1(b,c) values(1,10); replace into t1(b,c) values(2,11); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL AUTO_INCREMENT, `b` int(11) NOT NULL, `c` int(11) NOT NULL, PRIMARY KEY (`a`), UNIQUE KEY `uk_b` (`b`) ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1 select * from t1; a b c 3 3 3 4 1 10 5 2 11 show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL AUTO_INCREMENT, `b` int(11) NOT NULL, `c` int(11) NOT NULL, PRIMARY KEY (`a`), UNIQUE KEY `uk_b` (`b`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1 select * from t1; a b c 3 3 3 4 1 10 5 2 11 The auto_increment(4) is less then the max value(5). #now if master is crash, we consider slave as master, and write on slave(new master) connection slave set global read_only=0; replace into t1(b,c) values(9,12); ERROR 23000: Duplicate entry '4' for key 'PRIMARY'
[13 Jul 2018 11:47]
Daniel Price
Posted by developer: The following page was updated: https://dev.mysql.com/doc/refman/5.7/en/example-auto-increment.html Changes should appear online soon. Thank you for the bug report.
[13 Jul 2018 13:57]
Daniel Price
Posted by developer: Reopening for additional revisions.
[15 Jul 2018 19:56]
monty solomon
What was changed in the documentation? > The following page was updated: > https://dev.mysql.com/doc/refman/5.7/en/example-auto-increment.html
[16 Jul 2018 11:55]
Daniel Price
Posted by developer: The following behavior applies in MySQL 5.5, 5.6, and 5.7: "When you insert any other value into an AUTO_INCREMENT column, the column is set to that value and the sequence is reset so that the next automatically generated value follows sequentially from the largest column value. Updating an existing AUTO_INCREMENT column value in an InnoDB table does not reset the AUTO_INCREMENT sequence as it does for MyISAM and NDB tables." In MySQL 8.0, updating an existing AUTO_INCREMENT column value in an InnoDB table also resets the AUTO_INCREMENT sequence. https://dev.mysql.com/doc/mysql-tutorial-excerpt/5.7/en/example-auto-increment.html The revised documentation should appear online soon.
[20 Jul 2018 10:34]
Venkatesh Venugopal
Bug#87861 and Bug #65116 have been marked as duplicates of this bug.
[20 Jul 2018 14:24]
monty solomon
The documentation change appears to be unrelated to the REPLACE INTO replication bug. See more details in the bug #87861 and bug #65116. Please re-open this bug. Thanks.
[25 Jul 2018 6:48]
Venkatesh Venugopal
Hi Monty, The replace statement on master is considered as delete and insert. So, it increases the auto_incrment value. But in row-based replication, this replace is considered as an update event. The root cause for the bug is that InnoDB doesn't update the auto_increment value when the largest value in the auto_increment column was changed and this was against the documentation which said "When you insert any other value into an AUTO_INCREMENT column, the column is set to that value and the sequence is reset so that the next automatically generated value follows sequentially from the largest column value". The same can be observed in the below case. CREATE TABLE t1 (c1 INT NOT NULL DEFAULT '0') ENGINE=InnoDB; INSERT INTO t1(c1) VALUES (1), (2), (3); ALTER TABLE t1 ADD COLUMN c2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY; INSERT INTO t1(c1) VALUES (1000); SELECT * FROM t1; c1 c2 1 1 2 2 3 3 1000 4 UPDATE t1 SET c2= 1000 WHERE c1=1000; INSERT INTO t1(c1) VALUES (2000); # Since the largest value in the autoinc column was updated, # We expect c2=1001 when c1=2000, but it is 5. SELECT * FROM t1; c1 c2 1 1 2 2 3 3 2000 5 1000 1000 DROP TABLE t1; Fixing this may cause behavioral change for autoincrement in GA versions and may cause problems with replication between minor versions. However, the same has already been fixed in 8.0 by WL#6204 - InnoDB persistent max value for autoinc columns. Upgrading to 8.0 will fix the issue. Regards, Venkatesh Venugopal
[8 Oct 2018 18:04]
Fernando Camargos
A possible workaround for this bug for MySQL releases prior to 8 would be making the AUTO_INCREMENT sequence only UNIQUE, while making the previously UNIQUE field the new Primary Key of the table. So in the original: > create table t1(a int auto_increment primary key, b int not null, c int not null, unique key uk_b(b)) engine=innodb; `b` would be made the Primary Key while `a` would become UNIQUE. Trey and I blogged about this today.