欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文深入探究MySQL自增鎖

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

自增鎖

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

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

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

  • 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;
-- 插入記錄,如果存在這條記錄就報錯(主鍵唯一)
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;
-- 如果沒有這條記錄就新增,有這條記錄就修改
replace into t4 values(1,20);  
replace into t4 set id=10,age=100 ;
replace into t4 select * from t3;

insert的不同類型

1)Simple inserts

簡單插入模式

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

2)Bulk inserts

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

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

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

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

3)Mixed-mode

該模式也屬于Simple Inserts

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

自增鎖原理

1)插入原理

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

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

image

注意:自增鎖跟事務無關,即使多個insert語句存在同一個事務中,每次insert都會申請最新的自增鎖來獲取最新的AUTO_INCREMENT值;自增鎖保持到insert語句結(jié)束,而不是事務結(jié)束;

2)自增鎖表鎖

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

image

自增鎖的模式

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

show variables like 'innodb_autoinc_lock_mode';

image

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

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

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

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

image

Tips:再次說明,自增鎖是執(zhí)行insert時獲取auto_increment值時才會申請,獲取到auto_increment值時就會立即釋放,跟事務無關;

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

在連續(xù)模式下,InnoDB會根據(jù)當前執(zhí)行的insert語句來判斷是否使用表級別自增鎖。這也是InnoDB的默認值;

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

【Simple Inserts】

image

【Bulk Inserts】

image

3)interleaved(交叉模式)

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

  • 交叉模式示意圖:

image

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

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

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

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

步驟④:然后Thread-02線程也對auto_increment+1,此時auto_increment為12

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

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

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

image

【交叉模式的注意事項】

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

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

image

自增步長控制

一般我們在創(chuàng)建表的時候id起始值為1,通過AUTO_INCREMENT可以設置其值;

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)建表后也可以通過SQL語句修改auto_increment
alter table t3 auto_increment=20;

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

-- 自增的步長
set auto_increment_increment=2;         -- 默認1

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

select last_insert_id();

【測試】

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

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

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

相關文章

  • mysql8.0無備份通過idb文件恢復數(shù)據(jù)的方法、idb文件修復和tablespace?id不一致處理

    mysql8.0無備份通過idb文件恢復數(shù)據(jù)的方法、idb文件修復和tablespace?id不一致處理

    文章描述了公司服務器斷電后數(shù)據(jù)庫故障的過程,作者通過查看錯誤日志、重新初始化數(shù)據(jù)目錄、恢復備份文件、修改配置文件等步驟,成功修復了MySQL數(shù)據(jù)庫
    2025-03-03
  • MySQL中大對象的多版本并發(fā)控制詳解

    MySQL中大對象的多版本并發(fā)控制詳解

    這篇文章主要給大家介紹了關于MySQL中大對象的多版本并發(fā)控制的相關資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用mysql具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-11-11
  • MySQL時間類型和模式詳情

    MySQL時間類型和模式詳情

    這篇文章主要介紹MySQL時間類型和模式 MySQL會在存儲時將數(shù)據(jù)值轉(zhuǎn)換為UTC標準時間來存儲,讀取時再轉(zhuǎn)為當前時間。如果你的時區(qū)沒有發(fā)生改變,則該值就是你存儲的值,如果你改變了時區(qū),讀取到的值就會發(fā)生變化。這個特性不會對DATETIME生效,需要的朋友可以參考一下
    2021-09-09
  • Mysql自連接查詢實例詳解

    Mysql自連接查詢實例詳解

    這篇文章主要介紹了Mysql自連接查詢,結(jié)合實例形式分析了MySQL自連接查詢的應用場景、原理及相關操作技巧,需要的朋友可以參考下
    2019-07-07
  • mysql主從只同步部分庫或表的思路與方法

    mysql主從只同步部分庫或表的思路與方法

    mysql主從搭建后默認同步所有庫,同步原理是通過二進制日志方式傳輸,下面這篇文章主要給大家介紹了關于mysql主從只同步部分庫或表的思路與方法,需要的朋友可以參考下
    2022-06-06
  • 詳解MySQL中的視圖

    詳解MySQL中的視圖

    視圖是一個虛擬表,非真實存在,其本質(zhì)是根據(jù)SQL語句獲取動態(tài)的數(shù)據(jù)集,并為其命名,用戶使用時只需使用視圖名稱即可獲取結(jié)果集,并可以將其當作表來使用,這篇文章主要介紹了MySQL的視圖,需要的朋友可以參考下
    2022-12-12
  • MySQL中WITH用法小結(jié)

    MySQL中WITH用法小結(jié)

    WITH子句是MySQL中的一種SQL結(jié)構,本文主要介紹了MySQL中WITH用法小結(jié),具有一定的參考價值,感興趣的可以了解一下
    2023-10-10
  • MySQL redo死鎖問題排查及解決過程分析

    MySQL redo死鎖問題排查及解決過程分析

    被告知在多實例場景下 MySQL Server hang 住,無法測試下去,原生版本不存在這個問題,而新版本上出現(xiàn)了這個問題,不禁心頭一顫,心中不禁感到奇怪,還好現(xiàn)場環(huán)境還在,為排查問題提供了一個好的環(huán)境,隨即便投入到緊張的問題排查過程當中
    2016-10-10
  • MySQL安裝時initializing database失敗的問題解決

    MySQL安裝時initializing database失敗的問題解決

    本文主要介紹了MySQL安裝時initializing database失敗的問題解決,文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-02-02
  • 詳解mysql數(shù)據(jù)庫增刪改操作

    詳解mysql數(shù)據(jù)庫增刪改操作

    這篇文章主要介紹了mysql數(shù)據(jù)庫增刪改操作,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-04-04

最新評論