spring學習筆記(20)資料庫事務併發與鎖詳解
多事務執行併發問題
在實際應用中,往往是一臺(或多臺)伺服器向無數客戶程式提供服務,當伺服器查詢資料庫獲取資料時,如果沒有采用必要的隔離機制,可能會存在資料庫事務的併發問題,下面是一些常見的併發問題分類:
1. 第一類丟失更新:撤銷一個事務,其他事務已提交的更新資料覆蓋
2. 第二類丟失更新:一個事務覆蓋另一個事務已提交的更新資料
3. 髒讀:一個事務讀到另一個事務未提交的資料
4. 虛讀:一個事物讀到另一個已提交的新插入資料
5. 不可重複讀:事務讀到另一個事務已提交的更新資料
下面對這幾類併發問題進行詳細介紹:
1. 第一類丟失更新
產生過程:兩個事務更新同一資料,第一個事務被提交,第一個事務被撤銷,會把第一個事務所做的更新也撤銷,示意圖如下所示:
2. 第二類丟失更新
產生過程:兩個事務各自基於最初的查詢結果提交資料,例項流程如下圖所示:
3. 髒讀
產生過程:事務二查詢到事務一未提交資料,事務二根據此資料進行操作,事務一緊接著撤銷資料,導致事務二操縱的是“髒資料”,例項流程如下圖所示:
4.虛讀(幻象讀)
產生過程:對某行執行插入或刪除操作,而該行屬於某個事務正在讀取的行的範圍。若對資料精度要求不高,則影響不大,例項流程如下圖所示:
5.不可重複讀
產生過程:一個事務查詢到另一事務已提交的對資料的更新,例項流程如下圖所示:
與髒讀區別:髒讀->讀取前一事務未提交的髒資料,不可重複讀->重新讀取了前一事務已提交的資料
資料庫系統鎖的基本原理
1. 鎖的多粒度及自動升級:
- 鎖的多粒度按型別可分成下面幾類:
- 資料庫級鎖
- 表級鎖
- 區域級鎖
- 頁面級鎖
- 鍵值級鎖:鎖定資料庫表中帶有索引的一行資料
- 行級鎖
- 對資料的封鎖力度越大,往往隔離性越高,但併發效能變差。
- 對資料施行的鎖粒度越高,併發性往往越大,但這意味著在大併發量時鎖的數量的急劇增多,由此會帶來系統資源的嚴重負載,影響系統系統。常用的資料庫都有事務鎖自動升級功能,當系統效能因為鎖數量過大而急劇變差時,往往會升級使用更粗粒度的鎖來擴大封鎖面,減少鎖數優化系統資源。
2. 鎖的型別和相容性:
-
共享鎖
- 加鎖條件:讀取資料
- 解鎖條件:讀取完畢
- 相容性:放置了共享鎖的資源,能再放置共享鎖和獨佔鎖
- 併發性:多事務訪問相同資料,多鎖同時讀
-
獨佔鎖(排它鎖)
- 加鎖條件:修改資料且無其他鎖存在
- 解鎖條件:事務結束
- 相容性:不與其他鎖相容
-
更新鎖
- 加鎖條件:update操作
- 加鎖更新步驟:
- 獲得一個共享鎖,讀資料
- 升級為獨佔鎖,更新資料
- 相容性:與共享鎖相容,同一資源最多一把更新鎖,能有效避免死鎖產生,我們知道,共享鎖的相容性是最好的,加入一個資料同時被兩把共享鎖鎖住,如果這時兩條執行緒併發修改資料,由於共享鎖的非排他性,可能會同時出現兩把獨佔鎖鎖住資料,這樣就會產生死鎖了,而更新鎖排斥獨佔鎖,當出現更新操作時,只能將更新鎖本身升級為獨佔鎖,而有效避免死鎖產生。
- 併發性:效能一般,多事務訪問,單事務修改。
-
3. 死鎖產生及其解決方法:
- 產生過程:多事務鎖定一個資源->試圖去鎖定對方已鎖定的資源->多事務處於等待對方釋放鎖資源狀態,示意圖如下所示:
- 防止方法
- 合理安排表訪問順序
- 對事務要求不高,允許髒讀(不加鎖)
- 錯開多事務訪問相同資源的時間
- 使用盡可能低的事務隔離級別
- 使用短事務(操作儘可能少,時間儘可能短)
- 將大事務分解成多個小事務順序執行
4. 悲觀鎖與悲觀鎖
- 悲觀鎖:顯式為資料加鎖,常見有如下兩種加鎖方式
- 顯式指定獨佔鎖:select … for update
- 在資料庫增加表明狀態的LOCK欄位
- 樂觀鎖:通過版本控制實現,示意圖如下所示:
通過樂觀鎖的版本控制,我們能夠更好地提高併發事務的效能。
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 | 如果當前存在事務,則在巢狀事務內執行,如果巢狀事務存在,並且外層事務丟擲異常回滾,那麼內層事務必須回滾,反之,內層事務並不影響外層事務 |
相關文章
- 關係型資料庫中的事務管理詳解:併發控制與事務日誌資料庫
- MySQL資料庫學習筆記02(事務控制,資料查詢)MySql資料庫筆記
- 重新學習MySQL資料庫6:淺談MySQL的中事務與鎖MySql資料庫
- Spring學習筆記 - 第三章 - AOP與Spring事務Spring筆記
- MySQL(一):MySQL資料庫事務與鎖MySql資料庫
- 資料庫學習筆記:事務的特性和隔離級別資料庫筆記
- 資料庫併發控制幾隻——事務資料庫
- Spring學習筆記3(JDBC模板&事務管理)Spring筆記JDBC
- Spring 事務學習筆記(一) 初遇篇Spring筆記
- MySQL 筆記 - 事務&鎖MySql筆記
- 資料庫學習筆記資料庫筆記
- 深入理解 MySQL—鎖、事務與併發控制MySql
- 深入理解Mysql——鎖、事務與併發控制MySql
- Spring筆記(4) - Spring的程式設計式事務和宣告式事務詳解Spring筆記程式設計
- MySQL詳解--鎖,事務MySql
- MySQL學習筆記之資料型別詳解MySql筆記資料型別
- 資料庫學習筆記——20 使用遊標資料庫筆記
- Spring事務筆記Spring筆記
- 資料庫事務和MVCC多版本併發控制資料庫MVC
- MySQL資料庫學習筆記MySql資料庫筆記
- Spring 學習筆記(6)Spring和資料庫程式設計Spring筆記資料庫程式設計
- 《筆記》之學習高併發筆記
- JAVA 學習併發筆記(一)Java筆記
- (一)Java併發學習筆記Java筆記
- 《Python入門與資料科學庫》學習筆記Python資料科學筆記
- 資料庫mysql學習筆記記錄資料庫MySql筆記
- MySQL事務與併發MySql
- MySQL資料庫-鎖詳解MySql資料庫
- 資料庫學習筆記(四)2017.9.19資料庫筆記
- 資料庫學習與複習筆記--資料庫概念和不同類資料庫CRUD操作(1)資料庫筆記
- JUC併發程式設計學習筆記(四)8鎖現象程式設計筆記
- Redis學習筆記(七) 資料庫Redis筆記資料庫
- 達夢資料庫學習筆記資料庫筆記
- python學習筆記:資料庫Python筆記資料庫
- 資料庫原理學習筆記——引言資料庫筆記
- 資料庫事務與 MySQL 事務總結資料庫MySql
- 效能優化之資料庫篇2-事務與鎖優化資料庫
- MySQL優化系列(八)--鎖機制超詳細解析(鎖分類、事務併發、引擎併發控制)MySql優化