Bug #77743 Auto-increment sequence gets reset

Submitted: 16 Jul 2015 3:38 Modified: 27 Jul 2015 20:05
Reporter: Marcos Albe (OCA) Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server: InnoDB storage engine Severity:S2 (Serious)
Version:5.6.25, 5.6.27 OS:Any
Assigned to: CPU Architecture:Any
Tags: `, auto increment, table_open_cache

[16 Jul 2015 3:38] Marcos Albe
Description:
If we insert a row into a table with an auto-increment primary key and then we empty the table using DELETE without conditions, and then we run statements for a number of tables noticeably larger than table-open-cache  then the auto-inc sequence is reset and next INSERT into the table will get an insert_id of 1

We tried SELECTs and EXPLAINs and either produce the issue; The attached script is using EXPLAIN because it seems to show the problem faster.

How to repeat:
Run the attached script like

reproduce.sh 100 2000 10 innodb;

Usage: resetai.sh <table_open_cache> <tables count> <sleep interval> <engine>;

Suggested fix:
Don't allow the sequence to be reset unless table is truncated or altered.
[16 Jul 2015 3:39] Marcos Albe
Bash script to reproduce the issue

Attachment: reproduce.sh (application/x-shellscript, text), 1.76 KiB.

[16 Jul 2015 3:46] Marcos Albe
Fixed typo in synopsis
[16 Jul 2015 4:44] MySQL Verification Team
Hello Marcos,

Thank you for the report and test case.
Observed this with 5.6.27 build with innodb engine.

Thanks,
Umesh
[16 Jul 2015 4:48] MySQL Verification Team
// 5.6.27

[umshastr@hod03]/export/umesh/server/binaries/mysql-advanced-5.6.27: ./reproduce.sh 100 2000 10 innodb;
initial auto-inc value: 3... Sleeping 10
final auto-inc value: 1
FAILED!!, with 2000 innodb tables and table_open_cache=100; sleep set to 10.

Above should be more than enough to confirm, but just tried to see again:

[umshastr@hod03]/export/umesh/server/binaries/mysql-advanced-5.6.27: bin/mysql -uroot -S /tmp/mysql_ushastry.sock
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4019
Server version: 5.6.27-enterprise-commercial-advanced MySQL Enterprise Server - Advanced Edition (Commercial)

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use TESTAI
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> DROP TABLE IF EXISTS TESTAI.every5minutes;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE TABLE TESTAI.every5minutes (
    -> Id int(11) NOT NULL AUTO_INCREMENT,
    -> ActionId int(11) NOT NULL DEFAULT '0',
    -> ItemId int(11) NOT NULL DEFAULT '0',
    -> PRIMARY KEY (Id),
    -> KEY ActionId (ActionId),
    -> KEY ItemId (ItemId)
    -> ) ENGINE=InnoDB DEFAULT CHARSET=latin1 CHECKSUM=1;
Query OK, 0 rows affected (0.00 sec)

mysql> show create table TESTAI.every5minutes\G
*************************** 1. row ***************************
       Table: every5minutes
Create Table: CREATE TABLE `every5minutes` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `ActionId` int(11) NOT NULL DEFAULT '0',
  `ItemId` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`Id`),
  KEY `ActionId` (`ActionId`),
  KEY `ItemId` (`ItemId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 CHECKSUM=1
1 row in set (0.00 sec)

mysql> INSERT INTO TESTAI.every5minutes SET id=2;
Query OK, 1 row affected (0.00 sec)

mysql> show create table TESTAI.every5minutes\G
*************************** 1. row ***************************
       Table: every5minutes
