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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

InnoDB自增原理都搞不清楚,还怎么CRUD?

發布時間:2025/3/16 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 InnoDB自增原理都搞不清楚,还怎么CRUD? 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

雖然我們習慣于給主鍵ID指定AUTO_INCREMENT屬性,但是AUTO_INCREMENT也是可以指定到非主鍵字段的,唯一的約束就是這個字段上面得加索引,有了索引,就可以通過類似SELECT MAX(*ai_col*)的語句快速讀到這列數據的最大值。

本文要探討的話題是MySql的InnoDB引擎處理自增數據列的原理

MySql 5.1之前的實現

在這個版本之前,用AUTO_INCREMENT修飾的數據列確實是嚴格連續自增的。MySql的實現是會針對每個插入語句加一個全表維度的鎖,這個鎖可以保證每次只有一條插入語句在執行,每插入一行數據,就會生成一個自增數據。

mysql>?CREATE?TABLE?t1?(->?c1?INT?UNSIGNED?NOT?NULL?AUTO_INCREMENT?PRIMARY?KEY,?->?c2?CHAR(1)->?)?ENGINE=InnoDB?AUTO_INCREMENT=100;

假如我們在數據庫中新建上面的這張表,接著我們執行插入語句。

mysql>?INSERT?INTO?t1?(c1,c2)?VALUES?(NULL,'a'),?(NULL,'b'),?(NULL,'c'),?(NULL,'d');

