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

MYSQL數(shù)據(jù)庫(kù)Innodb?引擎mvcc鎖實(shí)現(xiàn)原理

 更新時(shí)間:2022年05月06日 11:22:45   作者:??斜月????  
這篇文章主要介紹了MYSQL數(shù)據(jù)庫(kù)Innodb?引擎mvcc鎖實(shí)現(xiàn)原理,但是mvcc?的實(shí)現(xiàn)原理是什么呢?下文我們就來(lái)實(shí)例說(shuō)明來(lái)mvcc?的實(shí)現(xiàn)原理,感興趣的小伙伴可以參考一下

前言:

大家都知道在java 開(kāi)發(fā)過(guò)程中,會(huì)經(jīng)常用到鎖,在java 代碼中,我們都知道鎖是加在對(duì)象頭上的,在java對(duì)象布局中有鎖的標(biāo)志位。程序通過(guò)判斷鎖的標(biāo)志位來(lái)獲取加鎖的情況。但是在mysql 中,鎖的實(shí)現(xiàn)原理是什么呢。可能大家都聽(tīng)過(guò) mvcc,但是mvcc 的實(shí)現(xiàn)原理是什么呢,可能就說(shuō)不太清楚了,本文就以實(shí)例說(shuō)明來(lái)mvcc 的實(shí)現(xiàn)原理。

1 數(shù)據(jù)庫(kù)設(shè)置隔離級(jí)別

我們都知道數(shù)據(jù)庫(kù)的隔離級(jí)別可以分為以下:

  • 讀未提交 RU : read uncommitted  
  • 讀提交   RC : read committed 
  • 可重復(fù)讀 RR : repeatable read 默認(rèn)隔離級(jí)別
  • 序列化   SE : serializable 序列化

我們使用select @@transaction_isolation;來(lái)查看數(shù)據(jù)庫(kù)的隔離級(jí)別,可能有讀者會(huì)有疑問(wèn)了,不是應(yīng)該是select @@tx_isolation;嗎, 因?yàn)槲业碾娔X上裝的是 mysql 8.0, 之前的 tx 也是 transaction的簡(jiǎn)寫(xiě),高版本的mysql 已經(jīng)使用 transaction 了。

# 查詢(xún)當(dāng)前會(huì)話(huà)隔離級(jí)別
select @@transaction_isolation;
# 查看當(dāng)前系統(tǒng)的隔離級(jí)別
select @@global.transaction_isolation;
# 命令行開(kāi)啟事務(wù),區(qū)別在于前者是第一條語(yǔ)句的執(zhí)行時(shí)間點(diǎn)為事務(wù)開(kāi)始的時(shí)間點(diǎn),建立一致性讀,后者是立即建立一致性讀,開(kāi)始執(zhí)行事務(wù)
start transaction 或者 start transaction with consistent snapshot
# 設(shè)置數(shù)據(jù)庫(kù)隔離級(jí)別,如若設(shè)置會(huì)話(huà)級(jí)別,則修改 global 為session 即可
set global transaction isolation level REPEATABLE READ;
set global transaction isolation level READ COMMITTED;
set global transaction isolation level READ UNCOMMITTED;
set global transaction isolation level SERIALIZABLE;

2 數(shù)據(jù)庫(kù)表以及案例操作

操作的數(shù)據(jù)庫(kù)表為:

CREATE TABLE `t_user` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主鍵',
  `age` int DEFAULT NULL COMMENT '年齡',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶(hù)表';
# 初始化語(yǔ)句
INSERT INTO `t_user`(`id`, `age`) VALUES (1, 3);
# 使用的操作語(yǔ)句
select * from t_user where id = 1;
update t_user set age = age + 1  where id = 1;

案例如圖所示:

 sessionA,sessionB,sessionC 是連接數(shù)據(jù)庫(kù)的3個(gè)會(huì)話(huà)窗口,mysql 數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別為RR,為了達(dá)到效果我們把當(dāng)前的數(shù)據(jù)庫(kù)隔離級(jí)別改為RC,語(yǔ)句如下:

set session transaction isolation level READ COMMITTED;

setp1 準(zhǔn)備工作,設(shè)置當(dāng)前會(huì)話(huà)事務(wù)隔離級(jí)別,查看數(shù)據(jù)庫(kù)表中的數(shù)據(jù)。窗口從左往右依次是sessionA、sessinB和sessionC。 

