第六章 鎖 閱讀總結(jié)

????????開發(fā)多用戶、 數(shù)據(jù)庫驅(qū)動(dòng)的應(yīng)用時(shí), 最大的一個(gè)難點(diǎn)是: 一方面要最大程度地利用數(shù)據(jù)庫的并發(fā)訪問, 另外一方面還要確保每個(gè)用戶能以一致的方式讀取和修改數(shù)據(jù)。 為此就有了鎖(locking)的機(jī)制, 同時(shí)這也是數(shù)據(jù)庫系統(tǒng)區(qū)別于文件系統(tǒng)的一個(gè)關(guān)鍵特性。

? ??????人們認(rèn)為行級(jí)鎖總會(huì)增加開銷。 實(shí)際上, 只有當(dāng)實(shí)現(xiàn)本身會(huì)增加開銷時(shí), 行級(jí)鎖才會(huì)增加開銷。InnoDB存儲(chǔ)引擎不需要鎖升級(jí), 因?yàn)橐粋€(gè)鎖和多個(gè)鎖的開銷是相同的。

6.1 什么是鎖

? ??????鎖是數(shù)據(jù)庫系統(tǒng)區(qū)別于文件系統(tǒng)的一個(gè)關(guān)鍵特性。 鎖機(jī)制用于管理對(duì)共享資源的并發(fā)訪問。InnoDB存儲(chǔ)引擎會(huì)在行級(jí)別上對(duì)表數(shù)據(jù)上鎖, 這固然不錯(cuò)。 不過InnoDB存儲(chǔ)引擎也會(huì)在數(shù)據(jù)庫內(nèi)部其他多個(gè)地方使用鎖, 從而允許對(duì)多種不同資源提供并發(fā)訪 問。 例如, 操作緩沖池中的LRU列表, 刪除、 添加、 移動(dòng)LRU列表中的元素, 為了保證一致性, 必須有鎖的介入。 數(shù)據(jù)庫系統(tǒng)使用鎖是為了支持對(duì)共享資源進(jìn)行并發(fā)訪問,提供數(shù)據(jù)的完整性和一致性。

? ??????對(duì)于MyISAM引擎,其鎖是表鎖設(shè)計(jì)。并發(fā)情況下的讀沒有問題,但是并發(fā)插人時(shí)的性能就要差一些了,若插入是在 底部", MyISAM存儲(chǔ)引擎還是可以有一定的并發(fā)寫入操作。

? ??????InnoDB存儲(chǔ)引擎鎖的實(shí)現(xiàn)和Oracle 數(shù)據(jù)庫非常類似,提供一致性的非鎖定讀 、行級(jí)鎖支持。行級(jí)鎖沒有相關(guān)額外的開銷,并可以同時(shí)得到并發(fā)性和一致性。

6.2 lock與latch

????????latch 一般稱為問鎖(輕量級(jí)的鎖),因?yàn)槠湟箧i定的時(shí)間必須非常短。若持續(xù)的 時(shí)間長,則應(yīng)用的性能會(huì)非常差。在InnoDB存儲(chǔ)引擎中,latch 又可以分為 mutex (互斥量) 和rwlock (讀寫鎖)。其目的是用來保證并發(fā)線程操作臨界資源的正確性,并且通常沒有死鎖檢測的機(jī)制。

? ??????lock的對(duì)象是事務(wù),用來鎖定的是數(shù)據(jù)庫中的對(duì)象,如表、頁、行。并且一般lock的對(duì)象僅在事務(wù) commit或rollback后進(jìn)行釋放(不同事務(wù)隔離級(jí)別釋放的時(shí)間可能不同)。此外,lock, 正如在大多數(shù)數(shù)據(jù)庫中一樣,是有死鎖機(jī)制的。


6.3?lnnoDB存儲(chǔ)引擎中的鎖

6.3.1 鎖的類型

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

