最近在排查問題時,發現一個表自增列的值不連續。在排除了刪除、更新的場景後,懷疑與replace into語句有關。特地重現了下。
如果一個表,同時存在自增主鍵和唯一鍵。replace into
時,如果一行數據中唯一鍵是存在的,該行數據指定了新的主鍵值或不指定主鍵值,會導致主鍵被更新成新值。
下面用例子演示一下問題。
初始化測試表和數據
/** 1.1 創建測試表,含自增主鍵、唯一鍵 */
mysql> create table test_replace (id int not null auto_increment, code char(1), title varchar(64), primary key (id), unique key key_code(code));
Query OK, 0 rows affected (0.03 sec)
/** 1.2 插入測試數據,自增主鍵 */
mysql> insert into test_replace (code, title) values ('a', 'first record'), ('b', 'second record');
Query OK, 2 rows affected (0.01 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> select * from test_replace;
+----+------+---------------+
| id | code | title |
+----+------+---------------+
| 1 | a | first record |
| 2 | b | second record |
+----+------+---------------+
2 rows in set (0.00 sec)
重現風險
/** 2.1 執行replace into,唯一鍵已存在、但主鍵是新生成的 */
mysql> replace into test_replace values (3, 'a', 'first record replaced');
Query OK, 2 rows affected (0.01 sec)
mysql> select * from test_replace;
+----+------+-----------------------+
| id | code | title |
+----+------+-----------------------+
| 2 | b | second record |
| 3 | a | first record replaced |
+----+------+-----------------------+
2 rows in set (0.00 sec)
/** 2.2 執行replace into,唯一鍵已存在、但主鍵未指定,由數據庫處理 */
mysql> replace into test_replace values (null, 'a', 'first record replaced 2');
Query OK, 2 rows affected (0.01 sec)
mysql> select * from test_replace;
+----+------+-------------------------+
| id | code | title |
+----+------+-------------------------+
| 2 | b | second record |
| 4 | a | first record replaced 2 |
+----+------+-------------------------+
2 rows in set (0.00 sec)
嚴格來講這個瓜是replace into
的,但是MySQL的自增實在是有太多的坑和細節了,我就是想吐槽AUTO_INCREMENT
。 當然自己去實現自增器,也不見得比MySQL做得好。
MySQL自增列使用可參考《MySQL自增列AUTO_INCREMENT詳解(含NULL值、初始值、指定值等說明)》
以上。感謝您的閱讀。