setp2 t1 時(shí)刻,sessionA 和 sessionB 開(kāi)啟事務(wù)。sessionA t2 時(shí)刻執(zhí)行查詢(xún)語(yǔ)句,sessionC 執(zhí)行更新操作,可以看到此時(shí) sessionC 立馬執(zhí)行成功。 

step3 t3 時(shí)刻,sessionB 查詢(xún)最新的數(shù)據(jù),并執(zhí)行更新操作 

step4 t4 時(shí)刻,sessionA 查詢(xún)最新數(shù)據(jù),并在t5 時(shí)刻更新數(shù)據(jù),這里因?yàn)閟essionB 的事務(wù)還未結(jié)束,因此執(zhí)行的操作會(huì)阻塞到超時(shí)(這里刻意等待到超時(shí)),t6 時(shí)刻sessionB 查詢(xún)數(shù)據(jù),并提交事務(wù)。 

step5 sesionB 提交事務(wù)后,sessionA 重新執(zhí)行語(yǔ)句,可以看到執(zhí)行后的結(jié)果,然后提交事務(wù)。 

通過(guò)上述的操作案例,我們可以觀察到:

  • 在一個(gè)事務(wù)中的數(shù)據(jù)更改對(duì)本事務(wù)是可見(jiàn)的,此外的事務(wù)是否可見(jiàn)取決于其隔離級(jí)別。
  • 兩個(gè)事務(wù)操作同一條數(shù)據(jù),會(huì)造成等待。innodb 引擎默認(rèn)開(kāi)啟死鎖檢測(cè),并會(huì)設(shè)置鎖的超時(shí)時(shí)間。
# 設(shè)置超時(shí)時(shí)間默認(rèn)是50s
innodb_lock_wait_timeout 
# 開(kāi)啟死鎖檢測(cè),默認(rèn)是開(kāi)啟死鎖檢測(cè),默認(rèn)值為 on,開(kāi)啟死鎖檢測(cè)
innodb_deadlock_detect
# 查看更多innodb 引擎的配置
show variables like '%innodb%'
  • 在會(huì)話(huà)中進(jìn)行數(shù)據(jù)修改,默認(rèn)事務(wù)是自動(dòng)提交的。

3 mvcc 實(shí)現(xiàn)原理

mvcc,Multi-Version Concurrency Control,即版本并發(fā)訪(fǎng)問(wèn)控制,是 mysql innodb 引擎實(shí)現(xiàn)的一種并發(fā)訪(fǎng)問(wèn)控制方法,用于其事務(wù)的實(shí)現(xiàn)。其主要作用是為了提高數(shù)據(jù)庫(kù)的并發(fā)性能,更好地處理讀寫(xiě)沖突問(wèn)題,在遇到?jīng)_突的境況也能夠做到不加鎖,非阻塞并發(fā)讀取數(shù)據(jù)。 在解釋實(shí)現(xiàn)原理前,先了解一下當(dāng)前讀和快照讀。

  • 當(dāng)前讀:像更改數(shù)據(jù)的操作(update/delete/insert)操作還有共享鎖和排他鎖(lock in share mode和for update)這操作都需要讀取當(dāng)前最新版本的數(shù)據(jù),否則就會(huì)有更新丟失的情況。數(shù)據(jù)庫(kù)的修改操作也是將數(shù)據(jù)所在的數(shù)據(jù)頁(yè)從磁盤(pán)加載到內(nèi)存,然后進(jìn)行修改,最后寫(xiě)回到磁盤(pán)中。
  • 快照讀:不加鎖的select獲取數(shù)據(jù)就是讀快照,不會(huì)產(chǎn)生阻塞。在串行化的數(shù)據(jù)庫(kù)隔離級(jí)別下,快照讀會(huì)退化成當(dāng)前度。每行數(shù)據(jù)都有多個(gè)版本,當(dāng)前讀就是獲取最新的已經(jīng)提交過(guò)得版本數(shù)據(jù)。

接下來(lái)講述的是非常重要的部分:

  • 已經(jīng)提交的事務(wù)
  • 未被提交的事務(wù)
  • 未開(kāi)始的事務(wù)

