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

詳解MySql中InnoDB存儲(chǔ)引擎中的各種鎖

 更新時(shí)間:2022年02月11日 09:36:30   作者:果子爸聊技術(shù)  
本文主要介紹了詳解MySql中InnoDB存儲(chǔ)引擎中的各種鎖,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

什么是鎖

現(xiàn)實(shí)生活中的鎖是為了保護(hù)你的私有物品,在數(shù)據(jù)庫(kù)中鎖是為了解決資源爭(zhēng)搶的問(wèn)題,鎖是數(shù)據(jù)庫(kù)系統(tǒng)區(qū)別于文件系統(tǒng)的一個(gè)關(guān)鍵特性。鎖機(jī)制用于管理對(duì)共享資源的并發(fā)訪。

數(shù)據(jù)庫(kù)系統(tǒng)使用鎖是為了支持對(duì)共享資源進(jìn)行并發(fā)訪問(wèn),提供數(shù)據(jù)的完整性和一致性

InnoDB存儲(chǔ)引擎區(qū)別于MyISAM的兩個(gè)重要特征就是:InnoDB存儲(chǔ)引擎支持事務(wù)和行級(jí)別的鎖,MyISAM只支持表級(jí)別的鎖

InnoDB存儲(chǔ)引擎中的鎖

InnoDB存儲(chǔ)引擎實(shí)現(xiàn)了如下兩種標(biāo)準(zhǔn)的行級(jí)鎖:

共享鎖(S Lock),允許事務(wù)讀一行數(shù)據(jù)排他鎖(X Lock),允許事務(wù)刪除或更新一行數(shù)據(jù)

鎖的兼容性

-XS
X不兼容不兼容
S不兼容兼容

可以看到,X排他鎖不與其他鎖兼容,S共享鎖只與S兼容

此外,InnoDB存儲(chǔ)引擎支持多粒度(granular)鎖定,這種鎖定允許事務(wù)在行級(jí)上的鎖和表級(jí)上的鎖同時(shí)存在

為了支持在不同粒度上進(jìn)行加鎖操作,InnoDB存儲(chǔ)引擎支持一種額外的鎖方式,稱之為意向鎖(Intention Lock)。

意向鎖是將鎖定的對(duì)象分為多個(gè)層次,意向鎖意味著事務(wù)希望在更細(xì)粒度(fine granularity)上進(jìn)行加鎖

在這里插入圖片描述

如上圖,數(shù)據(jù)庫(kù)從上到下可以分為數(shù)據(jù)庫(kù)、表、頁(yè)、記錄四個(gè)層次,行記錄是最細(xì)粒度的鎖,我們?cè)讷@取行鎖的時(shí)候,需要從上到下各個(gè)級(jí)別分別進(jìn)行鎖定,最后才能獲取到行鎖。比如,你要獲取行記錄x的鎖,需要先在數(shù)據(jù)庫(kù)、表、頁(yè)上加意向鎖IX,其中任何一方需要等待鎖,會(huì)造成行鎖的等待

InnoDB存儲(chǔ)引擎支持的意向鎖即為表級(jí)別的鎖。支持兩種意向鎖

  • 意向共享鎖(IS Lock),事務(wù)想要獲得一張表中某幾行的共享鎖
  • 意向排他鎖(IX Lock),事務(wù)想要獲得一張表中某幾行的排他鎖

由于InnoDB存儲(chǔ)引擎支持的是行級(jí)別的鎖,因此意向鎖其實(shí)不會(huì)阻塞除全表掃以外的任何請(qǐng)求。故表級(jí)意向鎖與行級(jí)鎖的兼容性如表所示

-ISIXSX
IS兼容兼容兼容不兼容
IX兼容兼容不兼容不兼容
S兼容不兼容兼容不兼容
X不兼容不兼容不兼容不兼容

一致性非鎖定讀

一致性的非鎖定讀(consistent nonlocking read)是指InnoDB存儲(chǔ)引擎通過(guò)行多版本控制(multi versioning)的方式來(lái)讀取當(dāng)前執(zhí)行時(shí)間數(shù)據(jù)庫(kù)中行的數(shù)據(jù)。

如果讀取的行正在執(zhí)行DELETE或UPDATE操作,這時(shí)讀取操作不會(huì)因此去等待行上鎖的釋放。

相反地,InnoDB存儲(chǔ)引擎會(huì)去讀取行的一個(gè)快照數(shù)據(jù)