1.共享鎖(S Lock), 允許事務(wù)讀一行數(shù)據(jù)。

2.排他鎖(X Lock), 允許事務(wù)刪除或更新一行數(shù)據(jù)。

? ??????如果一個(gè)事務(wù)Tl已經(jīng)獲得了行r的共享鎖, 那么另外的事務(wù)T2可以立即獲得行r的共享鎖, 因?yàn)樽x取并沒有改變行 r 的數(shù)據(jù), 稱這種情況為鎖兼容 (Lock Compatible)。 但若有其他的事務(wù)T3想獲得行r的排他鎖, 則其必須等待事務(wù)T1, T2釋放行r上的共享鎖——這種情況稱為鎖不兼容。

? ??????此外, InnoDB 存儲(chǔ)引擎支持多粒度 (granular) 鎖定, 這種鎖定允許事務(wù)在行級(jí)上的 鎖和表級(jí)上的鎖同時(shí)存在。為了支待在不同粒度上進(jìn)行加鎖操作, InnoDB 存儲(chǔ)引擎支持 一種額外的鎖方式, 稱之為意向鎖?。意向鎖是將鎖定的對(duì)象分為多個(gè)層次, 意向鎖意味著事務(wù)希望在更細(xì)粒度 (fine granularity) 上進(jìn)行加鎖。

? ??????若將上鎖的對(duì)象看成一棵樹,那么對(duì)最下層的對(duì)象上鎖,也就是對(duì)最細(xì)粒度的對(duì)象進(jìn)行上鎖,那么首先需要對(duì)粗粒度的對(duì)象上鎖。


? ??????lnnoDB存儲(chǔ)引擎支持意向鎖設(shè)計(jì)比較簡練, 其意向鎖即為表級(jí)別的鎖。設(shè)計(jì)目的主要是為了在一個(gè)事務(wù)中揭示下一行將被請(qǐng)求的鎖類型。其支持兩種意向鎖:

1)意向共享鎖OS Lock), 事務(wù)想要獲得一張表中某幾行的共享鎖

2)意向排他鎖(IXLock), 事務(wù)想要獲得一張表中某幾行的排他鎖

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


6.3.2 一致性非鎖定讀

? ??????一致性的非鎖定讀 (consistent non locking read) 是指 lnnoDB 存儲(chǔ)引擎通過行多版本控制 (multi versioning) 的方式來讀取當(dāng)前執(zhí)行時(shí)間數(shù)據(jù)庫中行的數(shù)據(jù)。 如果讀取的行正在執(zhí)行 DELETE 或 UPDATE操作, 這時(shí)讀取操作不會(huì)因此去等待行上 鎖的釋放。 相反地, InnoDB 存儲(chǔ)引擎會(huì)去讀取行的一個(gè)快照數(shù)據(jù)。

????????圖 6-4 直觀地展現(xiàn)了 lnnoDB 存儲(chǔ)引擎一致性的非鎖定讀。 之所以稱其為非鎖定讀, 因?yàn)椴恍枰却L問的行上 X 鎖的釋放。

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

? ??????可以看到, 非鎖定讀機(jī)制極大地提高了數(shù)據(jù)庫的并發(fā)性。 在 InnoDB 存儲(chǔ)引擎的默認(rèn)設(shè)置下, 這是默認(rèn)的讀取方式, 即讀取不會(huì)占用和等待表上的鎖。 但是在不同事務(wù)隔離級(jí)別下, 讀取的方式不同, 并不是在每個(gè)事務(wù)隔離級(jí)別下都是采用非鎖定的 致性一讀。 此外, 即使都是使用非鎖定的一致性讀, 但是對(duì)于快照數(shù)據(jù)的定義也各不相同。


