在資料庫操作中,一項事務(transaction)是由一條或多條運算元據庫的 sql 語句組成的乙個不可分割的工作單元,這些操作要麼都完成,要麼都取消。接下來將圍繞事務的特性、併發問題以及隔離級別進行講解。
原子性(atomicity)
原子性是指事務是乙個不可分割的工作單位,事務中的操作要麼全部成功,要麼全部失敗。比如在同乙個事務中的sql語句,要麼全部執行成功,要麼全部執行失敗
一致性(consistency)
事務必須使資料庫從乙個一致性狀態變換到另外乙個一致性狀態
隔離性(isolation)
事務的隔離性是多個使用者併發訪問資料庫時,資料庫為每乙個使用者開啟的事務,不能被其他事務的運算元據所干擾,多個併發事務之間要相互隔離。
永續性(durability)
永續性是指乙個事務一旦被提交,它對資料庫中資料的改變就是永久性的,接下來即使資料庫發生故障也不應該對其有任何影響
如何保證在多使用者併發的情況下時候的隔離性,這就需要設定資料庫事務的隔離級別
髒讀髒讀指乙個事務讀取了另外乙個事務未提交的資料。因為第二個事務可能會回滾,這時第乙個事務就讀到了資料庫不存在的髒資料。
不可重複讀
乙個事務對同一行資料讀取兩次時,讀取到的內容不一樣。在乙個事務的兩次相同查詢之間,有另外乙個事務更新了資料並提交。
幻讀虛讀(幻讀)是指在乙個事務內讀取到了別的事務插入的資料,導致前後讀取不一致。
丟失更新
指兩個事務同時更新一行資料,後提交(或撤銷)的事務將之前事務提交的資料覆蓋了。
第一類丟失更新是指兩個事務同時操作同乙個資料時,當第乙個事務撤銷時,把已經提交的第二個事務的更新資料覆蓋了,第二個事務就造成了資料丟失。
第二類丟失更新是指當兩個事務同時操作同乙個資料時,第乙個事務將修改結果成功提交後,對第二個事務已經提交的修改結果進行了覆蓋,對第二個事務造成了資料丟失。
讀未提交(read uncommitted)
顧名思義,就是可以讀到未提交的內容。如果乙個事務開始寫操作,其他的事務不允許同時寫操作,只能讀,這種情況只能防止丟失更新的問題
實現原理:
對讀取不加鎖,對資料的更新的瞬間對其加行級共享鎖,直到事務結束才釋放。
表現為:乙個事務對一條資料更新時,其他的事務不能對相同的行更新,但是讀取不受影響
讀已提交(read committed)
就是只能讀到已經提交了的內容。這是各種系統中最常用的一種隔離級別,也是sql server和oracle的預設隔離級別。
因為讀已提交採用的是快照讀,假設沒有「快照讀」,那麼當乙個更新的事務沒有提交時,另乙個對更新資料進行查詢的事務會因為無法查詢而被阻塞,這種情況下,併發能力就相當的差。
而「快照讀」就可以完成高併發的查詢,不過,「讀提交」只能避免「髒讀」,並不能避免「不可重複讀」和「幻讀」。
實現原理:
事務對當前被讀取的資料加行級共享鎖(當讀到時才加鎖),一旦讀完該行,立即釋放該行級共享鎖;事務在更新某資料的瞬間(就是發生更新的瞬間),必須先對其加行級排他鎖,直到事務結束才釋放。
表現為:事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、更新;當事務2對該記錄進行更新時,事務1再次讀取該記錄,讀到的只能是事務2更新前的版本,要不就是事務2提交後的版本(快照讀)。
可重複讀 (repeated read)
可重複讀,顧名思義,就是專門針對「不可重複讀」這種情況而制定的隔離級別,自然,它就可以有效的避免「不可重複讀」。而它也是mysql的預設隔離級別。
在這個級別下,普通的查詢同樣是使用的「快照讀」,但是,和「讀提交」不同的是,當事務啟動時,就不允許進行「修改操作(update)」了(因為在讀取的時候,加了行級共享鎖,直到事務結束才釋放,所以這之間是不能進行修改操作的),而「不可重複讀」恰恰是因為兩次讀取之間進行了資料的修改,因此,「可重複讀」能夠有效的避免「不可重複讀」,但卻避免不了「幻讀」,因為幻讀是由於「插入或者刪除操作(insert or delete)」而產生的。
實現原理:
事務在讀取某資料的瞬間(就是開始讀取的瞬間),必須先對其加行級共享鎖,直到事務結束才釋放;事務在更新某資料的瞬間(就是發生更新的瞬間),必須先對其加行級排他鎖,直到事務結束才釋放
表現為:事務1讀取某行記錄時,事務2也能對這行記錄進行讀取、但不能更新,只有當事務1結束,行級共享鎖釋放才能進行更新操作;當事務2對該記錄進行更新時是要等到事務1結束後釋放了行級共享鎖之後才可以,讀到的仍然是第一次讀取的那個版本。
序列化(serializable)
這是資料庫最高的隔離級別,這種級別下,事務「序列化順序執行」,也就是乙個乙個排隊執行。
這種級別下,「髒讀」、「不可重複讀」、「幻讀」都可以被避免,但是執行效率奇差,效能開銷也最大,所以基本沒人會用。
實現原理:
事務在讀取資料時,必須先對其加表級共享鎖,直到事務結束才釋放;事務在更新資料時,必須先對其加表級排他鎖,直到事務結束才釋放。
表現為:事務1正在讀取a表中的記錄時,則事務2也能讀取a表,但不能對a表做更新、新增、刪除,直到事務1結束。事務1正在更新a表中的記錄時,則事務2不能讀取a表的任意記錄,更不可能對a表做更新、新增、刪除,直到事務1結束。
資料庫的增刪改操作預設都會加排他鎖,而查詢不會加任何鎖。
共享鎖:對某一資源加共享鎖,自身可以讀該資源,其他人也可以讀該資源(也可以再繼續加共享鎖,即 共享鎖可多個共存),但無法修改。要想修改就必須等所有共享鎖都釋放完之後。語法為:
select * from table lock in share mode
排他鎖:對某一資源加排他鎖,自身可以進行增刪改查,其他人無法進行任何操作。語法為:
select * from table for update
為什麼會出現「髒讀」?因為沒有「select」操作沒有規矩。
為什麼會出現「不可重複讀」?因為「update」操作沒有規矩。
為什麼會出現「幻讀」?因為「insert」和「delete」操作沒有規矩。
「讀未提(read uncommitted)」能預防啥?預防丟失更新。
「讀提交(read committed)」能預防啥?使用「快照讀(snapshot read)」,避免「髒讀」,但是可能出現「不可重複讀」和「幻讀」。
「可重複讀(repeated red)」能預防啥?使用「快照讀(snapshot read)」,鎖住被讀取記錄,避免出現「髒讀」、「不可重複讀」,但是可能出現「幻讀」。
「序列化(serializable)」能預防啥?排排坐,吃果果,有效避免「髒讀」、「不可重複讀」、「幻讀」,不過效果誰用誰知道。
本文參考:
資料庫事務特性和隔離級別
一 事務的基本要素 acid 1 原子性 atomicity 事務開始後所有操作,要麼全部做完,要麼全部不做,不可能停滯在中間環節。事務執行過程中出錯,會回滾到事務開始前的狀態,所有的操作就像沒有發生一樣。也就是說事務是乙個不可分割的整體,就像化學中學過的原子,是物質構成的基本單位。2 一致性 co...
資料庫事務特性和隔離級別
資料庫事務是資料庫管理系統執行過程中的乙個邏輯單位,有乙個有限的資料庫操作序列完成。以 a賬戶向b賬戶匯錢 為例,乙個事務是下面乙個操作序列 a.從a賬號中把餘額讀出來。b.對a賬號做減法操作。c.把結果寫回a賬號中。d.從b賬號中把餘額讀出來。e.對b賬號做加法操作。f.把結果寫回b賬號中。事務有...
資料庫事務特性和隔離級別
一組業務操作,要麼全部成功,要麼全部不成功。原子性 乙個事務是乙個整體,不可分割,事務中的操作要麼都成功,要麼都失敗。一致性 事務必須是使資料庫從乙個一致性狀態變到另乙個一致性狀態。事務執行前後,資料庫的狀態是一致的。例如 a有1000,元,b有1000元,加起來是2000,中間執行轉賬的操作,轉賬...