日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql如何实现逻辑自增_每日一面 - mysql 的自增 id 的实现逻辑是什么样子的?

發(fā)布時間:2025/3/15 数据库 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql如何实现逻辑自增_每日一面 - mysql 的自增 id 的实现逻辑是什么样子的? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Key TakeAways

InnoDB 引擎中 有三種 AutoIncrement 鎖模式:

innodb_autoinc_lock_mode=0(traditional lock mode):獲取表鎖,語句執(zhí)行結束后釋放

innodb_autoinc_lock_mode=1(consecutive lock mode,MySQL 8.0 之前默認 ):對于不確定插入數量的語句(例如INSERT ... SELECT, REPLACE ... SELECT和LOAD DATA)和 innodb_autoinc_lock_mode=0 一樣,其他的確定數量的語句在執(zhí)行前先批量獲取 id,之后再執(zhí)行語句。

innodb_autoinc_lock_mode=2(interleaved lock mode,MySQL 8.0+ 默認 ):采用樂觀鎖, CAS 更新計數器獲取。

AutoIncrement 計數器在 MySQL 8.0 之前,存儲在內存中,在 MySQL 8.0 之后,持久化存儲到磁盤。通過每次更新寫入 Redo Log,并在檢查點刷入 innodb 引擎表中記錄下來。

AutoIncrement 的 id 可以讓新數據聚集在一起,利于大部分 OLTP 業(yè)務(訪問頻率在最近一天,一周,或者幾個月內比較活躍,而超過一段時間內的數據很少訪問)。如果是這類業(yè)務推薦使用自增主鍵,將業(yè)務主鍵(UUID)作為二級的唯一索引使用。

如果考慮分布式性能以及避免 AutoIncrement 帶來的鎖性能問題,可以考慮使用 ID 生成器生成:全局趨勢增長的主鍵

為何主鍵要 Auto Increment 而不是 UUID

MySQL InnoDB 引擎默認主鍵索引是 B+ 樹索引,也是聚集索引,為何叫聚集索引呢?

以 InnoDB 作為存儲引擎的表,表中的數據都會有一個主鍵,即使你不創(chuàng)建主鍵,系統(tǒng)也會幫你創(chuàng)建一個隱式的主鍵。這是因為 InnoDB 是把數據存放在 B+ 樹中的,而 B+ 樹的鍵值就是主鍵,在 B+ 樹的葉子節(jié)點中,存儲了表中所有的數據。這種以主鍵作為 B+ 樹索引的鍵值而構建的 B+ 樹索引,我們稱之為聚集索引。

存儲中,聚集索引的數據,會根據索引的值,對應的數據也會聚集存儲在一起:

MySQL 讀取磁盤上的數據是一頁一頁讀取的,如果某條我們要處理的數據在某一頁中,但是這一頁其他數據我們都不關心,這樣的請求多了,性能會急劇下降,類似于 CPU 的 false sharing:

按照 B+ 樹的原理,AutoIncrement 的 ID 能保證最新的數據在一頁中被讀取,而且減少了 B+ 樹分裂翻轉。 UUID 由于無序,插入時,B+ 樹會不斷翻轉,并且最新的數據可能不在同一頁。很可能會出現,最新一條數據,和好幾年前的數據在同一頁。

在大部分 OLTP 類業(yè)務中,例如購物和支付交易的訂單,節(jié)日促銷的抽獎活動這類業(yè)務都有這樣的使用場景,訪問頻率在最近一天,一周,或者幾個月內比較活躍,而超過一段時間內的數據很少訪問。如果是這類業(yè)務推薦使用自增主鍵,將業(yè)務主鍵(UUID)作為二級的唯一索引使用。 如果考慮分布式性能以及避免 AutoIncrement 帶來的鎖性能問題,可以考慮使用 ID 生成器生成全局趨勢增長的主鍵,例如 Twitter 的 Snowflake 算法生成的前面是時間戳的主鍵id,或者是 類似于這種 "時間+業(yè)務+自增"(例如 20210105105811233ORD0000001) 字符串,作為主鍵id,這樣其實也能近似保證熱數據聚集存儲在一起,也就是 MySQL 一頁一頁讀取能命中更多要讀取處理的數據

AutoIncrement 原理

我們這里只關心 InnoDB 引擎的。

AutoIncrement 最大值

AutoIncrement 最大值,和列類型相關。最大可以設置列類型為 UNSIGNED BIGINT,這樣最大值就是 18446744073709551615。 超過這個值繼續(xù)生成則還是 18446744073709551615。不會再增加。

AutoIncrement 鎖模式

獲取 AutoIncrement 最新值,需要涉及到鎖。目前有三種鎖模式,對應 innodb_autoinc_lock_mode 的值, 0 ,1,2. MySQL 8.0 之后,默認為 2, 在這之前,默認為 1

innodb_autoinc_lock_mode=0(traditional lock mode) 傳統(tǒng)的auto_increment機制,這種模式下所有針對auto_increment列的插入操作都會加表級別的AUTO-INC鎖,在語句執(zhí)行結束則會釋放,分配的值也是一個個分配,是連續(xù)的,正常情況下也不會有間隙(當然如果事務rollback了這個auto_increment值就會浪費掉,從而造成間隙)。

innodb_autoinc_lock_mode=1(consecutive lock mode) 這種情況下,針對未知數量批量插入(例如INSERT ... SELECT, REPLACE ... SELECT和LOAD DATA)才會采用AUTO-INC鎖這種方式,而針對已知數量的普通插入,則采用了一種新的輕量級的互斥鎖來分配auto_increment列的值。這種鎖,只會持續(xù)到獲取一定數量的 id,不會等待語句執(zhí)行結束在釋放。也就是拿輕量級鎖提前分配好所需數量的 id 之后釋放鎖,再執(zhí)行語句。當然,如果其他事務已經持有了AUTO-INC鎖,則simple inserts需要等待。當然,這種情況下,可能產生的間隙更多。

innodb_autoinc_lock_mode=2(interleaved lock mode) 這種模式下任何類型的inserts都不會采用AUTO-INC鎖,性能最好,但是在同一條語句內部產生auto_increment值間隙。其實這個就是所有語句對于同一個值進行 Compare-And-Set 更新,類似于樂觀鎖。這個鎖模式對statement-based replication的主從同步都有一定問題。因為同步傳輸的是語句,而不是行值,語句執(zhí)行后的差異導致主從可能主鍵不一致。

AutoIncrement 存儲

AutoIncrement 計數器在 MySQL 8.0 之前,存儲在內存中,每次啟動時通過以下語句初始化:

SELECT MAX(ai_col) FROM table_name FOR UPDATE;

在 MySQL 8.0 之后,持久化存儲到磁盤。通過每次更新寫入 Redo Log,并在檢查點刷入 innodb 引擎表中記錄下來。

所以,在MySQL 8.0 之前,如果 rollback 導致某些值沒有使用,重啟后,這些值還是會使用。但是在 MySQL 8.0 之后就不會了。

每日一刷,輕松提升技術,斬獲各種offer:

總結

以上是生活随笔為你收集整理的mysql如何实现逻辑自增_每日一面 - mysql 的自增 id 的实现逻辑是什么样子的?的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。