在可重復(fù)讀的隔離級(jí)別下,事務(wù)啟動(dòng)需要對(duì)整個(gè)庫(kù)做備份,這顯然是不可能的,實(shí)際上mvcc也沒(méi)有這樣做,而是利用版本號(hào)來(lái)控制,也就是事務(wù)開(kāi)始時(shí)向 innodb 事務(wù)系統(tǒng)申請(qǐng)一個(gè) transaction id,這個(gè)id申請(qǐng)順序是嚴(yán)格遞增的。每行數(shù)據(jù)的版本號(hào) row trx_id = transaction id , 也就可以保證其版本的唯一性??梢员WC事務(wù)啟動(dòng)時(shí),會(huì)獲取當(dāng)前所有活躍事務(wù)id的數(shù)組,可以保證其唯一性。事務(wù)id數(shù)組中的最小的id記為低水位,數(shù)組中的最大id+1記為高水位。低水位和高水位便是已經(jīng)提交的事務(wù)-未提交的數(shù)據(jù)、未提交的事務(wù)-未開(kāi)始的事務(wù)的分界標(biāo)志位,以上就組成了當(dāng)前事務(wù)的一致性視圖(read-view)。

前面已經(jīng)提到了,所有的數(shù)據(jù)都是有版本的,這個(gè)版本即row trx_id。當(dāng)需要讀快照時(shí),就需要讀取trx_id小于低水位且最大的trx_id版本號(hào)的數(shù)據(jù)。讀當(dāng)前就是讀取當(dāng)前最新版本的數(shù)據(jù),如果數(shù)據(jù)正在事務(wù)的處理中,那么久需要等待,這也是為什么會(huì)出現(xiàn)鎖等待超時(shí)的情況。

當(dāng)在RC的數(shù)據(jù)庫(kù)隔離級(jí)別下,每次的操作都會(huì)重新獲取當(dāng)前活躍的trx_id數(shù)組,形成新的一致性視圖,這就是sessionB 在t3 時(shí)刻讀取到了sessionC 在t2時(shí)刻提交的數(shù)據(jù),因?yàn)樵谛碌囊恢滦砸晥D中,sessionC 的trx_id 已經(jīng)已經(jīng)提交的事務(wù)了,所以就可以讀取到。在sessionA 的t5 時(shí)刻,拿到的一致性視圖中活躍的trx_id 數(shù)組中包含 sessionB 的活躍id,因?yàn)樵诟聰?shù)據(jù)時(shí),需要當(dāng)前讀,而數(shù)據(jù)已經(jīng)被鎖住,所以出現(xiàn)了鎖超時(shí)的情況。

而在RR的數(shù)據(jù)庫(kù)隔離級(jí)別下,在事務(wù)開(kāi)始時(shí)生成一個(gè)一致性視圖,此后在事務(wù)提交之前,其 trx_id 數(shù)組不會(huì)發(fā)生變化,這樣才能保證其可重復(fù)讀的特性。RR相對(duì)于RC實(shí)現(xiàn)簡(jiǎn)單,區(qū)別在于是否在執(zhí)行語(yǔ)句前更新一致性視圖,活躍事務(wù)id的數(shù)組是否更新。

綜上,我們就知道了mvcc 是如何實(shí)現(xiàn)可重復(fù)讀和讀提交的隔離級(jí)別了。

4 ACID 的實(shí)現(xiàn)

  • 事務(wù)的原子性 A 是通過(guò) undolog 回滾日志來(lái)實(shí)現(xiàn)。
  • 事務(wù)的持久性 C 性是通過(guò) redolog 重做日志來(lái)實(shí)現(xiàn)的。
  • 事務(wù)的隔離性 I 是通過(guò) MVCC 來(lái)實(shí)現(xiàn)的。
  • 原子性,持久性,隔離性都實(shí)現(xiàn)了,那么一致性 D 也就實(shí)現(xiàn)了。

