最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文深入探究MySQL自增鎖

 更新時(shí)間:2023年08月18日 08:40:16   作者:緑水長(zhǎng)流  
MySQL的自增鎖是指在使用自增主鍵(Auto?Increment)時(shí),為了保證唯一性和正確性,系統(tǒng)會(huì)對(duì)自增字段進(jìn)行加鎖,這樣可以確保同時(shí)插入多條記錄時(shí),每條記錄都能夠獲得唯一的自增值,本將和大家一起深入探究MySQL自增鎖,需要的朋友可以參考下

自增鎖

MySQL的自增鎖是指在使用自增主鍵(Auto Increment)時(shí),為了保證唯一性和正確性,系統(tǒng)會(huì)對(duì)自增字段進(jìn)行加鎖。這樣可以確保同時(shí)插入多條記錄時(shí),每條記錄都能夠獲得唯一的自增值。

表的插入數(shù)據(jù)方式

我們之前在表中插入數(shù)據(jù)都是用最基本的insert,但insert語(yǔ)句的用法用很多,另外MySQL還提供replace語(yǔ)句,允許對(duì)表中的數(shù)據(jù)進(jìn)行替換;

  • insert用法:
drop table if exists t3;
CREATE TABLE `t3`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `age` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT=1;
insert into t3 values(1,20);
insert into t3 values(2,25);
drop table if exists t4;
CREATE TABLE `t4`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `age` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT=1;
-- 插入記錄,如果存在這條記錄就報(bào)錯(cuò)(主鍵唯一)
insert into t4 values(10,20);
insert into t4 values(11,20),(12,21),(13,22);
insert into t4 set id=14,age=25;
insert into t4 select * from t3;
  • replace用法:
delete from t4;
-- 如果沒(méi)有這條記錄就新增,有這條記錄就修改
replace into t4 values(1,20);  
replace into t4 set id=10,age=100 ;
replace into t4 select * from t3;

insert的不同類型

1)Simple inserts

簡(jiǎn)單插入模式

  • 示例:
insert into table_name values(xxx);
  • 特點(diǎn):可以提前確定要插入的行數(shù)

2)Bulk inserts

批量插入模式,包含insert...select、replace select、load data等語(yǔ)句;

  • 示例:
insert into t4 select * from t3;
replace into t4 select * from t3;

Tips:load data屬于海量數(shù)據(jù)插入,暫時(shí)不演示

  • 特點(diǎn):事先不知道要插入的行數(shù),以及所需的自動(dòng)增量值的數(shù)量

3)Mixed-mode

該模式也屬于Simple Inserts

  • 示例:
insert into table_name values(xxxx),(xxxx),(xxxx);
  • 特點(diǎn):為一些(但不是全部)新行指定自動(dòng)增量值

自增鎖原理

1)插入原理

MySQL自增鎖的實(shí)現(xiàn)機(jī)制是使用了一個(gè)名為"auto-increment lock"的互斥鎖。當(dāng)使用INSERT語(yǔ)句插入一條新記錄時(shí),MySQL會(huì)自動(dòng)為自增字段加鎖,防止其他并發(fā)的插入操作同時(shí)獲取相同的自增值。這個(gè)鎖是在內(nèi)部實(shí)現(xiàn)的,不需要用戶手動(dòng)創(chuàng)建或管理。

自增鎖確保了插入記錄的唯一性和正確性,避免了并發(fā)插入產(chǎn)生沖突。但同時(shí)也會(huì)帶來(lái)一些性能上的影響,因?yàn)椴l(fā)插入操作需要等待鎖的釋放。因此,在高并發(fā)的場(chǎng)景下,可能需要考慮使用其他方案來(lái)避免自增鎖成為瓶頸。

image

注意:自增鎖跟事務(wù)無(wú)關(guān),即使多個(gè)insert語(yǔ)句存在同一個(gè)事務(wù)中,每次insert都會(huì)申請(qǐng)最新的自增鎖來(lái)獲取最新的AUTO_INCREMENT值;自增鎖保持到insert語(yǔ)句結(jié)束,而不是事務(wù)結(jié)束;

