1. 程式人生 > 其它 >Mysql 自增主鍵回溯的坑

Mysql 自增主鍵回溯的坑

使用mysql的時候,很多時候用自增主鍵。正常使用一般是沒有問題的,但是極小概率情況下會碰到主鍵回溯的問題。在業務上可能造成id一樣,但是對應的業務資料不一樣的問題。這個問題發生在Mysql 8.0版本之前。

出現場景: 插入一條資料返回主鍵3, 接著刪除了主鍵為3的資料,這個時候突然資料庫宕機了,重啟之後再進行插入,返回的主鍵還是3。正常這個時候應該是返回主鍵4的,與預期不一致,對業務資料會造成不一致。

模擬場景
1、建一張表:

mysql> CREATE TABLE t (
    ->      a INT AUTO_INCREMENT PRIMARY KEY,
    ->      b VARCHAR(255) default null
    ->  );
Query OK, 0 rows affected (0.03 sec)

2, 插入資料:

mysql> insert into t(`b`) values ('xxx'),('yyy'),('zzz');
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

3, 檢視插入的資料

mysql> select * from t;
+---+------+
| a | b    |
+---+------+
| 1 | xxx  |
| 2 | yyy  |
| 3 | zzz  |
+---+------+
3 rows in set (0.00 sec)

4, 刪除主鍵為3的資料

mysql> delete from t where a=3;
Query OK, 1 row affected (0.01 sec)

5,這個時候如果直接插入資料,返回的主鍵是4,這是正常的行為。但是如果這個時候突然宕機了,重啟再插入資料,返回的主鍵還是3。這裡只模擬異常情況,將mysql伺服器重啟,然後再插入資料。

mysql> insert into t (`b`) values ('new_line');
Query OK, 1 row affected (0.00 sec)

mysql> select * from t;
+---+----------+
| a | b        |
+---+----------+
| 1 | xxx      |
| 2 | yyy      |
| 3 | new_line |
+---+----------+
3 rows in set (0.00 sec)

6、可以看到剛插入的資料,主鍵還是3。

原因解釋: MySQL 8.0 版本前,自增不持久化,資料庫重啟時會發生主鍵回溯。
解決方法

  • 升級 MySQL 版本到 8.0 版本,每張表的自增值會持久化;
  • 若無法升級資料庫版本,則強烈不推薦在核心業務表中使用自增資料型別做主鍵。

造成影響:如果前端插入一條user的資料,返回給前端一個id,這個時候如果有客戶端刪除了這個id對應的資料,剛好宕機,重啟後又插入一條新的user資料,那麼會覆蓋掉之前的user。這是非常嚴重的業務資料錯亂,造成生產事故的。