????????通過圖6-4可以知道, 快照數(shù)據(jù)其實(shí)就是當(dāng)前行數(shù)據(jù)之前的歷史版本, 每行記錄可能有多個(gè)版本。 就圖6-4所顯示的, 一個(gè)行記錄可能有不止一個(gè)快照數(shù)據(jù), 一般稱這種技術(shù)為行多版本技術(shù)。 由此帶來的并發(fā)控制, 稱之為多版本并發(fā)控制 (Multi Version Concurrency Control, MVCC)。

? ??????在事務(wù)隔離級(jí)別 READ COMMITTED 和 REPEATABLE READ (InnoDB 存儲(chǔ)引擎的默認(rèn)事務(wù)隔離級(jí)別)下, InnoDB 存儲(chǔ)引擎使用非鎖定的一致性讀。 然而, 對(duì)于快照數(shù)據(jù)的定義卻不相同。 在 READ COMMITTED 事務(wù)隔離級(jí)別下, 對(duì)于快照數(shù)據(jù), 非一致性讀總是讀取被鎖定行的最新一份快照數(shù)據(jù)。 而在 REPEATABLE READ 事務(wù)隔離級(jí)別下, 對(duì)千快照數(shù)據(jù), 非一致性讀總是讀取事務(wù)開始時(shí)的行數(shù)據(jù)版本。

6.3.3 一致性鎖定讀

????????InnoDB存儲(chǔ)引擎的SELECT操作使用一致性非鎖定讀。但是在某些情況下,用戶需要顯式地對(duì)數(shù)據(jù)庫讀取操作進(jìn)行加鎖以保證數(shù)據(jù)邏輯的一致性

6.3.4 自增長與鎖

????????自增長在數(shù)據(jù)庫中是非常常見的一種屬性,也是很多DBA或開發(fā)人員首選的主鍵方式。在 InnoDB存儲(chǔ)引擎的內(nèi)存結(jié)構(gòu)中,對(duì)每個(gè)含有自增長值的表都有一個(gè)自增長計(jì)數(shù)器(auto-increment counter)。當(dāng)對(duì)含有自增長的計(jì)數(shù)器的表進(jìn)行插人操作時(shí),這個(gè)計(jì) 數(shù)器會(huì)被初始化,執(zhí)行如下的語句來得到計(jì)數(shù)器的值:

SELECT MAX(auto_inc_col) FROM t FOR UPDATE;

? ??????插入操作會(huì)依據(jù)這個(gè)自增長的計(jì)數(shù)器值加1賦予自增長列。這個(gè)實(shí)現(xiàn)方式稱做AUTO-INC Locking。這種鎖其實(shí)是采用一種特殊的表鎖機(jī)制,為了提高插入的性能,鎖不是在一個(gè)事務(wù)完成后才釋放,而是 在完成對(duì)自增長值插入的 SQL語句后立即釋放。

? ??????雖然AUTO-INC Locking從一定程度上提高了并發(fā)插入的效率,但還是存在一些性一能上的問題。首先,對(duì)于有自增長值的列的并發(fā)插入性能較差,事務(wù)必須等待前 個(gè)插入的完成(雖然不用等待事務(wù)的完成)。其次,對(duì)于INSERT…SELECT的大數(shù)據(jù)量的插一個(gè)事務(wù)中的插入會(huì)影響插入的性能, 因?yàn)榱硪粋€(gè)事務(wù)中的插入會(huì)被阻塞。

????????從 MySQL 5.1.22版本開始,InnoDB存儲(chǔ)引擎中提供了一種輕量級(jí)互斥量的自增長實(shí)現(xiàn)機(jī)制,這種機(jī)制大大提高了自增長值插入的性能。并且從該版本開始,InnoDB存儲(chǔ)引擎提供了一個(gè)參數(shù)innodb_autoinc_lock_mode來控制自增長模式,該參數(shù)默認(rèn)值為1。在繼續(xù)討論新的自增長實(shí)現(xiàn)方式之前,需要對(duì)自增長的插人進(jìn)行分類。