2)自增鎖表鎖

需要注意的是,自增鎖是基于表級(jí)別的,而不是行級(jí)別的。這意味著在同一時(shí)刻針對(duì)于同一張表只能有一個(gè)線程在插入記錄(前提是需要increment來(lái)分配id),并且每個(gè)表都有一個(gè)自己獨(dú)立的自增鎖。

image

自增鎖的模式

和自增鎖相關(guān)的一個(gè)參數(shù)為(5.1.22版本之后加入)innodb_autoinc_lock_mode:可以設(shè)定3個(gè)值,0,1,2

show variables like 'innodb_autoinc_lock_mode';

image

  • 0:traditional(傳統(tǒng)模式):每次insert都會(huì)產(chǎn)生表級(jí)別的自增鎖,能夠絕對(duì)保證insert的插入順序,但并發(fā)能力較弱;
  • 1:consecutive(連續(xù)模式):對(duì)于Simple Inserts能夠產(chǎn)生一個(gè)輕量級(jí)的頁(yè)面鎖來(lái)保證insert的連續(xù)插入;對(duì)于Bulk Inserts無(wú)法確定插入的行數(shù)時(shí)采用表級(jí)別自增鎖來(lái)保證insert的連續(xù)插入;
  • 2:interleaved(交叉模式):不采用表鎖,來(lái)一個(gè)insert處理一個(gè),并發(fā)能力最高,但可能會(huì)造成insert分配的id順序不一致;

Tips:參數(shù)只控制InnoDB引擎的設(shè)置,所有MyISAM均為traditional ,每次均會(huì)進(jìn)行表鎖。只有Innodb會(huì)視參數(shù)不同而產(chǎn)生不通的鎖。

1)traditional(傳統(tǒng)模式)

在傳統(tǒng)模式下,不管是在執(zhí)行Simple inserts還是Bulk inserts時(shí)每個(gè)insert獲取自增鎖時(shí)都會(huì)觸發(fā)表鎖,在某個(gè)insert沒(méi)有釋放表鎖之前其他線程/進(jìn)程均不可獲取自增鎖;雖然傳統(tǒng)模式保證了多個(gè)insert插入的連續(xù)性但實(shí)際上并發(fā)插入屬于串行化,性能較低;

image

Tips:再次說(shuō)明,自增鎖是執(zhí)行insert時(shí)獲取auto_increment值時(shí)才會(huì)申請(qǐng),獲取到auto_increment值時(shí)就會(huì)立即釋放,跟事務(wù)無(wú)關(guān);

2)consecutive(連續(xù)模式)

在連續(xù)模式下,InnoDB會(huì)根據(jù)當(dāng)前執(zhí)行的insert語(yǔ)句來(lái)判斷是否使用表級(jí)別自增鎖。這也是InnoDB的默認(rèn)值;

  • Simple inserts:InnoDB能夠預(yù)先知道要插入的行數(shù),因此產(chǎn)生的自增鎖只會(huì)鎖住對(duì)應(yīng)的那些id(頁(yè)鎖),避免表級(jí)別的自增鎖
  • Bulk Inserts:InnoDB無(wú)法預(yù)知要插入的行,觸發(fā)表級(jí)別自增鎖

【Simple Inserts】

image

【Bulk Inserts】

image

3)interleaved(交叉模式)

在交叉模式下,所有的insert語(yǔ)句都不會(huì)使用自增鎖(悲觀鎖),而是采用一個(gè)輕量級(jí)的mutex(樂(lè)觀鎖),來(lái)一個(gè)insert立即處理,在生成insert語(yǔ)句完畢后檢查id是否被其他線程/進(jìn)程使用,如果已經(jīng)被使用則重新獲取id;這樣一來(lái),多條 INSERT 語(yǔ)句可以并發(fā)的執(zhí)行,因此交叉模式并發(fā)量最高,但對(duì)于同一個(gè)語(yǔ)句來(lái)說(shuō)它所得到的auto_increment值可能不是連續(xù)的。

  • 交叉模式示意圖:

