自增 ID 用完了怎麼辦

2021-09-18 08:14:40 字數 2996 閱讀 6765

引言

在面試中,大家應該經歷過如下場景:

面試官:"用過mysql吧,你們是用自增主鍵還是uuid?"   

你:"用的是自增主鍵"    

面試官:"為什麼是自增主鍵?"    

你:"因為採用自增主鍵,資料在物理結構上是順序儲存,效能最好,blabla…"    

面試官:"那自增主鍵達到最大值了,用完了怎麼辦?"    

你:"what,沒複習啊!!"    (然後,你就可以回去等通知了!)

這個問題是乙個粉絲給我提的,我覺得挺有意(keng)思(b)!

於是,今天我們就來談一談,這個自增主鍵用完了該怎麼辦!

正文簡單版

我們先明白一點,在mysql中,int整型的範圍如下:

我們以無符號整型為例,儲存範圍為0~4294967295,約43億!我們先說一下,一旦自增id達到最大值,此時資料繼續插入是會報乙個主鍵衝突異常如下所示:

//duplicate entry '4294967295' for key 'primary'
那解決方法也是很簡單的,將int型別改為bigint型別,bigint的範圍如下

就算你每秒10000條資料,跑100年,單錶的資料也才

10000*24*3600*365*100=31536000000000

這數字距離bigint的上限還差的遠,因此你將自增id設為bigint型別,你是不用考慮自增id達到最大值這個問題!

然而,如果你在面試中的回答如果是:

你:"簡單啊,把自增主鍵的型別改為bigint型別就好了!"

接下來,面試官可以問你乙個更坑的問題!

你:"what!我還是回等通知吧!"

怎麼改

所謂的mysql自己提供的功能也就是mysql自己原生的語句,例如我們要修改原欄位名稱及型別。

mysql> alter table table_name change old_field_name new_field_name field_type;
那麼,在mysql5.5這個版本之前,這是通過臨時表拷貝的方式實現的。執行alter語句後,會新建乙個帶有新結構的臨時表,將原表資料全部拷貝到臨時表,然後rename,完成建立操作。這個方式過程中,原表是可讀的,不可寫。

那麼,對於修改列的資料型別這種操作,原表還能寫麼?來來來,煙哥特意去官網找了mysql8.0版本的一張圖:

因此,直接 alter 是不行滴!

那我們只能用方式二或者方式三

方式二: 借助第三方工具

以pt-osc為例,它的原理如下

1、建立乙個新的表,表結構為修改後的資料表,用於從源資料表向新錶中匯入資料。

2、建立觸發器,用於記錄從拷貝資料開始之後,對源資料表繼續進行資料修改的操作記錄下來,用於資料拷貝結束後,執行這些操作,保證資料不會丟失。

3、拷貝資料,從源資料表中拷貝資料到新錶中。

4、rename源資料表為old表,把新錶rename為源表名,並將old表刪除。

5、刪除觸發器。

然而這兩個有意(keng)思(b)的工具,居然。。。居然。。。唉!如果你的表裡有觸發器和外來鍵,這兩個工具是不行滴!

如果真碰上了資料庫裡有觸發器和外來鍵,只能硬槓了,請看方式三

方式三: 改從庫表結構,然後主從切換

此法極其麻煩,需要專業水平的選手進行操作。因為我們的mysql架構一般是讀寫分離架構,從機是用來讀的。我們直接在從庫上進行表結構修改,不會阻塞從庫的讀操作。改完之後,進行主從切換即可。唯一需要注意的是,主從切換過程中可能會有資料丟失的情況!

高深版

其實答完上面的問題後,這篇文章差不多完了。但是,還記得我在開頭說的麼。這是乙個很有意(keng)思(b)的問題,為什麼呢?

假設啊,你的表裡的自增字段為有符號的int型別的,也就是說,你的字段範圍為-2147483648到2147483648。

一切又那麼剛好,你的自增id是從0開始的,也就是說,現在你的可以用的範圍為0~2147483648。

我們明確一點,表中真實的資料id,肯定會出現一些意外,id不一定是連續的。例如,有如下情形的出現:

create table `t` (

`id` int(11) not null auto_increment,

primary key (`id`),

) engine=innodb;

執行下列sql

insert into t values(null);

// 插入的行是 (1)

begin;

insert into t values(null);

rolllack;

insert into t values(null);

// 插入的行是 (3)

因此,表中的真實id必然會出現斷續的情況。

好,那這會你的自增主鍵id的資料範圍為0~2147483648,也就是單錶21億條資料!考慮id會出現斷續,真實資料頂多18億條吧。

老哥,都單錶18億條了,還不分庫分表?你一旦分庫分表了,就不能依賴於每個表的自增id來全域性唯一標識這些資料了。此時,我們就需要提供一 個全域性唯一的id號生成策略來支援分庫分表的環境。

因此在實際中,你根本等不到自增主鍵用完到情形!

所以,專業版回答如下:

面試官:"那自增主鍵達到最大值了,用完了怎麼辦?"   

你:"這問題沒遇到過,因為自增主鍵我們用int型別,一般達不到最大值,我們就分庫分表了,所以不曾遇見過!"

MySQL中的自增主鍵用完了怎麼辦

目錄 一場面試引發的血案。引發的問題 解決方案 擴充套件 借助第三方工具 改從庫表結構,然後主從切換 專業版回答 面試官 用過mysql吧,你們是用自增主鍵還是uuid?你 用的是自增主鍵 面試官 為什麼是自增主鍵?你 因為採用自增主鍵,資料在物理結構上是順序儲存,效能最好,blabla 面試官 那...

資料庫自增id竟然被我用完了

事情的起因是這樣的 幾個月前做過乙個統計型別的job,上線之後小修小補了幾次一直執行的很平穩,就是有乙個缺點 慢。起初我一直以為是因為資料量過大導致的,每天早上六點準時開跑,一般要到下午一兩點才能跑完,其實現在想想這麼長時間的執行肯定是不合理的,而且本身業務的資料量也沒有大到那個地步,但是由於一直工...

面試官 資料庫自增ID用完了會怎麼樣?

看到這個問題,我想起當初玩魔獸世界的時候,25h難度的腦殘吼的血量已經超過了21億,所以那時候副本的boss都設計成了轉階段 回血的模式,因為魔獸的血量是int型,不能超過2 32大小。這些都是題外話,只是告訴你資料量大了是有可能達到上限的而已,回到mysql自增id上限的問題,可以分為兩個方面來說...