日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL 锁与MVCC :数据库的锁、MVCC、当前读、快照读、锁算法、死锁

發布時間:2024/4/11 数据库 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL 锁与MVCC :数据库的锁、MVCC、当前读、快照读、锁算法、死锁 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

文章目錄

    • lock與latch
    • 鎖的類型
    • MVCC
      • 一致性非鎖定讀(快照讀)
      • 一致性鎖定讀(當前讀)
    • 鎖算法
    • 死鎖
    • 鎖升級


lock與latch

在了解數據庫鎖之前,首先就要區分開locklatch。在數據庫中,lock和latch雖然都是鎖,卻有著截然不同的含義。

latch通常被我們稱為閂鎖(輕量級鎖),因為其要求鎖定的時間必須非常短。在InnoDB中,latch可以分為mutex(互斥鎖)和rwlock(讀寫鎖),它的作用是用來保證并發線程操作臨界資源的正確性,并且通常沒有死鎖檢測機制。

lock的操作對象則是事務,用來鎖定數據庫中的對象,如表、頁、行等,并且一半lock的對象僅在事務提交或者回滾后釋放,并且lock有死鎖檢測機制,本篇博客介紹的也主要是lock,下面是lock和latch的區別。


鎖的類型

在InnoDB存儲引擎中實現了下面兩種標準的行級鎖

  • 共享鎖(S Lock) :允許事務讀一行數據
  • 排他鎖(X Lock) :允許事務刪除或者更新一行數據。

由于共享鎖并不涉及到數據的修改,所以即使一個事務已經獲得了行1的共享鎖,另外的事務也可以立即獲得行1的共享鎖,這種情況又被稱為鎖兼容。

對于排他鎖又是另一種情況,由于排他鎖涉及到了數據的修改,為了保證安全,其他的事務想要獲得同一行的排他鎖時,必須要等到前一個事務釋放鎖才行,這種情況又被稱為鎖不兼容

下面是排他鎖和共享鎖的兼容性。

由于InnoDB支持多粒度鎖定,所以允許事務可以同時存在行鎖和表鎖,為了支持在不同粒度上進行加鎖操作,InnoDB支持一種額外的鎖方式,即意向鎖(Intention Lock)。意向鎖即將鎖定的對象分為多個層次,意味著希望事務在更細粒度上進行加鎖,如下圖。