image

【模擬交叉模式并發(fā)插入情況】

步驟①:Thread-01線程執(zhí)行insert獲取到auto_increment值為10

步驟②:與此同時(shí)Thread-02線程也獲取到10

步驟③:然后又回到Thread-01線程對(duì)auto_increment值+1,此時(shí)auto_increment為11

步驟④:然后Thread-02線程也對(duì)auto_increment+1,此時(shí)auto_increment為12

步驟⑤:Thread-01線程校驗(yàn)id值是否被其他線程使用過(guò),校驗(yàn)結(jié)果:未被其他線程使用過(guò),執(zhí)行插入

步驟⑥:Thread-01線程校驗(yàn)id值是否被其他線程使用過(guò),校驗(yàn)結(jié)果:已經(jīng)被其他線程使用過(guò),本次操作取消;

最終Thread-01線程先將auto_increment值寫入插入字段中,Thread-02線程將auto_increment寫入字段中發(fā)現(xiàn)該字段已經(jīng)被其他線程使用過(guò),因此本次操作取消;但auto_increment值已經(jīng)變?yōu)?2;下一次執(zhí)行insert的線程獲取auto_increment值將會(huì)獲取到12,auto_increment為11這一次就這樣跳過(guò)了;

image

【交叉模式的注意事項(xiàng)】

由于交叉模式所帶來(lái)的id不連續(xù)問(wèn)題,在搭建有MySQL主從復(fù)制的架構(gòu)并且binlog日志格式為SBR時(shí)會(huì)出現(xiàn)主從數(shù)據(jù)不一致問(wèn)題;

原因:當(dāng)Master接收高并發(fā)量的insert語(yǔ)句時(shí)會(huì)將insert語(yǔ)句記錄到binlog日志中,這些binlog日志被發(fā)送到Slave時(shí)Slave將會(huì)并發(fā)執(zhí)行這些SQL語(yǔ)句,很有可能導(dǎo)致Slave執(zhí)行這些語(yǔ)句的順序和當(dāng)初Master執(zhí)行的順序一致,導(dǎo)致主從分配的id不一致,因此在MySQL主從復(fù)制時(shí)從服務(wù)器應(yīng)禁止使用交叉模式;

image

自增步長(zhǎng)控制

一般我們?cè)趧?chuàng)建表的時(shí)候id起始值為1,通過(guò)AUTO_INCREMENT可以設(shè)置其值;

drop table if exists t3;
CREATE TABLE `t3`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `age` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT=1;
-- 在創(chuàng)建表后也可以通過(guò)SQL語(yǔ)句修改auto_increment
alter table t3 auto_increment=20;

自增幅度由以下兩個(gè)參數(shù)進(jìn)行控制:

-- 自增的步長(zhǎng)
set auto_increment_increment=2;         -- 默認(rèn)1

可以通過(guò)函數(shù)獲取最后一個(gè)插入的id:

select last_insert_id();

【測(cè)試】

session-01session-02
begin;
begin;
insert into t3 values(null,1);
insert into t3 values(null,1);
rollback;
commit;

最終session-02插入的那條記錄id為2;