快照數(shù)據(jù)是指該行的之前版本的數(shù)據(jù),該實(shí)現(xiàn)是通過(guò)undo段來(lái)完成。而undo用來(lái)在事務(wù)中回滾數(shù)據(jù),因此快照數(shù)據(jù)本身是沒(méi)有額外的開(kāi)銷。此外,讀取快照數(shù)據(jù)是不需要上鎖的,因?yàn)闆](méi)有事務(wù)需要對(duì)歷史的數(shù)據(jù)進(jìn)行修改操作

在這里插入圖片描述

快照數(shù)據(jù)其實(shí)就是當(dāng)前行數(shù)據(jù)之前的歷史版本,每行記錄可能有多個(gè)版本。如上圖,記錄B就有多個(gè)歷史的快照版本
這就是大名鼎鼎的MVCC

多版本并發(fā)控制(Multi Version Concurrency Control,MVCC)是指一個(gè)行記錄有多個(gè)快照版本,由多個(gè)快照版本引發(fā)的并發(fā)控制,叫做多版本并發(fā)控制

那這么多歷史的快速版本,訪問(wèn)的時(shí)候該用哪一個(gè)呢?

  • 在READ COMMITTED事務(wù)隔離級(jí)別下,非一致性讀總是讀取被鎖定行的最新一份快照數(shù)據(jù)
  • 在REPEATABLE READ事務(wù)隔離級(jí)別下,非一致性讀總是讀取事務(wù)開(kāi)始時(shí)的行數(shù)據(jù)版本

由此可見(jiàn),不同的事務(wù)隔離級(jí)別在MVCC的處理上還不一樣

一致性鎖定讀

在默認(rèn)配置下,即事務(wù)的隔離級(jí)別為REPEATABLE READ模式下,InnoDB存儲(chǔ)引擎的SELECT操作使用一致性非鎖定讀

但是在某些情況下,用戶需要顯式地對(duì)數(shù)據(jù)庫(kù)讀取操作進(jìn)行加鎖以保證數(shù)據(jù)邏輯的一致性

InnoDB存儲(chǔ)引擎對(duì)于SELECT語(yǔ)句支持兩種一致性的鎖定讀(locking read)操作:

  • SELECT…FOR UPDATE 對(duì)讀取的行記錄加一個(gè)X鎖,其他事務(wù)不能對(duì)已鎖定的行加上任何鎖
  • SELECT…LOCK IN SHARE MODE對(duì)讀取的行記錄加一個(gè)S鎖,其他事務(wù)可以向被鎖定的行加S鎖,但是如果加X(jué)鎖,則會(huì)被阻塞

對(duì)于一致性非鎖定讀,即使讀取的行已被執(zhí)行了SELECT…FOR UPDATE,也是可以進(jìn)行讀取的

一致性鎖定讀則需要檢查被讀取的行上有沒(méi)有互斥的鎖,假如有互斥的鎖存在就需要等待鎖的釋放

鎖的算法

行鎖的3種算法

  • Record Lock:?jiǎn)蝹€(gè)行記錄上的鎖
  • Gap Lock:間隙鎖,鎖定一個(gè)范圍,但不包含記錄本身
  • Next-Key Lock∶Gap Lock+Record Lock,鎖定一個(gè)范圍,并且鎖定記錄本身

Record Lock總是會(huì)去鎖住索引記錄,如果InnoDB存儲(chǔ)引擎表在建立的時(shí)候沒(méi)有設(shè)置任何一個(gè)索引,那么這時(shí)InnoDB存儲(chǔ)引擎會(huì)使用隱式的主鍵來(lái)進(jìn)行鎖定

Gap Lock的作用是為了阻止多個(gè)事務(wù)將記錄插入到同一范圍內(nèi),而這會(huì)導(dǎo)致幻讀問(wèn)題的產(chǎn)生

用戶可以通過(guò)以下兩種方式來(lái)顯式地關(guān)閉Gap Lock:

  • 將事務(wù)的隔離級(jí)別設(shè)置為READ COMMITTED
  • 將參數(shù)innodb_locks_unsafe_for_binlog設(shè)置為1

在上述的配置下,除了外鍵約束和唯一性檢查依然需要的Gap Lock,其余情況僅使用RecordLock進(jìn)行鎖定。

但需要牢記的是,上述設(shè)置破壞了事務(wù)的隔離性,并且對(duì)于replication,可能會(huì)導(dǎo)致主從數(shù)據(jù)的不一致。