? ??????接著來分析參數(shù)innodb_ auto inc_ lock_ mode以及各個(gè)設(shè)置下對(duì)自增的影響,其總共有三個(gè)有效值可供設(shè)定,即0、1、2,具體說明如表6-10所示。

6.3.5 外鍵和鎖

? ??????前面已經(jīng)介紹了外鍵,外鍵主要用于引用完整性的約束檢查。在InnoDB存儲(chǔ)引擎中,對(duì)于一個(gè)外鍵列,如果沒有顯式地對(duì)這個(gè)列加索引,lnnoDB存儲(chǔ)引擎自動(dòng)對(duì)其加一個(gè)索引,因?yàn)檫@樣可以避免表鎖。

? ??????于外鍵值的插入或更新,首先需要查詢父表中的記錄,即SELECT父表。但是對(duì)于父表的SELECT操作,不是使用一致性非鎖定讀的方式,因?yàn)檫@樣會(huì)發(fā)生數(shù)據(jù)不一致的問題,因此這時(shí)使用的是SELECT LOCKIN SHARE MODE方式,即主動(dòng)對(duì)父表加一個(gè)S鎖。如果這時(shí)父表上已經(jīng)這樣加X鎖,子表上的操作會(huì)被阻塞。

6.4 鎖的算法

6.4.1 行鎖的3種算法

InnoDB存儲(chǔ)引擎有3種行鎖的算法,其分別是:?

Record Lock: 單個(gè)行記錄上的鎖

Gap Lock: 間隙鎖, 鎖定一個(gè)范圍, 但不包含記錄本身

Next-Key Lock : Gap Lock+Record Lock, 鎖定一個(gè)范圍, 并且鎖定記錄本身

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

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

? ??????采用 Next-Key Lock 的鎖定技術(shù)稱為 Next-Key Locking。 其設(shè)計(jì)的目的是為了解決 Phantom Problem, 這將在下一小節(jié)中介紹。 而利用這種鎖定技術(shù), 鎖定的不是單個(gè)值, 而是一個(gè)范圍, 是謂詞鎖 (predict lock) 的一種改進(jìn)。 除了 next-key locking, 還有 previous-key locking 技術(shù)。

6.4.2 解決 Phantom Problem

????????在默認(rèn)的事務(wù)隔離級(jí)別下, 即 REPEATABLE READ 下, InnoDB 存儲(chǔ)引擎采用Next-Key Locking 機(jī)制來避免 Phantom Problem (幻像問題)。 這點(diǎn)可能不同于與其他的數(shù)據(jù)庫, 如 Oracle 數(shù)據(jù)庫, 因?yàn)槠淇赡苄枰?SERI ALIZABLE的事務(wù)隔離級(jí)別下才能 解決 Phantom Problem。? ??????

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

? ??????InnoDB存儲(chǔ)引擎默認(rèn)的事務(wù)隔離級(jí)別是REPEATABLE READ, 在該隔離級(jí)別下, 其采用Next-Key Locking的方式來加鎖。 而在事務(wù)隔離級(jí)別READ COMMITTED 下, 其僅采用Record Lock, 因此在上述的示例中, 會(huì)話A需要將事務(wù)的隔離級(jí)別設(shè)置為READ COMMITTED。

6.5 鎖問題

6.5.1 臟讀

? ??????在理解臟讀(DirtyRead)之前,需要理解臟數(shù)據(jù)的概念。但是臟數(shù)據(jù)和之前所介紹的臟頁完全是兩種不同的概念。臟頁指的是在緩沖池中已經(jīng)被修改的頁,但是還沒有刷新到磁盤中,即數(shù)據(jù)庫實(shí)例內(nèi)存中的頁和磁盤中的頁的數(shù)據(jù)是不一致的,當(dāng)然在刷新到磁盤之前,日志都已經(jīng)被寫入到了重做日志文件中。而所謂臟數(shù)據(jù)是指事務(wù)對(duì)緩沖池中行記錄的修改,并且還沒有被提交(commit)。