以上就是一文深入探究MySQL自增鎖的詳細(xì)內(nèi)容,更多關(guān)于MySQL自增鎖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MySQL binlog日志進(jìn)行手動(dòng)刪除與自動(dòng)清理

    MySQL binlog日志進(jìn)行手動(dòng)刪除與自動(dòng)清理

    本文介紹了MySQL的binlog日志的自動(dòng)清理和手動(dòng)刪除方法,自動(dòng)清理可以通過(guò)設(shè)置binlog_expire_logs_seconds參數(shù)實(shí)現(xiàn),而手動(dòng)刪除則可以使用purge命令,需要的朋友可以參考下
    2026-01-01
  • MySQL中索引的常見問(wèn)題與性能優(yōu)化詳解

    MySQL中索引的常見問(wèn)題與性能優(yōu)化詳解

    索引就像圖書館的檢索系統(tǒng),設(shè)計(jì)得好,找書會(huì)很快;設(shè)計(jì)的不好,反而會(huì)越用越慢,下面小編就和大家詳細(xì)介紹一下MySQL中索引的常見問(wèn)題與性能優(yōu)化吧
    2025-11-11
  • mysql binlog二進(jìn)制日志詳解

    mysql binlog二進(jìn)制日志詳解

    二進(jìn)制日志包含了所有更新了數(shù)據(jù)或者已經(jīng)潛在更新了數(shù)據(jù)(例如,沒(méi)有匹配任何行的一個(gè)DELETE)的所有語(yǔ)句
    2011-10-10
  • MYSQL查詢時(shí)間范圍內(nèi)的數(shù)據(jù)示例代碼

    MYSQL查詢時(shí)間范圍內(nèi)的數(shù)據(jù)示例代碼

    這篇文章主要介紹了MYSQL查詢時(shí)間范圍內(nèi)的數(shù)據(jù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • MySQL的ALTER TABLE命令的使用解讀

    MySQL的ALTER TABLE命令的使用解讀

    這篇文章主要介紹了MySQL的ALTER TABLE命令的使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-05-05
  • Mysql如何巧妙的繞過(guò)未知字段名詳解

    Mysql如何巧妙的繞過(guò)未知字段名詳解

    這篇文章主要給大家介紹了Mysql如何巧妙的繞過(guò)未知字段名的相關(guān)資料,文中給出了詳細(xì)的示例代碼供大家參考學(xué)習(xí),對(duì)學(xué)習(xí)mysql具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-05-05
  • Mysql 數(shù)據(jù)庫(kù)常用備份方法和注意事項(xiàng)

    Mysql 數(shù)據(jù)庫(kù)常用備份方法和注意事項(xiàng)

    Mysql 數(shù)據(jù)庫(kù)常用備份方法和注意事項(xiàng) ,需要的朋友可以參考下。
    2010-04-04
  • mysql 中如何取得漢字字段的各漢字首字母

    mysql 中如何取得漢字字段的各漢字首字母

    這篇文章主要介紹了mysql中如何取得漢字字段的各漢字首字母,需要的朋友可以參考下
    2014-08-08
  • MYSQL表優(yōu)化方法小結(jié) 講的挺全面

    MYSQL表優(yōu)化方法小結(jié) 講的挺全面

    一篇MYSQL表優(yōu)化的文章,說(shuō)的很好,使用mysql的朋友可以參考下。
    2010-05-05
  • MySQL?8.0?對(duì)?limit?的優(yōu)化技巧

    MySQL?8.0?對(duì)?limit?的優(yōu)化技巧

    從不同版本的 MySQL 發(fā)展軌跡來(lái)看 MySQL 的優(yōu)化器越來(lái)越智能 (比如大家期待已久的直方圖特性) ,能更多的減少人為干預(yù),提升執(zhí)行計(jì)劃的準(zhǔn)確性,這篇文章主要介紹了MySQL?8.0?對(duì)?limit?的優(yōu)化,需要的朋友可以參考下
    2022-10-10

最新評(píng)論

林口县| 昌黎县| 平阴县| 黄石市| 汤原县| 绥化市| 武夷山市| 大理市| 民权县| 丰台区| 论坛| 昌江| 稻城县| 辽宁省| 古蔺县| 嘉峪关市| 娱乐| 富顺县| 泽州县| 迁安市| 中方县| 西充县| 鄂伦春自治旗| 新民市| 平山县| 五家渠市| 读书| 家居| 满城县| 白银市| 玉山县| 和静县| 满城县| 鹿泉市| 龙游县| 全椒县| 宾阳县| 松江区| 竹溪县| 翁牛特旗| 西平县|