spring學習筆記---數據庫事務並發與鎖詳解


多事務運行並發問題

在實際應用中,往往是一台(或多台)服務器向無數客戶程序提供服務,當服務器查詢數據庫獲取數據時,如果沒有采用必要的隔離機制,可能會存在數據庫事務的並發問題,下面是一些常見的並發問題分類:

1. 第一類丟失更新:撤銷一個事務,其他事務已提交的更新數據覆蓋
2. 第二類丟失更新:一個事務覆蓋另一個事務已提交的更新數據
3. 臟讀:一個事務讀到另一個事務未提交的數據
4. 虛讀:一個事物讀到另一個已提交的新插入數據 
5. 不可重復讀:事務讀到另一個事務已提交的更新數據

下面對這幾類並發問題進行詳細介紹:

1. 第一類丟失更新

產生過程:兩個事務更新同一數據,第一個事務被提交,第一個事務被撤銷,會把第一個事務所做的更新也撤銷,示意圖如下所示: 
這里寫圖片描述

2. 第二類丟失更新

產生過程:兩個事務各自基於最初的查詢結果提交數據,實例流程如下圖所示: 
這里寫圖片描述

3. 臟讀

產生過程:事務二查詢到事務一未提交數據,事務二根據此數據進行操作,事務一緊接着撤銷數據,導致事務二操縱的是“臟數據”,實例流程如下圖所示: 
這里寫圖片描述

4.虛讀(幻象讀)

產生過程:對某行執行插入或刪除操作,而該行屬於某個事務正在讀取的行的范圍。若對數據精度要求不高,則影響不大,實例流程如下圖所示: 
這里寫圖片描述

5.不可重復讀

產生過程:一個事務查詢到另一事務已提交的對數據的更新,實例流程如下圖所示: 
這里寫圖片描述 
與臟讀區別:臟讀->讀取前一事務未提交的臟數據,不可重復讀->重新讀取了前一事務已提交的數據

數據庫系統鎖的基本原理

1. 鎖的多粒度及自動升級:

  1. 鎖的多粒度按類型可分成下面幾類: 
    • 數據庫級鎖
    • 表級鎖
    • 區域級鎖
    • 頁面級鎖
    • 鍵值級鎖:鎖定數據庫表中帶有索引的一行數據
    • 行級鎖
  2. 對數據的封鎖力度越大,往往隔離性越高,但並發性能變差。
  3. 對數據施行的鎖粒度越高,並發性往往越大,但這意味着在大並發量時鎖的數量的急劇增多,由此會帶來系統資源的嚴重負載,影響系統系統。常用的數據庫都有事務鎖自動升級功能,當系統性能因為鎖數量過大而急劇變差時,往往會升級使用更粗粒度的鎖來擴大封鎖面,減少鎖數優化系統資源。

2. 鎖的類型和兼容性:

  1. 共享鎖

    • 加鎖條件:讀取數據
    • 解鎖條件:讀取完畢
    • 兼容性:放置了共享鎖的資源,能再放置共享鎖和獨占鎖
    • 並發性:多事務訪問相同數據,多鎖同時讀
  2. 獨占鎖(排它鎖)

    • 加鎖條件:修改數據且無其他鎖存在
    • 解鎖條件:事務結束
    • 兼容性:不與其他鎖兼容
  3. 更新鎖

    • 加鎖條件:update操作
    • 加鎖更新步驟: 
      1. 獲得一個共享鎖,讀數據
      2. 升級為獨占鎖,更新數據
    • 兼容性:與共享鎖兼容,同一資源最多一把更新鎖,能有效避免死鎖產生,我們知道,共享鎖的兼容性是最好的,加入一個數據同時被兩把共享鎖鎖住,如果這時兩條線程並發修改數據,由於共享鎖的非排他性,可能會同時出現兩把獨占鎖鎖住數據,這樣就會產生死鎖了,而更新鎖排斥獨占鎖,當出現更新操作時,只能將更新鎖本身升級為獨占鎖,而有效避免死鎖產生。
    • 並發性:性能一般,多事務訪問,單事務修改。 
      -

3. 死鎖產生及其解決方法:

  1. 產生過程:多事務鎖定一個資源->試圖去鎖定對方已鎖定的資源->多事務處於等待對方釋放鎖資源狀態,示意圖如下所示: 
    這里寫圖片描述
  2. 防止方法 
    1. 合理安排表訪問順序
    2. 對事務要求不高,允許臟讀(不加鎖)
    3. 錯開多事務訪問相同資源的時間
    4. 使用盡可能低的事務隔離級別
    5. 使用短事務(操作盡可能少,時間盡可能短)
    6. 將大事務分解成多個小事務順序執行

4. 悲觀鎖與悲觀鎖

  1. 悲觀鎖:顯式為數據加鎖,常見有如下兩種加鎖方式 
    1. 顯式指定獨占鎖:select … for update
    2. 在數據庫增加表明狀態的LOCK字段
  2. 樂觀鎖:通過版本控制實現,示意圖如下所示: 
    這里寫圖片描述 
    通過樂觀鎖的版本控制,我們能夠更好地提高並發事務的性能。

3. 數據庫的事務隔離級別

4種隔離級別從高到低依次為: 
- Serializable:串行化 
- Repeatable Read: 可重復讀 
- Read Commited:讀已提交的數據 
- Read UnCommited:讀未提交的數據

它們對並發事務問題的支持如下圖所示 
這里寫圖片描述

4. spring的事務傳播行為

事務傳播行為類型 說明
PROPAGATION_REQUIRED 如果當前沒有事務,就新建一個,如果已經存在,則加入到事務中這是最常見的選擇。
PROPAGATION_SUPPORTS 表示事務對當前方法可有可無,如果有,則按該事務執行,如果當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY 表示當前方法必須在一個事務中執行,而且如果當前沒有事務,就拋出異常。
PROPAGATION_REQUIRES_NEW 表示當前方法總是需要獨立的新事務,如果當前已存在事務,就會把當前事務掛起,直到新的事務提交或者回滾才恢復執行
PROPAGATION_NOT_SUPPORTED 表示當前方法不需要事務,如果當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER 表示當前方法不需要事務,而且如果當前存在事務,則拋出異常。
PROPAGATION_NESTED 如果當前存在事務,則在嵌套事務內執行,如果嵌套事務存在,並且外層事務拋出異常回滾,那么內層事務必須回滾,反之,內層事務並不影響外層事務


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM