(十四)并發控制

??之前在(十三)事務處理中簡單的介紹了鎖系統,并且介紹了由于并發而產生的種種問題,例如臟讀、幻讀等,因此這里對如何解決這些問題再進行一下補充。


1、悲觀鎖

??在關系型數據庫管理系統里,悲觀并發控制是一種并發控制的方法,它可以阻止一個事務以影響其他事務的方式來修改數據。悲觀鎖需要使用數據庫的鎖機制,可以從字面理解為這種并發方式就是很悲觀,每次調用數據的時候都認為同時會有其他事務在修改數據,因此每次在調用數據前都會先上鎖,這樣可以防止其他事務讀取或修改表中的數據。

??例如:



??此處之所以會出現死鎖,就是因為執行這條語句時已經使用了鎖,

UPDATE tbl_name SET col_name = newValue WHERE id = x;

??因此互相調用相同的字段造成了死鎖。

??悲觀并發控制主要用于數據爭用激烈的環境,以及發生并發沖突時使用鎖保護數據的成本要低于回滾事務的成本的環境中。悲觀并發控制實際上是”先取鎖再訪問”的保守策略,為數據處理的安全提供了保證。但是在效率方面,處理加鎖的機制會讓數據庫產生額外的開銷,并且會增加產生死鎖的機會;另外,在只讀型事務處理中由于不會產生沖突,也沒必要使用鎖,這樣做只能增加系統負載,還會降低并行性,因為一個事務如果鎖定了某行數據,其他事務就必須等待該事務處理完才可以進行處理。


2、樂觀鎖

??樂觀鎖相對于悲觀鎖而言,通常會假設多用戶并發的事務在處理時不會彼此互相影響,各事務能夠在不產生鎖的情況下處理各自負責的數據。在提交數據更新之前,每個事務會先檢查在讀取數據后,有無其他事務再次修改了該數據。如果有,那么當前正在提交的事務會進行回滾。可以從字面理解為這種并發方式就是很樂觀,每次調用數據的時候都認為其他事務不會在同時修改數據,因此不會上鎖。

??在處理數據時,樂觀鎖并不會使用數據庫提供的鎖機制,通常樂觀鎖的實現方式是記錄數據版本,即為數據增加一個版本標識,一般是通過為數據庫表增加一個數字類型的 “version” 字段來實現。當讀取數據時,將version字段的值一同讀出,數據每更新一次,對此version值加1。當提交更新的時候,判斷當前version值是否與之前讀出的version值一致,如果相同,則予以更新,否則認為是過期數據。

??例如:
??假設用戶A和用戶B對同一張數據表的同一個字段記錄值進行修改,此時用戶A和用戶B從該表中讀取的version值為2,用戶A對記錄修改結束后,version值增加1,此時該表的version字段的值是3,而用戶B依然按照version值為2進行操作,不滿足“提交版本必須大于記錄當前版本才能執行更新”的樂觀鎖策略,因此,用戶B的提交被駁回。這樣,就避免了用戶B用基于version值為2的舊數據修改的結果覆蓋用戶A的操作結果的可能。

??樂觀并發控制多數用于數據爭用不大、沖突較少的環境中,此時偶爾回滾事務的成本會低于讀取數據時鎖定數據的成本,因此可以獲得比其他并發控制方法更高的吞吐量。


3、MVCC

??多版本并發控制(Multi-Version Concurrency Control)是為了實現數據庫的并發控制而設計的一種機制。大多數的關系型數據庫都支持MVCC,其突出特點是:讀不加鎖,讀寫不沖突。

??在MVCC中,讀操作可以分成兩類,快照讀和當前讀:

  • 快照讀,讀取的是記錄的可見版本(可能是歷史版本,即最新的數據可能正在被當前執行的事務并發修改),不會對返回的記錄加鎖;
  • 當前讀,讀取的是記錄的最新版本,并且會對返回的記錄加鎖,保證其他事務不會并發修改這條記錄。

??在MySQL InnoDB中,基本的SELECT操作,如

SELECT * FROM tbl_name WHERE xxxx;

??都屬于快照讀;而屬于當前讀的包含以下操作:

SELECT * FROM tbl_name WHERE xxxx LOCK IN SHARE MODE;(共享鎖)
SELECT * FROM tbl_name WHERE xxxx FOR UPDATE;(排他鎖)
INSERT,UPDATE,DELETE操作(排他鎖)

??可以將MVCC理解為行級鎖的一種妥協,它在許多情況下避免了使用鎖,同時可以提供更小的開銷。根據實現的不同,它可以允許非阻塞式讀,在寫操作進行時只鎖定必要的記錄。

??各個存儲引擎對于MVCC的實現各不相同,下面將通過一個簡化的InnoDB版本的行為來展示MVCC工作原理:
簡單來說,通過為每一行記錄添加兩個額外的隱藏的值來實現MVCC,這兩個值一個記錄這行數據何時被創建,另外一個記錄這行數據何時過期(或者被刪除)。但是InnoDB并不存儲這些事件發生時的實際時間,相反它只存儲這些事件發生時的系統版本號。這是一個隨著事務的創建而不斷增長的數字。每個事務在事務開始時會記錄它自己的系統版本號。每個查詢必須去檢查每行數據的版本號與事務的版本號是否相同。

??以下是在默認隔離級別REPEATABLE READ下,MVCC具體是怎樣實現的:

  • SELECT:
    ??InnoDB只查找版本早于(包含等于)當前事務版本的數據行。這保證了不管是事務開始之前,或者事務創建時,或者修改了這行數據的時候,這行數據是存在的;這行數據的刪除版本必須是未定義的或者比事務版本要大,這可以保證在事務開始之前這行數據沒有被刪除。
    ??符合這兩個條件的行可能會被當作查詢結果而返回。

  • INSERT:
    InnoDB為這個新行記錄當前的系統版本號。

  • DELETE:
    InnoDB將當前的系統版本號設置為這一行的刪除ID。

  • UPDATE:
    InnoDB會寫一個這行數據的新拷貝,這個拷貝的版本為當前的系統版本號。它同時也會將這個版本號寫到舊行的刪除版本里。


4、MVCC與樂觀鎖的區別

??在了解了MVCC的實現機制后可能會感覺與樂觀鎖中使用版本號加鎖有相似之處,實際上MVCC可以保證不阻塞地讀到一致的數據。但是,MVCC并沒有對實現細節做約束,在InnoDB引擎下是只對讀無鎖,寫操作仍是上鎖的悲觀并發控制,這也意味著,InnoDB中只能見到因死鎖和不變性約束而回滾,而不會出現因為寫沖突而回滾的現象;MVCC對數據表中的每行數據只保留一份,在更新數據時上行級鎖,同時將舊版數據寫入undo log;數據表和undo log中行數據都記錄著事務ID,在檢索時,只讀取來自當前已提交的事務的行數據。這種額外的記錄所帶來的結果就是對于大多數查詢來說根本就不需要獲得一個鎖。MVCC只是簡單地以最快的速度來讀取數據,確保只選擇符合條件的行。但其缺點也正是存儲引擎必須為每一行存儲更多的數據,做更多的檢查工作,處理更多的善后操作。


版權聲明:歡迎轉載,歡迎擴散,但轉載時請標明作者以及原文出處,謝謝合作!             ↓↓↓
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,024評論 3 413
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,285評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,548評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,328評論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,878評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,098評論 0 286
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,616評論 1 331
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,554評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,725評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 43,971評論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,361評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,613評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,339評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,695評論 2 370

推薦閱讀更多精彩內容