Next-Key Lock是結(jié)合了Gap Lock和Record Lock的一種鎖定算法,在Next-Key Lock算法下,InnoDB對(duì)于行的查詢都是采用這種鎖定算法

當(dāng)查詢的索引含有唯一屬性時(shí),InnoDB存儲(chǔ)引擎會(huì)對(duì)Next-Key Lock進(jìn)行優(yōu)化,將其降級(jí)為Record Lock,即僅鎖住索引本身,而不是范圍

幻像問(wèn)題

幻像問(wèn)題(Phantom Problem)是指在同一事務(wù)下,連續(xù)執(zhí)行兩次同樣的SQL語(yǔ)句可能導(dǎo)致不同的結(jié)果,第二次的SQL語(yǔ)句可能會(huì)返回之前不存在的行

看下面的場(chǎng)景:

  • 表t由1、2、5這三個(gè)值組成
  • 執(zhí)行select * from t where a > 2 for update;
  • 上述事務(wù)T1并沒(méi)有提交,那么此時(shí)另一個(gè)事務(wù)T2插入4這個(gè)值,并且數(shù)據(jù)庫(kù)允許這個(gè)操作
  • 那么事務(wù)T1再執(zhí)行上述查詢,就得到4、5兩筆記錄,跟第一次得到的結(jié)果不一樣,違反了事務(wù)的隔離性

InnoDB存儲(chǔ)引擎采用Next-Key Locking的算法避免幻像問(wèn)題。對(duì)于上述的SQL語(yǔ)句select * from t where a > 2 for update,其鎖住的不是5這單個(gè)值,而是對(duì)(2,+∞)這個(gè)范圍加了X鎖。因此任何對(duì)于這個(gè)范圍的插入都是不被允許的,從而避免幻像問(wèn)題

InnoDB存儲(chǔ)引擎默認(rèn)的事務(wù)隔離級(jí)別是REPEATABLE READ,在該隔離級(jí)別下,其采用Next-Key Locking的方式來(lái)加鎖

而在事務(wù)隔離級(jí)別READ COMMITTED下,其僅采用RecordLock行鎖

鎖的問(wèn)題

臟讀

臟讀指的就是在不同的事務(wù)下,當(dāng)前事務(wù)可以讀到另外事務(wù)未提交的數(shù)據(jù),簡(jiǎn)單來(lái)說(shuō)就是可以讀到臟數(shù)據(jù)

臟讀發(fā)生的條件是需要事務(wù)的隔離級(jí)別為READ UNCOMMITTED,而目前絕大部分的數(shù)據(jù)庫(kù)都至少設(shè)置成READCOMMITTED。

InnoDB存儲(chǔ)引擎默認(rèn)的事務(wù)隔離級(jí)別為READ REPEATABLE,Microsoft SQLServer數(shù)據(jù)庫(kù)為READ COMMITTED,Oracle數(shù)據(jù)庫(kù)同樣也是READ COMMITTED

不可重復(fù)讀

不可重復(fù)讀是指在一個(gè)事務(wù)內(nèi)多次讀取同一數(shù)據(jù)集合。在這個(gè)事務(wù)還沒(méi)有結(jié)束時(shí),另外一個(gè)事務(wù)也訪問(wèn)該同一數(shù)據(jù)集合,并做了一些DML操作。因此,在第一個(gè)事務(wù)中的兩次讀數(shù)據(jù)之間,由于第二個(gè)事務(wù)的修改,那么第一個(gè)事務(wù)兩次讀到的數(shù)據(jù)可能是不一樣的。這樣就發(fā)生了在一個(gè)事務(wù)內(nèi)兩次讀到的數(shù)據(jù)是不一樣的情況,這種情況稱為不可重復(fù)讀

不可重復(fù)讀和臟讀的區(qū)別是:臟讀是讀到未提交的數(shù)據(jù),而不可重復(fù)讀讀到的卻是已經(jīng)提交的數(shù)據(jù),但是其違反了數(shù)據(jù)庫(kù)事務(wù)一致性的要求

一般來(lái)說(shuō),不可重復(fù)讀的問(wèn)題是可以接受的,因?yàn)槠渥x到的是已經(jīng)提交的數(shù)據(jù),本身并不會(huì)帶來(lái)很大的問(wèn)題。因此,很多數(shù)據(jù)庫(kù)廠商(如Oracle、Microsoft SQL Server)將其數(shù)據(jù)庫(kù)事務(wù)的默認(rèn)隔離級(jí)別設(shè)置為READ COMMITTED,在這種隔離級(jí)別下允許不可重復(fù)讀的現(xiàn)象

