面試遇到乙個問題,設定自增主鍵的資料型別為int(10),範圍設定的比較小,如果自增超過這個範圍會怎麼樣?當時一臉懵逼,確實沒考慮過這個情況。
思路與猜測
首先是知道,字段型別宣告為int(10),後面的長度10只是zerofill的長度,不影響資料的儲存,也就是自增超過的範圍應該是int型別欄位的最大值。
型別儲存占用位元組
最小值最大值
無符號int40
4294967295(2^32-1)
有符號int
4-2147483648(-2^31)
2147483647(2^31-1)
對於無符號的自增主鍵,也就是超過2^32-1=4294967295。由於不知道會發生什麼,有幾種猜測:
重新從0開始?
直接返回錯誤碼?
驗證與結果
新建乙個表用於測試自增;為了驗證問題,把自增值設定到了最大值-2,用於測試。
create
table
`auto_inc `
(`id`
int(1)
unsigned
notnull
auto_increment
,`name`
varchar(64
)character
set utf8mb4 collate utf8mb4_general_ci not
null
primary
key(
`id`
)using
btree
)engine
=innodb
auto_increment
=4294967294
character
set= utf8mb4 collate
= utf8mb4_general_ci row_format = dynamic;
先插入一條資料,能夠插入成功,自增值上公升1;
mysql>
insert
into auto_inc(name)
values(''
);query ok,
1row affected (
0.04 sec)
mysql>
select
*from auto_inc;
+------------+------+
| id | name |
+------------+------+
|4294967294||
+------------+------+
1row
inset
(0.03 sec)
然後繼續插入兩條資料;發現第二條插入資料報錯了,主鍵衝突,而此時表裡最大的id是4294967295
mysql>
insert
into auto_inc(name)
values(''
);query ok,
1row affected (
0.04 sec)
mysql>
insert
into auto_inc(name)
values(''
);1062
-duplicate entry '4294967295'
forkey
'primary'
mysql>
select
*from auto_inc;
+------------+------+
| id | name |
+------------+------+
|4294967294||
|4294967295||
+------------+------+
2rows
inset
(0.04 sec)
所以可以得出結論:自增主鍵超過資料型別的最大值後,會繼續使用最大值作為下一次的遞增值,如果最大值記錄在表中已經存在,會報主鍵衝突錯誤;
這個問題用smallint和tinyint做自增鍵也可以復現,而且不需要設定自增值。
沒有意義。面試的時候可以考你一下。
如果是smallint或tinyint型別的自增主鍵溢位,那只能說表設計的不合理,用範圍這麼小的型別做主鍵欄位;
如果是int型別的自增主鍵溢位,int範圍都21億了,再加上主鍵一般無符號,42億的取值範圍不夠用?即便插入報錯之類的導致主鍵不連續,那30多億有效主鍵總有吧,mysql乙個表30億資料,想啥呢老哥,還不考慮分庫分表?
至於bigint……
可能mysql的開發人員也覺得這樣的情況應該由開發者決定怎麼處理,所以就在溢位後仍使用最大值?
todo
mysql 自增字段原理 MySQL自增字段暴增
找了點資料 從網上看到一篇文章,mysql在檢測到表中有損壞的記錄時,會自動修復,為了保證資料的完整性,mysql會以空格 0x20 寫進磁碟來完成修復。根據欄位的型別,自增字段的長度不同,所允許的最大值也不同。見下 int 10 unsigned型別最大值十進位制為4294967295,十六進製制...
Mysql自增字段
1.關鍵字 auto increment 2.自增用法 例 create table animals id mediumint not null auto increment,name char 30 not null,primary key id 3.關於自增 q 怎麼獲得當前的自增的最大值?q ...
mysql自增字段重排
由於刪除了某些記錄行,所以自增字段不連續了。重排或歸零的方法 方法1 truncate table 你的表名 這樣不但重新定位自增的字段,而且會將表裡的資料全部刪除,慎用!方法2 delete from 你的表名 dbcc checkident 你的表名,reseed,0 重新定位自增的字段,讓它從...