字節(jié)面試:MySQL自增ID用完會怎樣?
在一些中小型項(xiàng)目開發(fā)中,我們通常會使用自增 ID 來作為主鍵的生成策略,但隨著時(shí)間的推移,數(shù)據(jù)庫的信息也會越來越多,尤其是使用自增 ID 作為日志表的主鍵生成策略時(shí),可能很快就會遇到 ID 被用完的情況,那么如果發(fā)生了這種情況,MySQL 又會怎樣執(zhí)行呢?
PS:當(dāng)然,在分庫分表的場景中,我們通常會使用雪花算法來替代自增 ID,但中小型項(xiàng)目開發(fā)中,使用自增 ID 的場景還是比較多的。
1.自增ID
在 MySQL 中,如果字段的數(shù)據(jù)類型為整數(shù)類型(如 INT、BIGINT 等),則可以通過關(guān)鍵字“AUTO_INCREMENT”來設(shè)置讓當(dāng)前的字段實(shí)現(xiàn)自增,例如以下 SQL:
CREATE TABLE example_table (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(128)
);
1.1 優(yōu)點(diǎn)分析
自增 ID 的優(yōu)點(diǎn)如下:
- 簡單方便,能自動為每行數(shù)據(jù)分配唯一的標(biāo)識。
- 對于按順序插入的數(shù)據(jù),能很好地反映數(shù)據(jù)插入的先后順序。
1.2 缺點(diǎn)分析
自增 ID 的缺點(diǎn)如下:
- 在數(shù)據(jù)進(jìn)行遷移或分庫分表時(shí),可能會出現(xiàn)問題,需要特殊處理。
- 如果數(shù)據(jù)量非常大,可能會達(dá)到自增 ID 的上限。
- 存在安全性問題,比如通過自增 ID 可能會推測出一些業(yè)務(wù)信息。例如,一個(gè)電商訂單表使用自增 ID 作為主鍵,可能會被競爭對手通過訂單號大致推測出業(yè)務(wù)量等信息。
2.自增ID用完會怎樣?
自增 ID 分為以下兩種情況:
圖片
一種是主鍵自增 ID 用完后的情況,另一種是 InnoDB 引擎中未設(shè)置主鍵時(shí)使用 row_id 用完后的場景,它們的情況是不一樣的,所以我們分開來聊。
2.1 主鍵自增ID用完
當(dāng)主鍵自增 ID 達(dá)到上限后,再新增下一條數(shù)據(jù)時(shí),它的 ID 不會變(還是最大的值),只是此時(shí)再添加數(shù)據(jù)時(shí),因?yàn)橹麈I約束的原因,ID 是不允許重復(fù)的,所以就會報(bào)錯(cuò)提示主鍵沖突。
我們可以使用以下 SQL 來測試:
CREATE TABLE t (
id INT AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(128)
) auto_increment=2147483647;
insert into t(id,`name`) values(null,'javacn.site');
select * from t;
insert into t(id,`name`) values(null,'www.javacn.site');
以上 SQL 是創(chuàng)建了一個(gè)表 t,并且給 t 表的主鍵 id 設(shè)置自增 ID,之后再將表的自增 ID 初始化為 INT(有符號)的最大值 2147483647,然后再添加兩條數(shù)據(jù)。
以上 SQL 的執(zhí)行結(jié)果如下:
圖片
從上面的執(zhí)行結(jié)果可以看出:當(dāng)主鍵自增 ID 達(dá)到上限后,再新增下一條數(shù)據(jù)時(shí),它的 ID 不會變(還是最大的值),只是此時(shí)再添加數(shù)據(jù)時(shí),因?yàn)橹麈I約束的原因,ID 是不允許重復(fù)的,所以就會報(bào)錯(cuò)提示主鍵沖突。
2.2 row_id用完
如果表沒有設(shè)置主鍵,InnoDB 會自動創(chuàng)建一個(gè)全局隱藏的 row_id,其長度為 6 個(gè)字節(jié),當(dāng) row_id 達(dá)到上限后,它的執(zhí)行流程和主鍵 ID 不同,它是再次歸零,然后重新遞增,如果出現(xiàn)相同的 row_id,后面的數(shù)據(jù)會覆蓋之前的數(shù)據(jù)。