為什麼mysql自增主鍵不是連續的

2022-09-27 06:06:08 字數 1971 閱讀 8241

目錄

提出這個問題,是因為在工作中發現 mysql 中的 user 表的 id 預設是自程式設計客棧增的,但是資料庫儲存的結果卻不是連續的。

user 表結構:

create table `user` (

`id` bigint(20) unsigned not null auto_increment comment '遞增id',

`name` varchar(20),

`create_time` datetime default current_timestamp comment 程式設計客棧'建立時間',

`update_time` datetime default current_timestamp comment '更新時間',

primary key (`id`),unique key `idx_name` (`name`))

engine=innodb auto_increment=1 default charset=utf8mb4 comment='user表'

user 表儲存:

1.1  myisam 引擎的自增值儲存在資料檔案中。

1.2  innodb 引擎的自增值,其實是儲存在了記憶體裡,並且到了 mysql 8.0 版本後,才有了「自增值持久化」的能力,也就是才實現了「如果發生重啟,表的自增值可以恢復為 mysql 重啟前的值」,具體情況是:

在 mysql 裡面,如果字段 id 被定義為 auto_increment,在插入一行資料的時候,自增值的行為如下:

根據要插入的值和當前自增值的大小關係,自增值的變更結果也會有所不同。假設,某次要插入的值是 x,當前的自增值是 y。

新的自增值生成演算法是:從 auto_increment_offset 開始,以 auto_increment_increment 為步長,持續疊加,直到找到第乙個大於 x 的值,作為新的自增值。其中,auto_increment_offset 和 auto_increment_increment 是兩個系統引數,分別用來表示自增的初始值和步長,預設值都是 1。

insert into user values(null, '張三');

1 當執行上述 sql 時,執行器呼叫 innodb 引擎介面寫入一行,傳入的這一行的值是 (0,"張三");

2 innodb 發現 sql 沒有指定自增 id 的值,獲取 user 表當前的自增值 2;

3 將傳入的行的值改成 (2,"張三");

4 將表的自增值改成 3;

5 繼續執行插入資料操作。

假設執行 sql 的時候 user 表 id = 10,此時在記憶體中的自增 id 為11,此時發生唯一鍵衝突寫庫失敗,則 user 表沒有 id 程式設計客棧= 10 這條記錄,之後 id 從11開始寫入,因此uqkcqvuak id 是不連續的。

假設同時需要對 user、staff 表進行寫庫操作,執行 sql 的時候 user 表 id = 10,此時在記憶體中的自增 id 為11;staff 表 id = 20,此時記憶體中的自增 id 為21,一旦事務執行失敗,事務回滾,寫庫失敗,則 user 表沒有 id = 10 這條記錄,staff 表沒有 id = 20 這條記錄,user 表從11開始寫入,staff 表從21開始寫入,如此產生 id 不連續的現象。

對於批量插入資料的語句,mysql 有乙個批量申請自增 id 的策略:

1. 語句執行過程中,第一次申請自增 id,會分配 1 個;

2. 1 個用完以後,這個語句第二次申請自增 id,會分配 2 個;

3. 2 個用完以後,還是這個語句,第三次申請自增 id,會分配 4 個;

依此類推,同乙個語句去申請自增 id,每次申請到的自增 id 個數都是上一次的兩倍。

假設批量往 user 表中寫入四條記錄,則這四條記錄將分為三次申請id,

第一次分配到 id = 1,第二次分配到 id = 2、3 ,第三次分配到 id = 4、5、6、7,當批量寫入四條記錄之後,id = 1、2、3、4將會入庫,但是 id = 5、6、7就被廢棄了,下乙個 id 從8開始。

mysql為什麼建議使用自增主鍵

前面我寫了幾篇關於 mysql 索引的文章,索引是 mysql 非常重要的一部分。你也可能經常會看到一些關於 mysql 軍規 mysql 查詢優化的文章,其實這些操作的背後都是基於一定的原理的,你要想明白這些原理,首先就得知道 mysql 底層的一些東西。我在這裡舉幾個例子吧。我們都知道表的主鍵一...

mysql 主鍵自增語句 MySQL 自增主鍵

以下僅考慮 innodb 儲存引擎。自增主鍵有兩個性質需要考慮 單調性每次插入一條資料,其 id 都是比上一條插入的資料的 id 大,就算上一條資料被刪除。連續性插入成功時,其資料的 id 和前一次插入成功時資料的 id 相鄰。自增主鍵的單調性 為何會有單調性的問題?這主要跟自增主鍵最大值的獲取方式...

MySQL 為什麼推薦自增 id 作為主鍵

在計算機裡,無論是記憶體還是磁碟,作業系統都是按頁的大小進行讀取的 頁大小通常為 4 kb 磁碟每次讀取都會預讀,會提前將連續的資料讀入記憶體中,這樣就避免了多次 io,這就是計算機中有名的區域性性原理,即我用到一塊資料,很大可能這塊資料附近的資料也會被用到,乾脆一起載入,省得多次 io 拖慢速度,...