????????對(duì)于臟頁的讀取,是非常正常的。臟頁是因?yàn)閿?shù)據(jù)庫實(shí)例內(nèi)存和磁盤的異步造成的,這并不影響數(shù)據(jù)的一致性(或者說兩者最終會(huì)達(dá)到一致性,即當(dāng)臟頁都刷回到磁盤)。并且因?yàn)榕K頁的刷新是異步的,不影響數(shù)據(jù)庫的可用性,因此可以帶來性能的提高。??

? ??????臟數(shù)據(jù)卻截然不同,臟數(shù)據(jù)是指未提交的數(shù)據(jù),如果讀到了臟數(shù)據(jù),即一個(gè)事務(wù)可以讀到另外一個(gè)事務(wù)中未提交的數(shù)據(jù), 則顯然違反了數(shù)據(jù)庫的隔離性。

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

6.5.2 不可重復(fù)讀

? ??????不可重復(fù)讀是指在一個(gè)事務(wù)內(nèi)多次讀取同一數(shù)據(jù)集合。在這個(gè)事務(wù)還沒有結(jié)束時(shí),另外一個(gè)事務(wù)也訪問該同一數(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ù)庫事務(wù)一致性的要求。可以通過下面一個(gè)例子來觀察不可重復(fù)讀的情況。

6.5.3 丟失更新

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

1) 事務(wù)Tl將行記錄r更新為vi, 但是事務(wù)Tl并未提交。

2, 與此同時(shí),事務(wù) T2 將行記錄 r 更新為 v2, 事務(wù) T2未提交。

3) 事務(wù)Tl提交。

4)事務(wù) T2 提交。

? ??????但是,在當(dāng)前數(shù)據(jù)庫的任何隔離級(jí)別下,都不會(huì)導(dǎo)致數(shù)據(jù)庫理論意義上的丟失更新問題。這是因?yàn)?,即使是READUNCOMMITTED的事務(wù)隔離級(jí)別,對(duì)于行的DML 操作,需要對(duì)行或其他粗粒度級(jí)別的對(duì)象加鎖。因此在上述步驟 2) 中,事務(wù) T2 并不能對(duì)行記錄r進(jìn)行更新操作,其會(huì)被阻塞,直到事務(wù)Tl提交。

????????雖然數(shù)據(jù)庫能阻止丟失更新問題的產(chǎn)生,但是在生產(chǎn)應(yīng)用中還有另一個(gè)邏輯意義的 丟失更新問題,而導(dǎo)致該問題的并不是因?yàn)閿?shù)據(jù)庫本身的問題。實(shí)際上,在所有多用戶計(jì)算機(jī)系統(tǒng)環(huán)境下都有可能產(chǎn)生這個(gè)問題。簡單地說來,出現(xiàn)下面的情況時(shí),就會(huì)發(fā)生 丟失更新:

1) 事務(wù)Tl查詢一行數(shù)據(jù),放人本地內(nèi)存,并顯示給一個(gè)終端用戶 User1 。

2, 事務(wù) T2 也查詢該行數(shù)據(jù),并將取得的數(shù)據(jù)顯示給終端用戶 User2。

3) User1 修改這行記錄,更新數(shù)據(jù)庫并提交。

4) User2 修改這行記錄,更新數(shù)據(jù)庫并提交。

????????要避免丟失更新發(fā)生,需要讓事務(wù)在這種情況下的操作變成串行化,而不是并行的操作。即在上述四個(gè)步驟的I)中,對(duì)用戶讀取的記錄加上一個(gè)排他X鎖。同樣,在步驟2) 的操作過程中,用戶同樣也需要加一個(gè)排他X鎖。通過這種方式,步驟2) 就必須等待一步驟I)和步驟3)完成,最后完成步驟4)。

6.6 阻塞? ??????

