Mysql自增id的示例分析

這篇文章主要為大家展示了“MySQL自增id的示例分析”,內(nèi)容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領(lǐng)大家一起研究并學(xué)習(xí)一下“Mysql自增id的示例分析”這篇文章吧。

成都創(chuàng)新互聯(lián)公司專注于萊蕪企業(yè)網(wǎng)站建設(shè),響應(yīng)式網(wǎng)站,商城系統(tǒng)網(wǎng)站開發(fā)。萊蕪網(wǎng)站建設(shè)公司,為萊蕪等地區(qū)提供建站服務(wù)。全流程按需網(wǎng)站制作,專業(yè)設(shè)計,全程項目跟蹤,成都創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

導(dǎo)讀:

在使用MySQL建表時,我們通常會創(chuàng)建一個自增字段(AUTO_INCREMENT),并以此字段作為主鍵。本篇文章將以問答的形式講述關(guān)于自增id的一切。

注:本文所講的都是基于Innodb存儲引擎。

1.MySQL為什么建議將自增列id設(shè)為主鍵?

  • 如果我們定義了主鍵(PRIMARY KEY),那么InnoDB會選擇主鍵作為聚集索引、如果沒有顯式定義主鍵,則InnoDB會選擇第一個不包含有NULL值的唯一索引作為主鍵索引、如果也沒有這樣的唯一索引,則InnoDB會選擇內(nèi)置6字節(jié)長的ROWID作為隱含的聚集索引(ROWID隨著行記錄的寫入而主鍵遞增,這個ROWID不像ORACLE的ROWID那樣可引用,是隱含的)。

  • 數(shù)據(jù)記錄本身被存于主索引(一顆B+Tree)的葉子節(jié)點上。這就要求同一個葉子節(jié)點內(nèi)(大小為一個內(nèi)存頁或磁盤頁)的各條數(shù)據(jù)記錄按主鍵順序存放,因此每當(dāng)有一條新的記錄插入時,MySQL會根據(jù)其主鍵將其插入適當(dāng)?shù)墓?jié)點和位置,如果頁面達(dá)到裝載因子(InnoDB默認(rèn)為15/16),則開辟一個新的頁(節(jié)點)

  • 如果表使用自增主鍵,那么每次插入新的記錄,記錄就會順序添加到當(dāng)前索引節(jié)點的后續(xù)位置,當(dāng)一頁寫滿,就會自動開辟一個新的頁

  • 如果使用非自增主鍵(如果身份證號或?qū)W號等),由于每次插入主鍵的值近似于隨機(jī),因此每次新紀(jì)錄都要被插到現(xiàn)有索引頁得中間某個位置,此時MySQL不得不為了將新記錄插到合適位置而移動數(shù)據(jù),甚至目標(biāo)頁面可能已經(jīng)被回寫到磁盤上而從緩存中清掉,此時又要從磁盤上讀回來,這增加了很多開銷,同時頻繁的移動、分頁操作造成了大量的碎片,得到了不夠緊湊的索引結(jié)構(gòu),后續(xù)不得不通過OPTIMIZE TABLE來重建表并優(yōu)化填充頁面。

綜上而言:當(dāng)我們使用自增列作為主鍵時,存取效率是最高的。

2.自增列id一定是連續(xù)的嗎?

自增id是增長的 不一定連續(xù)。

我們先來看下MySQL 對自增值的保存策略:

InnoDB 引擎的自增值,其實是保存在了內(nèi)存里,并且到了 MySQL 8.0 版本后,才有了“自增值持久化”的能力,也就是才實現(xiàn)了“如果發(fā)生重啟,表的自增值可以恢復(fù)為 MySQL 重啟前的值”,具體情況是:
在 MySQL 5.7 及之前的版本,自增值保存在內(nèi)存里,并沒有持久化。每次重啟后,第一次打開表的時候,都會去找自增值的最大值 max(id),然后將 max(id)+1 作為這個表當(dāng)前的自增值。
舉例來說,如果一個表當(dāng)前數(shù)據(jù)行里最大的 id 是 10,AUTO_INCREMENT=11。這時候,我們刪除 id=10 的行,AUTO_INCREMENT 還是 11。但如果馬上重啟實例,重啟后這個表的 AUTO_INCREMENT 就會變成 10。
也就是說,MySQL 重啟可能會修改一個表的 AUTO_INCREMENT 的值。
在 MySQL 8.0 版本,將自增值的變更記錄在了 redo log 中,重啟的時候依靠 redo log 恢復(fù)重啟之前的值。

造成自增id不連續(xù)的情況可能有:

1.唯一鍵沖突

2.事務(wù)回滾

3.insert ... select語句批量申請自增id

3.自增id有上限嗎?

自增id是整型字段,我們常用int類型來定義增長id,而int類型有上限 即增長id也是有上限的。
下表列舉下 int 與 bigint 字段類型的范圍:

類型大小范圍(有符號)范圍(無符號)
int4字節(jié)(-2147483648,2147483647)(0,4294967295)
bigint8字節(jié)(-9223372036854775808,9223372036854775807)(0,18446744073709551615)

從上表可以看出:當(dāng)自增字段使用int有符號類型時,最大可達(dá)2147483647即21億多;使用int無符號類型時,最大可達(dá)4294967295即42億多。當(dāng)然bigint能表示的范圍更大。

下面我們測試下當(dāng)自增id達(dá)到最大時再次插入數(shù)據(jù)會怎么樣:

create table t(id int unsigned auto_increment primary key) auto_increment=4294967295;
insert into t values(null);
// 成功插入一行 4294967295
show create table t;
/* CREATE TABLE `t` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4294967295;
*/

insert into t values(null);
//Duplicate entry '4294967295' for key 'PRIMARY'

從實驗可以看出,當(dāng)自增id達(dá)到最大時將無法擴(kuò)展,第一個 insert 語句插入數(shù)據(jù)成功后,這個表的AUTO_INCREMENT 沒有改變(還是 4294967295),就導(dǎo)致了第二個 insert 語句又拿到相同的自增 id 值,再試圖執(zhí)行插入語句,報主鍵沖突錯誤。

4.關(guān)于自增列 我們該怎么維護(hù)?

維護(hù)方面主要提供以下2點建議:

1.字段類型選擇方面:推薦使用int無符號類型,若可預(yù)測該表數(shù)據(jù)量將非常大 可改用bigint無符號類型。

2.多關(guān)注大表的自增值,防止發(fā)生主鍵溢出情況。

以上是“Mysql自增id的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!

新聞名稱:Mysql自增id的示例分析
當(dāng)前鏈接:http://muchs.cn/article6/pdjeog.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供微信小程序、定制網(wǎng)站、網(wǎng)站營銷、網(wǎng)站建設(shè)做網(wǎng)站、營銷型網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)