redo log 是mysql innodb 引擎產(chǎn)生的物理日志,其大小有一定的限制,采用循環(huán)寫(xiě)入的方式,寫(xiě)滿(mǎn)之后進(jìn)行刷盤(pán)。主要用于宕機(jī)后的數(shù)據(jù)恢復(fù)。redo log是一個(gè)循環(huán)寫(xiě)入的日志,可以理解為一個(gè)環(huán),有 checkpoint 和 write pos 兩個(gè)標(biāo)志點(diǎn),checkpoint之前的空間是清除后的可寫(xiě)空間,清除之前會(huì)更新到磁盤(pán)中,write pos是數(shù)據(jù)寫(xiě)入的位置,當(dāng)兩個(gè)標(biāo)志點(diǎn)相遇表明redo log已經(jīng)滿(mǎn)了,這時(shí)數(shù)據(jù)庫(kù)停止進(jìn)行數(shù)據(jù)庫(kù)更新語(yǔ)句的執(zhí)行,轉(zhuǎn)而進(jìn)行redo log日志同步到磁盤(pán)中。

binlog 是mysql server 層記錄邏輯的日志,可以一致追加寫(xiě)入,主要用于主從數(shù)據(jù)同步。

到此這篇關(guān)于MYSQL數(shù)據(jù)庫(kù)Innodb 引擎mvcc鎖實(shí)現(xiàn)原理的文章就介紹到這了,更多相關(guān)mysql mvcc鎖實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Win10安裝MySQL5.7.18winX64 啟動(dòng)服務(wù)器失敗并且沒(méi)有錯(cuò)誤提示

    Win10安裝MySQL5.7.18winX64 啟動(dòng)服務(wù)器失敗并且沒(méi)有錯(cuò)誤提示

    這篇文章主要介紹了Win10安裝MySQL5.7.18winX64 啟動(dòng)服務(wù)器失敗并且沒(méi)有錯(cuò)誤提示,需要的朋友可以參考下
    2017-06-06
  • 查看修改MySQL表結(jié)構(gòu)命令

    查看修改MySQL表結(jié)構(gòu)命令

    這篇文章主要介紹了查看修改MySQL表結(jié)構(gòu)命令,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • 三種東西永遠(yuǎn)不要放到mysql數(shù)據(jù)庫(kù)里

    三種東西永遠(yuǎn)不要放到mysql數(shù)據(jù)庫(kù)里

    這篇文章主要介紹了mysql數(shù)據(jù)庫(kù)不能存儲(chǔ)的三樣?xùn)|西,需要的朋友可以參考下
    2014-06-06
  • mysql創(chuàng)建存儲(chǔ)過(guò)程實(shí)現(xiàn)往數(shù)據(jù)表中新增字段的方法分析

    mysql創(chuàng)建存儲(chǔ)過(guò)程實(shí)現(xiàn)往數(shù)據(jù)表中新增字段的方法分析

    這篇文章主要介紹了mysql創(chuàng)建存儲(chǔ)過(guò)程實(shí)現(xiàn)往數(shù)據(jù)表中新增字段的方法,結(jié)合實(shí)例形式對(duì)比分析了通過(guò)存儲(chǔ)過(guò)程新增字段相關(guān)操作技巧,需要的朋友可以參考下
    2018-12-12
  • Mysql高效分頁(yè)詳解

    Mysql高效分頁(yè)詳解

    這篇文章主要為大家詳細(xì)介紹了Mysql高效分頁(yè)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • MySQL約束(創(chuàng)建表時(shí)的各種條件說(shuō)明)

    MySQL約束(創(chuàng)建表時(shí)的各種條件說(shuō)明)

    這篇文章主要介紹了MySQL約束(創(chuàng)建表時(shí)的各種條件說(shuō)明),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • MySQL中的binlog相關(guān)命令和恢復(fù)技巧

    MySQL中的binlog相關(guān)命令和恢復(fù)技巧

    這篇文章主要介紹了MySQL中的binlog相關(guān)命令和恢復(fù)技巧,需要的朋友可以參考下
    2014-05-05
  • MySQL入門(mén)(四) 數(shù)據(jù)表的數(shù)據(jù)插入、更新、刪除

    MySQL入門(mén)(四) 數(shù)據(jù)表的數(shù)據(jù)插入、更新、刪除

    這篇文章主要介紹了mysql數(shù)據(jù)庫(kù)中表的插入、更新、刪除非常簡(jiǎn)單,但是簡(jiǎn)單的也要學(xué)習(xí),細(xì)節(jié)決定成敗,需要的朋友可以參考下
    2018-07-07
  • 最新評(píng)論