事務和鎖
事務的定義
簡而言之:事務(Transaction)是并發控制的基本單位。
- 所謂的事務,它是一個操作序列,這些操作要么都執行,要么都不執行,它是一個不可分割的工作單位。
事務的特點ACID
原子性(Atomicity):一個事務是一個不可分割的工作單位,事務中包括的諸操作要么都做,要么都不做。
一致性(Consistency):事務必須是使數據庫從一個一致性狀態變到另一個一致性狀態。一致性與原子性是密切相關的。
隔離性(Isolation):一個事務的執行不能被其他事務干擾。即一個事務內部的操作及使用的數據對并發的其他事務是隔離的,并發執行的各個事務之間不能互相干擾。
持久性(Durability):持久性也稱永久性(permanence),指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。接下來的其他操作或故障不應該對其有任何影響。
事務對應的語句
BEGINTRANSACTION開始事務
COMMITTRANSACTION提交事務
ROLLBACKTRANSACTION回滾事務
事務并發控制
事務不考慮隔離性引發的問題
臟讀:此種異常時因為一個事務讀取了另一個事務修改了但是未提交的數據,當修改的事務進行回滾操作時將造成讀取事務異常。
不可重復讀:在一個事務內讀取表中的某一行數據,多次讀取結果不同。(一個事務讀取到了另外一個事務提交的數據)
幻讀(虛讀):指在一個事務內讀取到了別的事務插入的數據,導致前后讀取不一致。例如讀整個表,即表的行數,例如第一次讀某個表有3條記錄,第二次讀該表又有4條記錄(和不可重復讀的不同:不可重復讀針對的是數據的值,幻讀針對的是數據的數量)
數據庫事務隔離級別(SQL標準定義)
READUNCOMMITTED(未提交讀):事務中的修改,即使沒有提交,其他事務也可以看得到。很容易導致臟讀等眾多問題,如無必要,很少使用
READCOMMITTED(提交讀):大多數數據庫系統默認的隔離級別(除Mysql等)。這種隔離級別就是一個事務的開始,只能看到已經完成的事務的結果,正在執行的,是無法被其他事務看到的。這種級別會出現讀取舊數據的現象,即不可重復讀的問題。
REPEATABLEREAD(可重復讀):解決了臟讀的問題,該級別保證了每行的記錄的結果是一致的,也就是上面說的讀了舊數據的問題,但是卻無法解決另一個問題,幻行,顧名思義就是突然蹦出來的行數據。指的就是某個事務在讀取某個范圍的數據,但是另一個事務又向這個范圍的數據去插入數據,導致多次讀取的時候,數據的行數不一致。即幻讀。–MYSQL默認隔離級別
SERIALIZABLE(可串行化):最高的隔離級別,它通過強制事務串行執行(注意是串行),避免了前面的幻讀情況,由于他大量加上鎖,導致大量的請求超時,因此性能會比較底下,在特別需要數據一致性且并發量不需要那么大的時候才可能考慮這個隔離級別
數據庫鎖
數據庫鎖的基本類型:
X鎖:exclusive用于寫操作
-某數據對象在沒有加任何鎖的情況下,一個事務可以對其加X鎖,而其他事務就不能對其再加任何鎖
S鎖:share用于讀操作
-一個事務對某數據對象加了S鎖后,其他事務就不能對其加X鎖,但可以加S鎖
U鎖:update
-事務要更新數據對象時,先申請該對象的U鎖。對象加了U鎖,允許其他事務對它加S鎖。在最后寫入時,再申請將U鎖升級為X鎖。不必在全過程中加X
不同級別的加鎖協議
一級封鎖協議(臟數據、不可重復讀)
任一事務在寫某數據前,必須對其加上X鎖,該事務結束后才釋放。不采用S鎖,讀數據不用加鎖。
事務結束包括正常結束(COMMIT)和非正常結束(ROLLBACK)。
二級封鎖協議(不可重復讀)
滿足一級封鎖協議,且任一事務在讀取某數據前,必須對其加上S鎖,讀完后就釋放
三級封鎖協議()
滿足一級封鎖協議,且任一事務在讀取某數據前,必須對其加上S鎖,事務結束后釋放鎖
其他加鎖協議
兩階段加鎖協議:
整個事務分為兩個階段,前一個階段為加鎖,后一個階段為解鎖。在加鎖階段,事務只能加鎖,也可以操作數據,但不能解鎖,直到事務釋放第一個鎖,就進入解鎖階段,此過程中事務只能解鎖,也可以操作數據,不能再加鎖。兩階段鎖協議使得事務具有較高的并發度,因為解鎖不必發生在事務結尾。它的不足是沒有解決死鎖的問題,因為它在加鎖階段沒有順序要求。如兩個事務分別申請了A,B鎖,接著又申請對方的鎖,此時進入死鎖狀態。
定理:若所有事務均遵守兩段鎖協議,則這些事務的所有交叉調度都是可串行化的。
多粒度加鎖協議
行級鎖:開銷大,加鎖慢;會出現死鎖;鎖定粒度最小,發生鎖沖突的概率最低,并發度也最高。只在存儲引擎層實現
頁級鎖:開銷和加鎖時間界于表鎖和行鎖之間;會出現死鎖;鎖定粒度界于表鎖和行鎖之間,并發度一般
表級鎖:開銷小,加鎖快;不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,并發度最低。