? ??????因?yàn)椴煌i之間的兼容性關(guān)系,在有些時(shí)刻一個(gè)事務(wù)中的鎖需要等待另一個(gè)事務(wù)中的鎖釋放它所占用的資源,這就是 阻塞。阻塞并不是一件壞事,其是為了確保事務(wù)可以 并發(fā)且正常地運(yùn)行。

? ??????在InnoDB存儲(chǔ)引擎中,參數(shù)innodb _lock_ wait_ timeout用來控制等待的時(shí)間(默認(rèn)是50秒),innodb_rollback_on_timeout用來設(shè)定是否在等待超時(shí)時(shí)對(duì)進(jìn)行 中的事務(wù)進(jìn)行回滾操作(默認(rèn)是OFF, 代表不回滾)。參數(shù)innodb_lock_ wait_ timeout是動(dòng)態(tài)的,可以 在MySQL數(shù)據(jù)庫運(yùn)行時(shí)進(jìn)行調(diào)整,而innodb _rollback_ on_ timeout是靜態(tài)的,不 可在啟動(dòng)時(shí)進(jìn)行修改。

? ??????需要牢記的是,在默認(rèn)情況下InnoDB存儲(chǔ)引擎不會(huì)回滾超時(shí)引發(fā)的錯(cuò)誤異常。

6.7 死鎖

6.7.1 死鎖的概念

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

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

????????超時(shí)機(jī)制雖然簡單, 但是其僅通過超時(shí)后對(duì)事務(wù)進(jìn)行回滾的方式來處理, 或者說其是根據(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ù)庫還都普遍采用wait-forgraph (等待圖)的方式來進(jìn)行死鎖檢測。 較之超時(shí)的解決方案, 這是一種更為主動(dòng)的死鎖檢測方式。InnoDB存儲(chǔ)引擎也采用的這種方式。 wait-forgraph要求數(shù)據(jù)庫保存以下兩種信息:

1.鎖的信息鏈表

2.事務(wù)等待鏈表

? ??????通過上述鏈表可以構(gòu)造出一張圖, 而在這個(gè)圖中若存在回路, 就代表存在死鎖, 因此資源間相互發(fā)生等待。 在wait-for graph中, 事務(wù)為圖中的節(jié)點(diǎn)。 而在圖中, 事務(wù)Tl指向T2邊的定義為:

事務(wù)T1等待事務(wù)T2所占用的資源

事務(wù)T1最終等待T2所占用的資源, 也就是事務(wù)之間在等待相同的資源, 而事務(wù)T1發(fā)生在事務(wù)T2 的后面

????????下面來看一個(gè)例子, 當(dāng)前事務(wù)和鎖的狀態(tài)如圖6-5所示。

6.8 鎖升級(jí)

? ??????鎖升級(jí) (Lock Escalation) 是指將當(dāng)前鎖的粒度降低。 舉例來說, 數(shù)據(jù)庫可以把一個(gè)表的 1000 個(gè)行鎖升級(jí)為一個(gè)頁鎖, 或者將頁鎖升級(jí)為表鎖。 如果在數(shù)據(jù)庫的設(shè)計(jì)中認(rèn)為鎖是一種稀有資源, 而且想避免鎖的開銷, 那數(shù)據(jù)庫中會(huì)頻繁出現(xiàn)鎖升級(jí)現(xiàn)象。

? ??????InnoDB存儲(chǔ)引擎不存在鎖升級(jí)的問題。因?yàn)槠洳皇歉鶕?jù)每個(gè)記錄來產(chǎn)生行鎖的,相反,其根據(jù)每個(gè)事務(wù)訪問的每個(gè)頁對(duì)鎖進(jìn)行管理的,采用的是位圖的方式。因此不管一 個(gè)事務(wù)鎖住頁中一個(gè)記錄還是多個(gè)記錄,其開銷通常都是一致 的。

? ??????


? ??????

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容