針對這條MySql執行的流程為:

  • 全表加 AUTO-INC鎖

    1.1 生成主鍵ID:101

    1.2 將行(101, 'a')插入表中

    1.3 生成主鍵ID: 102

    1.4 將行(102, 'b')插入表中

    ...

  • 釋放 AUTO-INC鎖

  • MySql5.1之前的這種實現方式可以保證AUTO_INCREMENT嚴格自增,但是并發程度也最差,因為AUTO_INCREMENT鎖是全表加鎖直到這條語句結束

    MySql 5.1版本帶來的優化

    前文中的insert語句是比較簡單的,所謂簡單的insert語句指的是插入的的數據行數是可以提前確定的,與之相對的是Bulk insert比如INSERT ... SELECT這類語句,這類插入語句的插入行數不能提前確定。

    在這個版本以及之后,對于簡單語句的插入,不再加全表的AUTO-INC鎖,只會在產生自增列數據的時候加一個輕量級的互斥鎖,等自增數據分配好,鎖就釋放了,因此像上面的例子,在MySql5.1之后的執行流程如下

  • 加輕量級互斥鎖

    1.1 分配自增數據

  • 釋放鎖

  • 將行(101, 'a')插入表中

  • 將行(102, 'b')插入表中

    ...

  • 可以看到,對于簡單的插入語句,并發情況下的臨界區變小了,且不再持有全表的鎖,提升了并發性能。當然,如果在嘗試加鎖的過程中遇到有其他事務持有全表的AUTO-INC鎖,還是要等待全表的AUTO-INC鎖釋放再執行本次插入操作

    對于Bulk insert的插入語句,仍然避免不了全局的AUTO-INC鎖,這類語句,他們的執行流程仍然保持和5.1之前版本一致,比如以下表為例

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

    執行下面兩條語句

    Tx1:?INSERT?INTO?t1?(c2)?SELECT?1000?rows?from?another?table?... Tx2:?INSERT?INTO?t1?(c2)?VALUES?('xxx');

    由于在執行Tx1時,InnoDB無法知道要插入的具體行數,因此會獲取一個全表的鎖,每執行一條插入語句就會給自增列賦新的值。因為有全表的鎖,所以Tx1這條語句插入的所有行數都是連續自增的,Tx2自增列的值要么小于Tx1自增列的最小值,要么大于Tx1自增列中的最大值,這取決于這兩條語句的執行順序

    InnoDB采取這樣的決策一個重要的原因是主從復制,在MySql8.0之前,MySql的主從是基于語句復制的。在剛才的例子中,如果Tx1執行的時候沒有全表的鎖,那有可能在Tx1執行的過程中Tx2也在執行,這就會導致Tx1和Tx2自增列的數據每次執行結果都不相同,也就無法在從庫中通過語句回放復制。

    MySql 8.0版本之后的優化

    雖然MySql5.1版本對簡單的插入語句做了優化,避免了全表加鎖,但對于INSERT ... SELECT這樣的復雜插入語句,仍然避免不了全表的AUTO-INC鎖,主要是基于執行語句的主從復制要能在從庫完全回放復制主庫,所有的語句執行結果就不能和執行順序有關。

    在MySql 8.0以及之后默認的主從復制策略變成了基于數據行實現,在這樣的背景下INSERT ... SELECT這樣的復雜插入語句也不需要全表加鎖來生成自增列數據了,所有的插入語句只有在生成自增列數據的時候要求持有一個輕量級的互斥鎖,等到自增數據生成好之后釋放鎖。在這種實現下,所有插入語句的自增列都不能保證連續自增,但是并發性能確實最好的。

    總結

    需要說明的是,如果插入語句所處的事務回滾了,生成的自增列數據是不會回滾的,這種情況下會造成自增列數據非連續增長。

    以上所述都是各個MySql版本的默認實現,MySql 5.1引入了一個新的參數 innodb_autoinc_lock_mode 通過修改這個字段的值,可以改變InnoDB生成自增列的策略,其值總結如下:

    值名稱含義
    0traditional lock mode每次插入語句執行都會全表加鎖至語句結束,5.1版本之前默認實現
    1consecutive lock mode簡單插入不再全表加鎖,INSERT ... SELECT類的語句才持有全表鎖,5.1至8.0默認實現
    2interleaved lock modeINSERT ... SELECT類的語句也不會全表加鎖,只有生成自增列數據時才加鎖,8.0之后默認實現

    不推薦顯式指定自增列數據,因為在5.7以及之前的版本,如果通過update語句顯式指定一個比SELECT MAX(*ai_col*)還大的自增列值,后續insert語句可能會拋"Duplicate entry"錯誤,這一點在8.0版本之后也有了改變,如果通過顯式的update語句顯式指定一個比SELECT MAX(*ai_col*)還大的自增列值,那該值就會被持久化,后續的自增列值都從該值開始生成。

    假如有下面這張表

    mysql>?CREATE?TABLE?t1?(->?c1?INT?UNSIGNED?NOT?NULL?AUTO_INCREMENT?PRIMARY?KEY,?->?c2?CHAR(1)->?)?ENGINE?=?INNODB?AUTO_INCREMENT=100;

    試想,在我們執行完下面這條語句之后表的內容變成了什么?

    mysql>?INSERT?INTO?t1?(c1,c2)?VALUES?(1,'a'),?(NULL,'b'),?(5,'c'),?(NULL,'d');

    MySql 5.1之前,或者innodb_autoinc_lock_mode設置為0

    mysql>?SELECT?c1,?c2?FROM?t1?ORDER?BY?c2; +-----+------+ |?c1??|?c2???| +-----+------+ |???1?|?a????| |?101?|?b????| |???5?|?c????| |?102?|?d????| +-----+------+

    在這種模式下,每插入一行數據就會生成一個自增值賦到c1這一行,因此c1的下一個自增值是103

    MySql 8.0之前,或者innodb_autoinc_lock_mode設置為1

    mysql>?SELECT?c1,?c2?FROM?t1?ORDER?BY?c2; +-----+------+ |?c1??|?c2???| +-----+------+ |???1?|?a????| |?101?|?b????| |???5?|?c????| |?102?|?d????| +-----+------+

    當前表的數據與前一個場景一致,但是下一個自增值卻是105,因為在這個場景下,自增數據是在插入語句執行的最開始一次性生成的

    MySql 8.0之后,或者innodb_autoinc_lock_mode設置為2

    mysql>?SELECT?c1,?c2?FROM?t1?ORDER?BY?c2; +-----+------+ |?c1??|?c2???| +-----+------+ |???1?|?a????| |???x?|?b????| |???5?|?c????| |???y?|?d????| +-----+------+

    在這種場景下,因為同時可能有其他的插入語句執行,因此x和y的值是不確定的,下一個自增值也是未知的。

    有道無術,術可成;有術無道,止于術

    歡迎大家關注Java之道公眾號

    好文章,我在看??

    總結

    以上是生活随笔為你收集整理的InnoDB自增原理都搞不清楚,还怎么CRUD?的全部內容,希望文章能夠幫你解決所遇到的問題。

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

    主站蜘蛛池模板: 美女屁股眼视频网站 | 亚洲美女中文字幕 | 在线欧美 | 天天躁日日躁aaaxxⅹ | 亚洲精品小视频 | 国产午夜免费视频 | 亚洲第一视频在线观看 | 欧美三级三级三级爽爽爽 | 337p粉嫩大胆色噜噜狠狠图片 | 国产欧美专区 | 中国女人特级毛片 | 色噜噜一区二区三区 | 国产在线精品成人欧美 | 日本在线播放视频 | 影音先锋亚洲天堂 | 韩国av电影在线观看 | 欧美大色 | 亚洲av无码国产精品永久一区 | 性少妇videosexfreexxx片 | 国产福利在线播放 | 精品免费久久久 | 欧美日韩亚洲色图 | 国产农村妇女毛片精品 | 熟妇人妻中文字幕无码老熟妇 | 日韩片在线观看 | 无码人妻精品一区二区三区温州 | v99av | 麻豆影视av| 美女裸体跪姿扒开屁股无内裤 | 久久久久久久久国产精品 | 91理论片午午伦夜理片久久 | 一本色道久久综合亚洲二区三区 | 饥渴少妇伦色诱公 | 91免费毛片| 国产专区欧美专区 | 亚洲精品高潮久久久久久久 | 让男按摩师摸好爽视频 | 露脸啪啪清纯大学生美女 | 国产成人无码aa精品一区 | 精品视频一区二区在线观看 | 91视频插插插 | 亚洲国产日韩一区无码精品久久久 | 亚洲一区二区色 | 天天躁日日摸久久久精品 | 久爱视频在线观看 | 日韩久久av| 26uuu国产| 在线视频观看免费 | 黄色三极片 | 97视频免费 | 日本成人午夜 | 鲁丝一区二区 | 免费色网 | 色戒在线免费 | 男女www | 久热热| 欧美激情福利 | 日日干夜夜骑 | 欧美日韩在线观看一区二区三区 | av网子 | 奇米影音| 热re99久久精品国产99热 | 久久久久美女 | 欧美精品久久99 | 亚洲黄色自拍 | 成人h视频在线 | av毛片观看 | 在线一区二区三区四区 | 91精品国产色综合久久不8 | www.午夜av | 国产娇小hdxxxx乱 | av在线不卡网 | 久久精品国产欧美亚洲人人爽 | 99欧美| 少女忠诚电影高清免费 | 日韩午夜视频在线观看 | 国产ts系列| 日韩欧美一二三 | 国产一区二区网 | 日本wwwwww | 中文字幕人妻色偷偷久久 | 中文字幕av久久爽一区 | 老司机av影院 | 日本免费黄色小视频 | 天天色影院 | 四川丰满妇女毛片四川话 | a级无遮挡超级高清-在线观看 | 亚洲综合一 | 亚洲免费视频大全 | 久色99| 国产麻豆天美果冻无码视频 | av免费看在线 | 中文字幕+乱码+中文字幕一区 | 国语对白在线观看 | 中文字幕精品久久久久人妻红杏ⅰ | 91久久精品日日躁夜夜躁国产 | 国产大片中文字幕 | 啊av在线| 国产毛片欧美毛片久久久 |