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

詳解MySql中InnoDB存儲引擎中的各種鎖

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

什么是鎖

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

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

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

InnoDB存儲引擎中的鎖

InnoDB存儲引擎實現(xiàn)了如下兩種標準的行級鎖:

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

鎖的兼容性

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

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

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

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

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

在這里插入圖片描述

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

InnoDB存儲引擎支持的意向鎖即為表級別的鎖。支持兩種意向鎖

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

由于InnoDB存儲引擎支持的是行級別的鎖,因此意向鎖其實不會阻塞除全表掃以外的任何請求。故表級意向鎖與行級鎖的兼容性如表所示

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

一致性非鎖定讀

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

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

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

快照數(shù)據(jù)是指該行的之前版本的數(shù)據(jù),該實現(xiàn)是通過undo段來完成。而undo用來在事務(wù)中回滾數(shù)據(jù),因此快照數(shù)據(jù)本身是沒有額外的開銷。此外,讀取快照數(shù)據(jù)是不需要上鎖的,因為沒有事務(wù)需要對歷史的數(shù)據(jù)進行修改操作

在這里插入圖片描述

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

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

那這么多歷史的快速版本,訪問的時候該用哪一個呢?

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

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

一致性鎖定讀

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

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

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

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

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

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

鎖的算法

行鎖的3種算法

  • Record Lock:單個行記錄上的鎖
  • Gap Lock:間隙鎖,鎖定一個范圍,但不包含記錄本身
  • Next-Key Lock∶Gap Lock+Record Lock,鎖定一個范圍,并且鎖定記錄本身

Record Lock總是會去鎖住索引記錄,如果InnoDB存儲引擎表在建立的時候沒有設(shè)置任何一個索引,那么這時InnoDB存儲引擎會使用隱式的主鍵來進行鎖定

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

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

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

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

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

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

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

幻像問題

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

看下面的場景:

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

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

InnoDB存儲引擎默認的事務(wù)隔離級別是REPEATABLE READ,在該隔離級別下,其采用Next-Key Locking的方式來加鎖

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

鎖的問題

臟讀

臟讀指的就是在不同的事務(wù)下,當前事務(wù)可以讀到另外事務(wù)未提交的數(shù)據(jù),簡單來說就是可以讀到臟數(shù)據(jù)

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

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

不可重復(fù)讀

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

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

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

在InnoDB存儲引擎中,通過使用Next-Key Lock算法來避免不可重復(fù)讀的問題。

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

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

丟失更新

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

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

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

死鎖

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

解決死鎖問題最簡單的一種方法是超時,即當兩個事務(wù)互相等待時,當一個等待時間超過設(shè)置的某一閾值時,其中一個事務(wù)進行回滾,另一個等待的事務(wù)就能繼續(xù)進行。在InnoDB存儲引擎中,參數(shù)innodb_lock_wait_timeout用來設(shè)置超時的時間

超時機制雖然簡單,但是其僅通過超時后對事務(wù)進行回滾的方式來處理,或者說其是根據(jù)FIFO的順序選擇回滾對象。但若超時的事務(wù)所占權(quán)重比較大,如事務(wù)操作更新了很多行,占用了較多的undo log,這時采用FIFO的方式,就顯得不合適了,因為回滾這個事務(wù)的時間相對另一個事務(wù)所占用的時間可能會很多

因此,除了超時機制,當前數(shù)據(jù)庫還都普遍采用wait-for graph(等待圖)的方式來進行死鎖檢測。

較之超時的解決方案,這是一種更為主動的死鎖檢測方式。InnoDB存儲引擎也采用的這種方式。

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

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

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

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

相關(guān)文章

  • Mysql?InnoDB引擎中的數(shù)據(jù)頁結(jié)構(gòu)詳解

    Mysql?InnoDB引擎中的數(shù)據(jù)頁結(jié)構(gòu)詳解

    這篇文章主要為大家介紹了Mysql?InnoDB引擎中的數(shù)據(jù)頁結(jié)構(gòu)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • 解決mysql使用not in 包含null值的問題

    解決mysql使用not in 包含null值的問題

    這篇文章主要介紹了解決mysql使用not in 包含null值的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • MySQL?原理優(yōu)化之Group?By的優(yōu)化技巧

    MySQL?原理優(yōu)化之Group?By的優(yōu)化技巧

    這篇文章主要介紹了MySQL?原理優(yōu)化之Group?By的優(yōu)化技巧,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • mysql 列轉(zhuǎn)行,合并字段的方法(必看)

    mysql 列轉(zhuǎn)行,合并字段的方法(必看)

    下面小編就為大家?guī)硪黄猰ysql 列轉(zhuǎn)行,合并字段的方法(必看)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • MySQL數(shù)據(jù)庫可以用任意ip連接訪問的方法

    MySQL數(shù)據(jù)庫可以用任意ip連接訪問的方法

    本文主要介紹了MySQL數(shù)據(jù)庫可以用任意ip連接訪問的方法,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Mysql賬號管理與引擎相關(guān)功能實現(xiàn)流程

    Mysql賬號管理與引擎相關(guān)功能實現(xiàn)流程

    Mysql中的每一種技術(shù)都使用不同的存儲機制、索引技巧、鎖定水平、并且最終提供廣泛的不同功能和能力。通過選擇不同的技術(shù),你能夠獲得額外的速度或者功能,從而改善應(yīng)用的整體功能。這些不同的技術(shù)以及配套的相關(guān)功能在MySQL中被稱作存儲引擎
    2022-10-10
  • MySQL 基礎(chǔ)常用命令總結(jié)

    MySQL 基礎(chǔ)常用命令總結(jié)

    這篇文章主要介紹了MySQL 的基礎(chǔ)常用命令,在執(zhí)行語句的時候,很多命令都是必須記住的,想具體了解的小伙伴請參考下面文章內(nèi)容
    2021-09-09
  • MySql存儲引擎的作用

    MySql存儲引擎的作用

    mysql面試中最常問的問題之一:小伙子,你說一下你們公司用的存儲引擎,以及你知道有哪些存儲引擎和他們之間的區(qū)別? 所以下面這篇文章主要給大家介紹了關(guān)于Mysql存儲引擎的相關(guān)資料,需要的朋友可以參考下
    2022-09-09
  • 解決mysql導(dǎo)入還原時亂碼的問題

    解決mysql導(dǎo)入還原時亂碼的問題

    sql文件,直接記事本方式打開,中文顯示正常,還原導(dǎo)入后,發(fā)現(xiàn)中文是亂碼
    2012-12-12
  • SQL優(yōu)化老出錯,那是你沒弄明白MySQL解釋計劃用法

    SQL優(yōu)化老出錯,那是你沒弄明白MySQL解釋計劃用法

    本篇文章講的是SQL優(yōu)化老出錯,那是你沒弄明白MySQL解釋計劃用法,有興趣的小伙伴速度來看看吧,希望本篇文章能夠幫助到你
    2021-11-11

最新評論