1. 程式人生 > 資料庫 >MySQL的自增ID(主鍵) 用完了的解決方法

MySQL的自增ID(主鍵) 用完了的解決方法

在 MySQL 中用很多型別的自增 ID,每個自增 ID 都設定了初始值。一般情況下初始值都是從 0 開始,然後按照一定的步長增加(一般是自增 1)。一般情況下,我們都是用int(11)來作為資料表的自增 ID,在 MySQL 中只要定義了這個數的位元組長度,那麼就會有上限。

MySQL的自增ID(主鍵) 用完了,怎麼辦?

如果用 int unsigned (int,4個位元組 ),我們可以算下最大當前宣告的自增ID最大是多少,由於這裡定義的是 int unsigned,所以最大可以達到2的32冪次方 - 1 = 4294967295。

這裡有個小技巧,可以在建立表的時候,直接宣告AUTO_INCREMENT的初始值為4294967295。

create table `test` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4294967295;

SQL插入語句

insert into `test` values (null);

當想再嘗試插入一條資料時,得到了下面的異常結果。

[SQL] insert into `test` values (null);
[Err] 1062 - Duplicate entry '4294967295' for key 'PRIMARY'

說明,當再次插入時,使用的自增ID還是 4294967295,報主鍵衝突的錯誤,這說明 ID 值達到上限之後,就不會再變化了。4294967295,這個數字已經可以應付大部分的場景了,如果你的服務會經常性的插入和刪除資料的話,還是存在用完的風險,建議採用 bigint unsigned ,這個數字就大了。

bigint unsigned 的範圍是 -2^63 (-9223372036854775808) 到 2^63-1 (9223372036854775807) 的整型資料(所有數字), 儲存大小為 8 個位元組。

不過,還存在另一種情況,如果在建立表沒有顯示申明主鍵,會怎麼辦?

如果是這種情況,InnoDB會自動幫你建立一個不可見的、長度為6位元組的row_id,而且InnoDB 維護了一個全域性的 dictsys.row_id,所以未定義主鍵的表都共享該row_id,每次插入一條資料,都把全域性row_id當成主鍵id,然後全域性row_id加 1。

該全域性row_id在程式碼實現上使用的是bigint unsigned型別,但實際上只給row_id留了6位元組,這種設計就會存在一個問題:如果全域性row_id一直漲,一直漲,直到2的48冪次-1時,這個時候再+1,row_id的低48位都為0,結果在插入新一行資料時,拿到的row_id就為0,存在主鍵衝突的可能性。

所以,為了避免這種隱患,每個表都需要定一個主鍵。

總結

資料庫表的自增 ID 達到上限之後,再申請時它的值就不會在改變了,繼續插入資料時會導致報主鍵衝突錯誤。因此在設計資料表時,儘量根據業務需求來選擇合適的欄位型別。

以上就是MySQL的自增ID(主鍵) 用完了的解決方法的詳細內容,更多關於MySQL 自增ID(主鍵)的資料請關注我們其它相關文章!