java面試一日一題:mysql中的自增主鍵

迷茫中守候發表於2021-04-28

問題:請講下mysql中的自增主鍵

分析:該問題主要考察對mysql中自增主鍵的掌握,使用場景及如何設定

回答要點:

主要從以下幾點去考慮

1、什麼自增主鍵

2、使用場景是什麼;

3、innodb_autoinc_lock_mode的設定;

 

從學習mysql開始,我們就知道在建表時經常建的是自增主鍵,並且在mysql的優化中經常看到的一句就是,最好有自增主鍵,那麼自增主鍵是做什麼用的。

自增主鍵的用法,

CREATE TABLE t1 (
  c1 INT(11) NOT NULL AUTO_INCREMENT,
  c2 VARCHAR(10) DEFAULT NULL,
  PRIMARY KEY (c1)
) ENGINE=InnoDB;

上面的建表語句中c1就是一個自增主鍵。自增主鍵的好處是在進行資料插入時,會按照主鍵的順序自增插入,且在innodb引擎下,會有一個聚集索引,該索引便是按照自增主鍵來組織的,也就是非葉子節點中儲存的是自增主鍵。還會經常聽到這樣一句話,如果表中沒有自增主鍵,那麼變會選擇一個不為空的唯一列作為主鍵索引來組織索引樹,如果表中沒有這樣的列變會隱式生成一列rowid作為主鍵來組織索引樹,當然此時的索引也是聚集索引。所謂聚集索引就是索引和資料是在一起的,像myIsam引擎則是非聚集索引,只有innodb的主鍵索引才是聚集索引,其葉子節點儲存的是整行資料。

上面瞭解了自增索引的用法,下面講下自增索引的使用場景。在分散式的系統中經常會有使用分散式ID的情況,有一種方案便是利用innodb引擎的自增索引,建一張表,表中有一個自增的主鍵列,該列的值可以作為分散式ID使用。

使用這樣的方式會不會產生問題,會不會存在多個事務間的問題,要解決這個問題,首先要了解自增ID的生產原理。詳見可以參看下面的官方文件,

https://dev.mysql.com/doc/refman/5.7/en/innodb-auto-increment-handling.html

從上面的官方文件中,可以大致得出這樣的結論,自增主鍵的生成方式可以簡單理解為事務在執行的時候會使用表鎖鎖住表,其他事務要想進行操作必須等待上一個事務釋放表鎖以後。隨著mysql版本的升級,可以對該方式進行配置,於是有了innodb_autoinc_lock_mode屬性,該屬性可以對在插入自增主鍵時採用什麼樣的方式,其值有0 1 2三個值。

0  傳統鎖定模式

innodb_autoinc_lock_mode=0的情況,該值是為了相容innodb_autoinc_lock_mode配置項未出現前的情況,在插入自增主鍵的時候使用的就是一把表鎖。通過特殊的表級AUTO-INC鎖進行鎖定,可以確保為給定的INSERT 語句序列以可預測和可重複的順序分配自動遞增值,並確保自動遞增值任何給定語句分配的都是連續的。

引入1和2的目的是為了增大併發,減少使用表級鎖,提升效能,優化針對批量插入的場景

1  簡單鎖定模式

innodb_autoinc_lock_mode=1的情況,主要優化了批量插入和簡單插入的場景下的AUTO-INC鎖,該模式下可以保證任何給定語句分配的自動遞增編號都是連續的。

2  混合鎖定模式

inndob_autoinc_lock_mode=2的情況,這是最快、最具有擴充套件性的方案,但多個語句同時生成數字,生產的自增數字可能不是連續的。

 

innodb_autoinc_lock_mode的三種值都可以保證生成的數字是唯一遞增的,但不能全部保證是連續的,且在主從複製的情況下也會有不安全的問題,因為主從複製的是binlog,而binlog的形式有3種。

 

有不當之處,請留言

相關文章