在InnoDB存儲(chǔ)引擎中,通過(guò)使用Next-Key Lock算法來(lái)避免不可重復(fù)讀的問(wèn)題。

在MySQL官方文檔中將不可重復(fù)讀的問(wèn)題定義為Phantom Problem,即幻像問(wèn)題。在Next-Key Lock算法下,對(duì)于索引的掃描,不僅是鎖住掃描到的索引,而且還鎖住這些索引覆蓋的范圍(gap)。

因此在這個(gè)范圍內(nèi)的插入都是不允許的。這樣就避免了另外的事務(wù)在這個(gè)范圍內(nèi)插入數(shù)據(jù)導(dǎo)致的不可重復(fù)讀的問(wèn)題。因此,InnoDB存儲(chǔ)引擎的默認(rèn)事務(wù)隔離級(jí)別是READ REPEATABLE,采用Next-Key Lock算法,避免了不可重復(fù)讀的現(xiàn)象

丟失更新

丟失更新是另一個(gè)鎖導(dǎo)致的問(wèn)題,簡(jiǎn)單來(lái)說(shuō)其就是一個(gè)事務(wù)的更新操作會(huì)被另一個(gè)事務(wù)的更新操作所覆蓋,從而導(dǎo)致數(shù)據(jù)的不一致

  • 事務(wù)T1將行記錄r更新為v1,但是事務(wù)T1并未提交
  • 與此同時(shí),事務(wù)T2將行記錄r更新為v2,事務(wù)T2未提交
  • 事務(wù)T1提交
  • 事務(wù)T2提交

在當(dāng)前數(shù)據(jù)庫(kù)的任何隔離級(jí)別下,都不會(huì)導(dǎo)致數(shù)據(jù)庫(kù)理論意義上的丟失更新問(wèn)題。這是因?yàn)?,即使是READ UNCOMMITTED的事務(wù)隔離級(jí)別,對(duì)于行的DML操作,需要對(duì)行或其他粗粒度級(jí)別的對(duì)象加鎖

死鎖

死鎖是指兩個(gè)或兩個(gè)以上的事務(wù)在執(zhí)行過(guò)程中,因爭(zhēng)奪鎖資源而造成的一種互相等待的現(xiàn)象

解決死鎖問(wèn)題最簡(jiǎn)單的一種方法是超時(shí),即當(dāng)兩個(gè)事務(wù)互相等待時(shí),當(dāng)一個(gè)等待時(shí)間超過(guò)設(shè)置的某一閾值時(shí),其中一個(gè)事務(wù)進(jìn)行回滾,另一個(gè)等待的事務(wù)就能繼續(xù)進(jìn)行。在InnoDB存儲(chǔ)引擎中,參數(shù)innodb_lock_wait_timeout用來(lái)設(shè)置超時(shí)的時(shí)間

超時(shí)機(jī)制雖然簡(jiǎn)單,但是其僅通過(guò)超時(shí)后對(duì)事務(wù)進(jìn)行回滾的方式來(lái)處理,或者說(shuō)其是根據(jù)FIFO的順序選擇回滾對(duì)象。但若超時(shí)的事務(wù)所占權(quán)重比較大,如事務(wù)操作更新了很多行,占用了較多的undo log,這時(shí)采用FIFO的方式,就顯得不合適了,因?yàn)榛貪L這個(gè)事務(wù)的時(shí)間相對(duì)另一個(gè)事務(wù)所占用的時(shí)間可能會(huì)很多

因此,除了超時(shí)機(jī)制,當(dāng)前數(shù)據(jù)庫(kù)還都普遍采用wait-for graph(等待圖)的方式來(lái)進(jìn)行死鎖檢測(cè)。

較之超時(shí)的解決方案,這是一種更為主動(dòng)的死鎖檢測(cè)方式。InnoDB存儲(chǔ)引擎也采用的這種方式。

wait-for graph要求數(shù)據(jù)庫(kù)保存以下兩種信息

  • 鎖的信息鏈表
  • 事務(wù)等待鏈表

wait-for graph的死鎖檢測(cè)通常采用深度優(yōu)先的算法實(shí)現(xiàn),通常來(lái)說(shuō)InnoDB存儲(chǔ)引擎選擇回滾undo量最小的事務(wù)

