目錄
第一章 資料庫基礎知識
文章目錄
- 目錄
- 前言
- 資料庫事務
- 一、定義
- 二、要求
- 三、影響
- 四、特性(ACID)
- (1)A:原子性 Atomicity
- (2)C:一致性 Consistency
- (3)I:隔離性 Isolation
- 事務的隔離級別及解決方案
- 1.未提交讀
- 2.已提交讀
- 3.可重復讀
- 4.可串行化
- 總結
- (4)D:永久性 Durability
- 愿你享受溫暖感受愛,sincerely,end.
前言
??認為自己大學時學得不夠深入,發現實際作業中需要用到它的地方很多,因此記下此文幫助自己梳理知識,也希望可以給需要的你提供幫助,自學之路,如有錯誤,請糾正,萬分感謝!
來自筆者內心理解(以及結合相關文獻 綜合思考后)的正文:
資料庫事務
一、定義
??資料庫事務是一個不可分割的作業單位,由事務開始與事務結束之間執行的全部資料庫操作構成,這些操作要么全部執行,要么全部不執行,
二、要求
??一個資料庫事務可以包含多個查詢、修改、洗掉、插入等資料庫動作,它們要么作為一個整體完全得到確認,要么完全失敗;一個事務只能包含對一個資料庫實體的資料操作,跨多個資料庫實體需要分布式事務的支持,
三、影響
??資料庫事務會給資料庫并發操作帶來一定影響,降低系統的并發能力,
四、特性(ACID)
(1)A:原子性 Atomicity
??一個原子事務中的所有操作要么全部成功,要么全部失敗,即整個事務中的每項任務都必須正確執行,如有任一任務執行失敗,則整個事務就會被終止,此前對資料所作的任何修改都將被撤銷(回滾);如果每項任務都執行成功,事務則會被提交,是資料庫系統區別于其他一切檔案系統的重要特性之一(檔案系統出錯不可恢復),
看個小例子吧~
??假如我們需要進行轉賬服務,以下表格中的每一步都需要保證全部正確,否則需要回滾到初始狀態
| First | 檢查活期存款余額是否高于轉賬金額 |
|---|---|
| Second | 活期存款余額 減去 轉賬金額 |
| Third | 轉賬賬戶余額 加上 轉賬金額 |
(2)C:一致性 Consistency
??資料庫總是從一個一致性的狀態轉換到另一個一致性的狀態,
承接上個小例子~
??我們的轉賬服務中轉出賬戶的扣除金額與轉入賬戶的轉入金額必須保持一致,
| Q: | 誰來保證? |
|---|---|
| A: | 事務系統 & 應用開發人員 |
| Q: | 如何保證? |
| A: | 事務系統:保證事務的原子性、隔離性和持久性 應用開發人員:保證資料庫有適當的約束,并且事務中所實作的業務邏輯要與預期現實業務情況完全一致 |
(3)I:隔離性 Isolation
??針對并發事務而言,事務必須在不干擾其他行程或事務的前提下獨立執行,(有級別設定)即要隔離并發運行的多個事務之間的影響,
寫在前面的兩個關鍵:共享鎖和排他鎖,是實作隔離級別的兩種鎖模式,都為悲觀鎖①,
共享鎖 [S鎖_shared lock]:
?是一種讀鎖,
?當事務A對資料物件B加S鎖時,事務A可以讀B但不能修改B,其他事務也能對B加S鎖,但不能加X鎖,直到A釋放B上的S鎖,
?這保證了其他事務在A釋放B上的S鎖之前對B可讀,但不可寫,
排他鎖 [X鎖_exclusive lock]:
?是一種寫鎖,
?當事務A對臨界區B加X鎖時,事務A可以讀寫B,但其他事務不能對B加任何鎖(共享鎖,排他鎖),直到A釋放B上的X鎖,
?這保證了其他事務在A釋放B上的X鎖之前不能對B進行讀寫,
總結:
?共享鎖保證大家可以一起做只讀操作(e.g. select),不可以有人再寫入;
?排他鎖保證只能一個人去處理資料(用于資料修改,e.g. insert、update、delete),其他人不能讀寫,
?X鎖比S鎖有更高的優先級,一個X鎖請求可能會被插入到S鎖佇列的前面,但S鎖不能插入到X鎖前面,
注釋(可跳過):實作并發控制的主要手段大致可以分為樂觀并發控制和悲觀并發控制兩種,
①悲觀鎖:
??在操作資料時,認為此操作會出現資料沖突,所以在每次操作都需通過獲取鎖才能進行,
??方法 由資料庫自己實作,用的時候,直接呼叫資料庫相關陳述句就可以,
??場景 適用于沖突頻率高、重試代價大的場景,為資料處理的安全提供了保證,
??缺點 會降低并行性,需耗費較多的時間,增加產生死鎖的機會,
?樂觀鎖:
??在操作資料時,不認為此操作會出現資料沖突(不加鎖),在操作結束后再判斷是否有沖突,
??方法 需要我們自己實作,可以使用版本號等機制,資料庫不自帶,
??場景 適用于讀操作多、回應效率高的場景,可以提高程式的吞吐量,
??缺點 鎖的粒度如果掌握不好,更新失敗的概率會比較高,
事務的隔離級別及解決方案
| 事務隔離級別 | 臟讀 ② | 不可重復讀③ | 幻讀④ |
|---|---|---|---|
| 未提交讀[Read Uncommitted] | 允許 | 允許 | 允許 |
| 已提交讀[Read Committed] | 禁止 | 允許 | 允許 |
| 可重復讀[Repeatable Read] | 禁止 | 禁止 | 允許 |
| 可串行化[Serializable] | 禁止 | 禁止 | 禁止 |
上表中,在相同運行環境下,不同隔離級別的順序按照并發性由高到低,隔離性由低到高排序,
注釋(也許看完注釋之后依舊云里霧里,that’s OK,我們還有小例子在后面):
??②臟讀:事務A讀取到了事務B沒有提交的資料
??③不可重復讀:在事務A中,兩次讀取同一資料,得到的內容不同
??④幻讀:在事務A中,相同操作讀取兩次,得到的記錄數不同
由下列例子幫助我們更好的理解事務的隔離級別:
1.未提交讀
??加鎖機制:在寫事務時加行級共享鎖,讀事務時不加鎖
??例子:事務A修改了一條記錄的內容,但是并沒有提交(commit),在隔離級別為未提交讀的情況下,事務B可以讀取到A修改后并未提交的記錄內容,(由于是共享鎖,寫事務未提交前其他事務仍然能讀)
??有何影響呢?一旦A執行回滾操作(沒有commit之前都是可以回滾的),B之前所讀取的記錄內容則為臟資料,這就造成了臟讀,[不僅臟讀無法避免,不可重復讀(下面2.已提交讀中介紹)、幻讀(下面3.可重復讀中介紹)也無法避免]
2.已提交讀
??是如何避免臟讀的呢?加鎖機制:寫事務時加行級排他鎖,事務結束才釋放;讀事務時加行級共享鎖,讀完立即釋放鎖(不等到整個事務結束后才釋放),(確保寫一行時其他事務無法讀寫此行,只有commit以后才可讀寫,讀一行時其他事務只能讀,無法寫這一行)
??例子:事務A查詢一條記錄后,并沒有結束事務A,在隔離級別為已提交讀的情況下,接著事務B修改了A剛才查詢的那條記錄(既然是已提交讀,那B修改內容后需要commit),
??有何影響呢?當A又再次查詢這條記錄時,發現與之前查詢的記錄不同(因為事務A沒結束的時候B修改了內容,導致事務A兩次讀取不一致),前后查詢的記錄不一就造成了不可重復讀,[不僅不可重復讀無法避免,幻讀(下面3.可重復讀中介紹)也無法避免]
3.可重復讀
??是如何避免不可重復讀的呢?加鎖機制:寫事務時加行級排他鎖,讀事務時加行級共享鎖,都持續到事務結束才釋放,(確保整個事務中寫就是寫,讀就是讀,整個事務讀完之后才可以寫)
??例子:事務A根據條件查詢一組記錄,之后事務B在A查詢條件的記錄范圍內插入一條記錄,
??有何影響呢?當A又使用相同的方式再次對表進行檢索時,卻發現了一條新紀錄,這個新記錄對A來說就像突然出現的一樣,這就造成了幻讀,(讀寫事務只是加了行級鎖,其他事務雖然不能修改這些行,但是能添加新行,因此出現幻讀現象)
4.可串行化
??是如何避免幻讀的呢?加鎖機制:讀事務時加表級共享鎖,寫事務時加表級排他鎖,(避免其他事務對該表的操作)
總結
| 事務隔離級別 | 總結 | 資料庫默認隔離級別 |
|---|---|---|
| 未提交讀[Read Uncommitted] | 事務A中的修改,即使沒有提交,其他事務也可以看得到 | |
| 已提交讀[Read Committed] | 事務A中的修改只有提交以后才能被其它事務看到 有可能發生不可重復讀和幻讀 | SQLServer , Oracle |
| 可重復讀[Repeatable Read] | 事務A中看到的每條記錄的結果一致 有可能發生幻讀 | MySQL |
| 可串行化[Serializable] | 嚴格要求資料的一致性 靠大量加鎖實作,導致大量的鎖超時和鎖征用問題,效率低下 |
(4)D:永久性 Durability
??一旦事務提交成功,它對于資料的修改就會永久保存到資料庫中,此時即使系統崩潰,修改的資料也不會丟失(磁盤損壞不包括,需要靠備份等),
愿你享受溫暖感受愛,sincerely,end.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/197021.html
標籤:java
