事務四特性原子性是指事務包含的所有操作要麼全部成功,要麼全部失敗回滾,這和前面兩篇部落格介紹事務的功能是一樣的概念,因此事務的操作如果成功就必須要完全應用到資料庫,如果操作失敗則不能對資料庫有任何影響。
一致性是指事務必須使資料庫從乙個一致性狀態變換到另乙個一致性狀態,也就是說乙個事務執行之前和執行之後都必須處於一致性狀態。
拿轉賬來說,假設使用者a和使用者b兩者的錢加起來一共是5000,那麼不管a和b之間如何轉賬,轉幾次賬,事務結束後兩個使用者的錢相加起來應該還得是5000,這就是事務的一致性。
隔離性是當多個使用者併發訪問資料庫時,比如操作同一張表時,資料庫為每乙個使用者開啟的事務,不能被其他事務的操作所干擾,多個併發事務之間要相互隔離。
即要達到這麼一種效果:對於任意兩個併發的事務t1和t2,在事務t1看來,t2要麼在t1開始之前就已經結束,要麼在t1結束之後才開始,這樣每個事務都感覺不到有其他事務在併發地執行。
關於事務的隔離性資料庫提供了多種隔離級別,稍後會介紹到。
永續性是指乙個事務一旦被提交了,那麼對資料庫中的資料的改變就是永久性的,即便是在資料庫系統遇到故障的情況下也不會丟失提交事務的操作。
例如我們在使用jdbc運算元據庫時,在提交事務方法後,提示使用者事務操作完成,當我們程式執行完成直到看到提示後,就可以認定事務以及正確提交,即使這時候資料庫出現了問題,也必須要將我們的事務完全執行完成,否則就會造成我們看到提示事務處理完畢,但是資料庫因為故障而沒有執行事務的重大錯誤。
以上介紹完事務的四大特性(簡稱acid),現在重點來說明下事務的隔離性,當多個執行緒都開啟事務運算元據庫中的資料時,資料庫系統要能進行隔離操作,以保證各個執行緒獲取資料的準確性,在介紹資料庫提供的各種隔離級別之前,我們先看看如果不考慮事務的隔離性,會發生的幾種問題:
事務的併發問題1、髒讀:事務a讀取了事務b更新的資料,然後b回滾操作,那麼a讀取到的資料是髒資料
2、不可重複讀:事務 a 多次讀取同一資料,事務 b 在事務a多次讀取的過程中,對資料作了更新並提交,導致事務a多次讀取同一資料時,結果 不一致。
3、幻讀:系統管理員a將資料庫中所有學生的成績從具體分數改為abcde等級,但是系統管理員b就在這個時候插入了一條具體分數的記錄,當系統管理員a改結束後發現還有一條記錄沒有改過來,就好像發生了幻覺一樣,這就叫幻讀。
事務的隔離級別(五種)文字描述
這是乙個platfromtransactionmanager預設的隔離級別,使用資料庫預設的事務隔離級別
另外四個與jdbc的隔離級別相對應;
事務間隔離開【a:b】,事務之間可讀取未提交,可併發執行
這是事務最低的隔離級別,它充許另外乙個事務可以讀取這個事務未提交的資料。
這種隔離級別會產生髒讀,不可重複讀和幻像讀。
事務間隔離開【a:b】,事務之間只讀取提交,可併發執行
保證乙個事務修改的資料提交後才能被另外乙個事務讀取。另外乙個事務不能讀取該事務未提交的資料。
這種事務隔離級別可以避免髒讀出現,但是可能會出現不可重複讀和幻像讀。
事務間隔離開【a:b】,事務之間重複讀,可併發執行
這種事務隔離級別可以防止髒讀,不可重複讀。但是可能出現幻像讀。
它除了保證乙個事務不能讀取另乙個事務未提交的資料外,還保證了避免下面的情況產生(不可重複讀)。
事務間隔離開【a:b】,事務之間順序執行,不能併發執行
這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。
除了防止髒讀,不可重複讀外,還避免了幻像讀。
圖表描述
事務隔離級別 髒讀 不可重複讀 幻讀
讀未提交(read-uncommitted) 是 是 是
不可重複讀(read-committed) 否 是 是
可重複讀(repeatable-read) 否 否 是
序列化(serializable) 否 否 否
註解使用
@transactional(isolation=isolation.default)
事務的傳播行為文字描述
propagation_required 如果當前沒有事務,就新建乙個事務,如果已經存在乙個事務中,加入到這個事務中。這是最常見的選擇。
propagation_supports 支援當前事務,如果當前沒有事務,就以非事務方式執行。
propagation_mandatory 使用當前的事務,如果當前沒有事務,就丟擲異常。
propagation_requires_new 新建事務,如果當前存在事務,把當前事務掛起。
propagation_not_supported 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
propagation_never 以非事務方式執行,如果當前存在事務,則丟擲異常。
propagation_nested 如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則執行與propagation_required類似的操作。
事務傳播行為型別(七種)文字描述
如果當前沒有事務,就新建乙個事務,如果已經存在乙個事務中,加入到這個事務中。這是最常見的選擇。
支援當前事務,如果當前沒有事務,就以非事務方式執行。
使用當前的事務,如果當前沒有事務,就丟擲異常。
新建事務,如果當前存在事務,把當前事務掛起。
以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
以非事務方式執行,如果當前存在事務,則丟擲異常。
如果當前存在事務,則在巢狀事務內執行。如果當前沒有事務,則執行與propagation_required類似的操作。
註解使用
@transaction(propagation=***)
事務使用
事務及巢狀事務的理解1.propagation.required
同乙個事務,一起成功或失敗。注意:required方法內的事務方法,不應該try-catch 而不丟擲異常。
2.propagation.requires_new
完全是新的事務,回滾或提交不受外部影響。
3.propagation.nested的巢狀事務理解
回滾只是回滾內部方法本身,外部事務可以選擇回滾/提交(try-catch方式處理的不同處理)
ps:這點propagation.requires_new也能做到。
外部事務提交回滾/提交,它也進行回滾/提交(它成功時的提交是在外部事務提交時)。
ps:這點propagation.requires_new做不到。
異常:transaction rolled back because it has been marked as1.捕獲後又丟擲了不回滾的異常(預設runtimeexception才回滾,而exception不回滾)。rollback-only原因
2.propagation.required a方法呼叫 propagation.required b方法,如果捕獲了b方法中的異常沒有丟擲 或 捕獲後又丟擲了不回滾的異常(預設exception不回滾)。
transactional的不回滾問題
檢查你方法是不是public的,public方法的transactional註解才是有效的,才能控制事務。
spring預設只對unchecked異常(runtimeexception)回滾,對於checked(exception)異常不回滾。
你的異常型別是checked異常。如果想check異常也想回滾怎麼辦?
(1)註解上加rollbackfor=exception.class
(2)對異常進行轉換,轉換成runtimeexception或自定義繼承 runtimeexception的異常(如承保2.0的busines***ception)
同乙個類中的方法呼叫,內部方法的事務是沒有效果的。
如方法a沒加事務,方法b中加了事務(不管加的是什麼型別的事務)。方法a呼叫方法b,這樣方法b中的事務是無效的。因為aop只對a方法進行處理了,而不會對內部的b方法進行處理。
父類中加了transactional註解,子類中會繼承。
現象:service層繼承了commonsercice的方法預設。commonsercice加了transaction註解,結果service層的每個方法都預設有了transaction註解(required)。
專案實踐(不一定遵守,怎麼方便怎麼用)
不在類中加@transactional,只在用到的方法中加。
不用propagation_supports,因為效果和不加是一樣的。
大多數事務:propagation_required即可滿足要求,要有rollbackfor=exception.class,格式統一如下:
@transactional(propagation = propagation.required,rollbackfor=exception.class)
資料庫事務詳解
事務 transaction 是由一系列對系統中資料進行訪問與更新的操作所組成的乙個程式執行邏輯單元。1.原子性 atomicity 事務的原子性是指事務必須是乙個原子的操作序列單元。事務中包含的各項操作在一次執行過程中,只允許出現兩種狀態之一。全部執行成功 全部執行失敗 任何一項操作都會導致整個事...
資料庫事務詳解
事務 transaction 是在同乙個處理單元中,由一系列對資料進行訪問與更新的操作所組成的乙個基本程式執行邏輯單元。資料庫事務其實主要做了以下兩方面的事 事務具有4個基本特徵,分別是 原子性 atomicity 一致性 consistency 隔離性 isolation 永續性 duration...
資料庫事務詳解
從根本上理解mysql事務,是指作為單個邏輯工作單元執行的一系列操作,要麼成功完全地執行,要麼失敗全部回滾。最經典的例子 使用者a往 使用者b賬戶裡轉100塊錢。正常邏輯 首先使用者a賬戶裡扣除一百元,然後使用者b賬戶增加100元,則轉賬操作完成。這是正常情況,接下來再看看這種情況 使用者a賬戶裡扣...