到此這篇關(guān)于詳解MySql中InnoDB存儲(chǔ)引擎中的各種鎖的文章就介紹到這了,更多相關(guān)詳解MySql中InnoDB存儲(chǔ)引擎中的各種鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL 自動(dòng)清理binlog日志的方法

    MySQL 自動(dòng)清理binlog日志的方法

    這篇文章主要介紹了MySQL 自動(dòng)清理binlog日志的方法,需要的朋友可以參考下
    2016-10-10
  • MySQL系列之十一 日志記錄

    MySQL系列之十一 日志記錄

    這篇文章主要介紹了MySQL日志文件詳解,本文分別講解了錯(cuò)誤日志、二進(jìn)制日志、通用查詢?nèi)罩尽⒙樵內(nèi)罩?、Innodb的在線redo日志、更新日志等日志類型和作用介紹,需要的朋友可以參考下
    2021-07-07
  • MySQL索引優(yōu)化之不適合構(gòu)建索引及索引失效的幾種情況詳解

    MySQL索引優(yōu)化之不適合構(gòu)建索引及索引失效的幾種情況詳解

    索引是有雙面性的,合理的建立索引可以提高數(shù)據(jù)庫(kù)的效率。但是如果沒(méi)有合理的構(gòu)建索引和使用索引,可能會(huì)導(dǎo)致索引失效或者影響數(shù)據(jù)庫(kù)性能,本文主要討論的是索引失效以及不適合建立索引的場(chǎng)景
    2022-07-07
  • Mysql超時(shí)配置項(xiàng)的深入理解

    Mysql超時(shí)配置項(xiàng)的深入理解

    超時(shí)是我們?nèi)粘=?jīng)常會(huì)遇到的一個(gè)問(wèn)題,這篇文章主要給大家介紹了關(guān)于Mysql超時(shí)配置項(xiàng)的深入理解,內(nèi)容簡(jiǎn)明扼要并且容易理解,絕對(duì)能使你眼前一亮,需要的朋友可以參考下
    2023-01-01
  • 全面解析MySQL常見(jiàn)問(wèn)題的排查與解決方法

    全面解析MySQL常見(jiàn)問(wèn)題的排查與解決方法

    MySQL 是一款常用的關(guān)系型數(shù)據(jù)庫(kù)管理系統(tǒng),廣泛應(yīng)用于各類應(yīng)用開(kāi)發(fā)和數(shù)據(jù)管理場(chǎng)景,然而,在實(shí)際使用中,MySQL 有時(shí)會(huì)遇到啟動(dòng)失敗、服務(wù)中斷或性能問(wèn)題等情況,所以本文給大家介紹了MySQL常見(jiàn)問(wèn)題的排查與解決方法,需要的朋友可以參考下
    2024-11-11
  • 輕松解決MySQL忘記密碼如何重置的方法

    輕松解決MySQL忘記密碼如何重置的方法

    這篇文章主要為大家介紹了MySQL忘記密碼如何重置的方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • mysql字段名和關(guān)鍵字沖突的問(wèn)題

    mysql字段名和關(guān)鍵字沖突的問(wèn)題

    這篇文章主要介紹了mysql字段名和關(guān)鍵字沖突的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • MySQL多表聯(lián)查的實(shí)現(xiàn)思路

    MySQL多表聯(lián)查的實(shí)現(xiàn)思路

    數(shù)據(jù)庫(kù)應(yīng)用在我們的生活中是很常見(jiàn)的,在編輯一些應(yīng)用以及軟件的時(shí)候都需要用到數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于MongoDB中實(shí)現(xiàn)多表聯(lián)查的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • MySQL5.7.21安裝與密碼圖文配置教程

    MySQL5.7.21安裝與密碼圖文配置教程

    這篇文章主要為大家詳細(xì)介紹了MySQL5.7.21安裝與密碼圖文配置教程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • MySQL Explain使用詳解

    MySQL Explain使用詳解

    這篇文章主要介紹了MySQL Explain使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12

最新評(píng)論

宾川县| 新源县| 泊头市| 西安市| 彩票| 东山县| 封开县| 微博| 钟山县| 澜沧| 朝阳县| 奉贤区| 武强县| 兖州市| 武鸣县| 商南县| 扎赉特旗| 陇西县| 鄂伦春自治旗| 新邵县| 扶绥县| 婺源县| 大同县| 玛沁县| 丹江口市| 舟山市| 定边县| 古丈县| 平远县| 思茅市| 伽师县| 米泉市| 吉水县| 泸定县| 乌鲁木齐市| 尉犁县| 怀来县| 屏东市| 台中市| 青阳县| 青田县|