如果我們想對下層的對象如記錄上一個X鎖,就需要先對粒度更粗的上層對象上鎖,需要分別先對數據庫、表、頁上IX鎖,再對記錄上X鎖。(防止我們對一行上了讀鎖之后,某個事務申請了一個表級的寫鎖,此時這個事務就會對我們上鎖的數據進行修改,導致出現問題

InnoDB支持意向鎖設計比較簡練,其意向鎖即為表級別的鎖,設計目錄主要是為了在一個事務中揭示下一行將被請求的鎖的類型,兩種意向鎖分別如下

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

由于InnoDB支持的是行級別的鎖,因此意向鎖不會阻塞除全表掃描外的任何請求,故兼容性如下。


MVCC

MVCC(Multi-Version Concurrency Control)即多版本并發控制,是數據庫并發控制的一種方法

一致性非鎖定讀(快照讀)

一致性非鎖定讀又叫做快照讀,如果我們讀取的行正在執行DELETE或者UPDATE操作,這時就不會去等待鎖釋放后再讀取,而是直接去讀取行的一個快照數據,如下圖所示

快照數據指的是該行之前版本的數據,這些數據存儲在undo段中,由于undo用來在事務中回滾數據,因此這些快照數據本身并沒有額外的開銷。并且我們只是讀操作,并不涉及修改,而且也沒有事務會去對歷史數據進行修改,所以在讀取快照數據的時候不需要進行加鎖。

因為讀取操作不再占用和等待表上的鎖,所以快照讀的機制極大的提高了數據庫的性能。由于每個快照都相當于是一個歷史版本,所以這種對于行的多版本技術帶來的并發控制,就是MVCC名字的由來。

需要注意的是,MVCC只在READ COMMITTED(讀已提交) 和 REPEATABLE READ(可重復讀)兩個隔離級別下工作。由于READ UNCOMMITTED(讀未提交)總會讀取在最新的數據,而SERIALIZABLE(可串行化)會對所有讀取的行加鎖,所以這兩種都不兼容MVCC

一致性鎖定讀(當前讀)

一致性鎖定讀又稱為當前讀,它與快照讀剛好相反,它讀取的是行的最新版本,并且讀取的時候為了防止其他事務不會修改當前行,還會對當前行進行加鎖。

在InnoDB中,對于SELECT語句支持以下兩種一致性鎖定讀操作

  • SELECT…FOR UPDATE(排他鎖)
  • SELECT…LOCK IN SHARE MODE(共享鎖)

SELECT…FOR UPDATE會對讀取的行加一個排他鎖,此時其他事務不能對該行上任何鎖。

SELECT…LOCK IN SHARE MODE會位讀取的行加上一個共享鎖,此時其余的事務可以對該行加上共享鎖,但是如果相加排他鎖,則會被阻塞。


鎖算法

在InnoDB中由三種行鎖的算法

  • Record Lock(記錄鎖):單個行記錄上的鎖
  • Gap Lock(間隙鎖) : 鎖定一個范圍,但不包含記錄本身
  • Next-Key Lock(下一鍵鎖) :前兩種鎖的結合,既鎖定一個范圍,也鎖定記錄本身

為了更好的理解他們的區別,我拿一組數據來進行舉例

有一組數據,其索引分別為10、30、60
此時使用SQL語句SELECT * FROM t WHERE id = 10 FOR UPDATE,三種鎖的范圍如下

  • Record: 對10單行進行加鎖
  • Gap Lock : (-∞, 10)、(10, 30)、(30, 60)、(60, +∞)
  • Next-Key Lock : (-∞,10]、(10,30]、(30,60]、(60,+∞)

對于Record Lockl來說,其總是會去鎖住索引記錄,即使沒有設置任何一個索引,它也會使用隱式的索引進行鎖定。

Next-Key Lock是結合了前面所說的兩種鎖算法,既鎖住范圍,也鎖住記錄本身,在InnoDB中對于行的查詢都會采用這種算法,而設計它的目的正是為了解決幻讀問題。

在上一篇博客中也說了,幻讀指在同一事務中,用同樣的操作讀取兩次,得到的記錄數卻不一樣。(針對同一個范圍的數據)。 主要原因就是當第一個事務對表中的數據進行修改,并且這個涉及到表中的全部數據行。同時,第二個事務也修改這個表中的數據,向其中插入了一行。這樣也就導致了操作第一個事務的用戶發現表中還有沒修改的數據行,像發生了幻覺一樣。

明明在會話A的第一次查詢中,大于2的數只有行只有一列,而由于會話B插入了新列后,對于會話A而言就憑空多出來了一列,像出現了幻覺一樣。

對于以上數據,Next-Key Locking算法在SELECT * FROM t WHERE a > 2 FOR UPDATE這條語句中,鎖住的不僅僅是5這個數值,而是對直接對(2,+∞)這個范圍加了排他鎖,所以任何對于這個范圍的插入都不能進行,也就避免了幻讀現象的發生。

同理,間隙鎖Gap Lock也是鎖定某個范圍,所以它也能防止幻讀的出現。

InnoDB正是借助鎖(Gap Lock、Next-Key Lock)以及MVCC(快照讀)這兩個機制實現了事務的隔離性


死鎖

死鎖指的是兩個或者兩個以上的事務在執行過程中,因為爭搶所資源而導致的一種互相等待的現象。在死鎖的情況下,如果沒有外力作用,事務將永遠無法推進下去。

在數據庫中通常都會使用超時機制來解決死鎖。即為事務設置超時時間,即使兩個事務互相等待,當其中一方超時后立刻進行回滾,另一個事務就能夠繼續進行了。

雖然超時機制可以解決這個問題,但是我們并不能掌握回滾的事務的量級,倘若事務更新龐大,則回滾就會帶來大量的性能損耗,所以我們通常會采用更加主動的策略,即使用等待圖來進行死鎖檢測,如下圖。

  • 圖中每個節點即為一個事務
  • 每條指向其他節點的線則代表著正在等待該節點的資源
  • 當存在回路時,則代表著事務互相等待,此時就意味著存在死鎖

每當事務請求鎖并發生等待時,都會主動判斷等待圖中是否存在回路,如果存在則代表著有死鎖產生,此時就會主動選擇undo量最小的事務來打破死鎖。在現版本的InnoDB中,通常采用深度優先搜索(老版本使用遞歸)來檢測死鎖的存在。


鎖升級

在數據庫為了保證安全,大量的并發下必定存在著大量的鎖,由于鎖是一種稀有資源,為了避免大量鎖的開銷,數據庫中存在著鎖升級的機制。

鎖升級指的是將當前的鎖升級為更粗粒度的鎖,例如我們可以將多個行鎖升級為一個頁鎖,又或者將多個頁鎖升級為一個表鎖。這種升級保護了系統資源,防止系統使用太多內存來維護大量的鎖,在一定程度上提高了效率。

在SQL Server中,鎖升級是很常見的現象,當滿足以下條件中其中一個時則會進行鎖升級

  • 鎖資源占用的內存超過了激活內存的40%
  • 由一條單獨的SQL語句在一個對象上持有的鎖數量超過了閾值,閾值默認為5000

而在MySQL的InnoDB中,則不存在鎖升級的問題。其根據每個事務訪問的每個頁對鎖進行管理,并且使用位圖來標記,所以一個事務無論鎖住頁中多少條記錄,開銷都相同

總結

以上是生活随笔為你收集整理的MySQL 锁与MVCC :数据库的锁、MVCC、当前读、快照读、锁算法、死锁的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。