Create Table: CREATE TABLE `every5minutes` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `ActionId` int(11) NOT NULL DEFAULT '0',
  `ItemId` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`Id`),
  KEY `ActionId` (`ActionId`),
  KEY `ItemId` (`ItemId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 CHECKSUM=1
1 row in set (0.00 sec)

mysql> DELETE FROM TESTAI.every5minutes;
Query OK, 1 row affected (0.00 sec)

mysql> show create table TESTAI.every5minutes\G
*************************** 1. row ***************************
       Table: every5minutes
Create Table: CREATE TABLE `every5minutes` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `ActionId` int(11) NOT NULL DEFAULT '0',
  `ItemId` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`Id`),
  KEY `ActionId` (`ActionId`),
  KEY `ItemId` (`ItemId`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1 CHECKSUM=1
1 row in set (0.00 sec)

mysql> source /export/umesh/server/binaries/mysql-advanced-5.6.27/5_6_27.explains.new;
Database changed
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                                              |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
|  1 | SIMPLE      | t1    | ALL   | NULL          | NULL    | NULL    | NULL |    1 | NULL                                               |
|  1 | SIMPLE      | t     | range | PRIMARY       | PRIMARY | 4       | NULL |    1 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
2 rows in set (0.00 sec)

+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                                              |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
|  1 | SIMPLE      | t2    | ALL   | NULL          | NULL    | NULL    | NULL |    1 | NULL                                               |
|  1 | SIMPLE      | t     | range | PRIMARY       | PRIMARY | 4       | NULL |    1 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
2 rows in set (0.00 sec)

.
.
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                                              |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
|  1 | SIMPLE      | t1999 | ALL   | NULL          | NULL    | NULL    | NULL |    1 | NULL                                               |
|  1 | SIMPLE      | t     | range | PRIMARY       | PRIMARY | 4       | NULL |    1 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
2 rows in set (0.00 sec)

+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                                              |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
|  1 | SIMPLE      | t2000 | ALL   | NULL          | NULL    | NULL    | NULL |    1 | NULL                                               |
|  1 | SIMPLE      | t     | range | PRIMARY       | PRIMARY | 4       | NULL |    1 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+-------+---------------+---------+---------+------+------+----------------------------------------------------+
2 rows in set (0.00 sec)

mysql> show create table TESTAI.every5minutes\G
*************************** 1. row ***************************
       Table: every5minutes
Create Table: CREATE TABLE `every5minutes` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `ActionId` int(11) NOT NULL DEFAULT '0',
  `ItemId` int(11) NOT NULL DEFAULT '0',
  PRIMARY KEY (`Id`),
  KEY `ActionId` (`ActionId`),
  KEY `ItemId` (`ItemId`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 CHECKSUM=1
1 row in set (0.00 sec)

## with myisam

[umshastr@hod03]/export/umesh/server/binaries/mysql-advanced-5.6.27: ./reproduce.sh 100 2000 10 myisam;
initial auto-inc value: 3... Sleeping 10
final auto-inc value: 3
Passed, with 2000 myisam tables and table_open_cache=100; sleep set to 10.
[16 Jul 2015 5:12] MySQL Verification Team
// 5.7.9 build seems to be not affected

[umshastr@hod03]/export/umesh/server/binaries/mysql-advanced-5.7.9: ./reproduce.sh 100 2000 10 innodb;
initial auto-inc value: 3... Sleeping 10
final auto-inc value: 3
Passed, with 2000 innodb tables and table_open_cache=100; sleep set to 10.
[16 Jul 2015 5:16] MySQL Verification Team
// 5.5.46 build not affected as well
[umshastr@hod03]/export/umesh/server/binaries/mysql-5.5.46: ./reproduce.sh 100 2000 10 innodb;
initial auto-inc value: 3... Sleeping 10
final auto-inc value: 3
Passed, with 2000 innodb tables and table_open_cache=100; sleep set to 10.
[23 Jul 2015 0:09] Sveta Smirnova
Umesh, can you check if this is related to bug #76037?
[24 Jul 2015 12:14] Shaohua Wang
Posted by developer:
 
autoinc is reset to 0 when table is loaded after table is evicted without any rows. The solution is store autoinc value in a map when table is evicted, and restore autoinc when table is loaded.

Pushed the fixed to 5.6 & 5.7. In trunk, WL#6204 - InnoDB persistent max value for autoinc columns will fix the bug(rb#9138).
[24 Jul 2015 12:46] Sveta Smirnova
Thank you for the quick fix,  Shaohua!
[27 Jul 2015 20:05] Daniel Price
Fixed as of the upcoming 5.6.27, 5.7.9, 5.8.0 releases, and here's the changelog entry:

Reloading a table that was evicted while empty caused an AUTO_INCREMENT
value to be reset. 

Thank you for the bug report.
[28 Jul 2015 17:10] Sveta Smirnova
Shaohua,

did you test cases when table includes few rows (not 100% empty), but auto-increment field still reset? We saw such a case in the environment where bug occurred first time.
[29 Jul 2015 4:16] Shaohua Wang
Sveta, if reset means auto_increment starts from 1, I don't see such case
with a few rows. When a table is loaded, we usually search for max
auto_increment value in the table, that's why auto_increment gets reset with
empty table. after all, the patch pushed fixed all such reset issues.
[20 Aug 2015 19:46] Sveta Smirnova
Tese case for situation when table is not empty

Attachment: reproduce_non_empty.sh (application/x-shellscript, text), 1.82 KiB.

[21 Sep 2015 10:27] MySQL Verification Team
Bug #78491 marked as duplicate of this

Portions of this website are copyright © 2001, 2002 The PHP Group

Page generated in 0.068 sec. using MySQL 8.4.7-u6-cloud

Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the respective copyright holders.
It is not reviewed in advance by Oracle and does not necessarily represent the opinion of Oracle or any other party.