看到這個問題,我想起當初玩魔獸世界的時候,25h難度的腦殘吼的血量已經超過了21億,所以那時候副本的boss都設計成了轉階段、回血的模式,因為魔獸的血量是int型,不能超過2^32大小。
這些都是題外話,只是告訴你資料量大了是有可能達到上限的而已,回到mysql自增id上限的問題,可以分為兩個方面來說。
如果設定了主鍵,並且一般會把主鍵設定成自增。
我們知道,mysql裡int型別是4個位元組,如果有符號位的話就是[-2^31,2^31-1],無符號位的話最大值就是2^32-1,也就是4294967295。
create table `test1` (
`id` int(11) not null auto_increment,
`name` varchar(32) not null default '',
primary key (`id`)
) engine=innodb auto_increment=2147483647 default charset=utf8mb4;
然後執行插入
insert into test1(name) values('qq');
這樣表裡就有一條達到有符號位的最大值上限的資料。
也就是說,如果設定了主鍵並且自增的話,達到自增主鍵上限就會報錯重複的主鍵key。
解決方案,mysql主鍵改為bigint,也就是8個位元組。
設計的時候要考慮清楚值的上限是多少,如果業務頻繁插入的話,21億的數字其實還是有可能達到的。
如果沒有設定主鍵的話,innodb則會自動幫你建立乙個6個位元組的row_id,由於row_id是無符號的,所以最大長度是2^48-1。
create table `test2` (
`name` varchar(32) not null default ''
) engine=innodb default charset=utf8mb4;
通過ps -ef|grep mysql
拿到mysql的程序id,然後執行命令,通過gdb先把row_id修改為1
sudo gdb -p 2584 -ex 'p dict_sys->row_id=1' -batch
insert into test2(name) values('1');
insert into test2(name) values('2');
insert into test2(name) values('3');
再次修改row_id為2^48,也就是281474976710656
sudo gdb -p 2584 -ex 'p dict_sys->row_id=281474976710656' -batch
再次插入資料
insert into test2(name) values('4');
insert into test2(name) values('5');
insert into test2(name) values('6');
然後查詢資料會發現3條資料是4,5,6,3。
因為我們先設定row_id=1開始,所以1,2,3的row_id也是1,2,3。
修改row_id為上限值之後,row_id會從0重新開始計算,所以4,5,6的row_id就是0,1,2。
由於1,2資料已經存在,資料則是會被覆蓋。
如果設定了主鍵,那麼將會報錯主鍵衝突。
如果沒有設定主鍵,資料庫則會幫我們自動生成乙個全域性的row_id,新資料會覆蓋老資料
表盡可能都要設定主鍵,主鍵盡量使用bigint型別,21億的上限還是有可能達到的,比如魔獸,雖然說row_id上限高達281萬億,但是覆蓋資料顯然是不可接受的。
- end -
資料庫自增id竟然被我用完了
事情的起因是這樣的 幾個月前做過乙個統計型別的job,上線之後小修小補了幾次一直執行的很平穩,就是有乙個缺點 慢。起初我一直以為是因為資料量過大導致的,每天早上六點準時開跑,一般要到下午一兩點才能跑完,其實現在想想這麼長時間的執行肯定是不合理的,而且本身業務的資料量也沒有大到那個地步,但是由於一直工...
資料庫ID自增優缺點?
優點 1.自增,趨勢自增,可作為聚集索引,提公升查詢效率 2.節省磁碟空間。500w資料,uuid佔5.4g,自增id佔2.5g.3.查詢,寫入效率高 查詢略優。寫入效率自增id是uuid的四倍。缺點 1.匯入舊資料時,可能會id重複,導致匯入失敗。2.分布式架構,多個mysql例項可能會導致id重...
面試官 說說資料庫事務吧
面試官在資料庫這方面最常問的除了sql優化,還有資料庫事務 儲存引擎等相關知識。上期有人說沒有自動門,所以這一期我特地造了自動門,這門沒有四五塊造不下來。注意 只是crud的搬磚工就不需要看了,看了也忘了,只需要拉到最後,點讚 在看 分享,一鍵三連然後收藏起來就行了。事務是指是程式中一系列嚴密的邏輯...