事務的四大特性:
ACID: 原子性,一致性,隔離性,持久性
- 原子性:要不一起成功,要不一起回滾;
- 一致性:對數據的操作,數據總數不變 ; (轉賬業務 A 轉賬B 20元,但是A B的總計還是原來的數值)
- 隔離性:一個事務不會影響另一個事物;
- 持久性:事務一旦提交對數據庫的影響是持久的;
事務的隔離級別:
- 讀未提交Read uncommitted
- 讀已提交Read committed
- 可重復讀Repeatable read
- 串行化Serializable
讀未提交 Read uncommitted:
一個事務讀了另一個事務的未提交內容;可能會出現臟讀、不可重復讀、幻讀;
讀已提交Read committed:
在讀取的時候,其他事務可以進行更改;避免了臟讀;
示例:事務a先讀取某一條數據,事務b更新該條數據,當事務a再次讀取數據的時候,數據發生改變;造成不可重復讀;
可重復讀 Repeatable read:
在讀取的時候,其他事務不可以進行更改;避免了出現臟讀、不可重復讀;但是可能會出現幻讀;事務A讀到的數據是一個數據集,不在是某一行數據,讀取到打印期間,事務B增添了 一條新的數據,這個時候A打印的結果包含之前沒有讀取到的新數據集;
串行化 Serializable:
避免了臟讀、不可重復讀、幻讀 ,但是執行相率不高,相當於鎖表;
擴展:
Oracle只支持Serializable串行化和Read committed讀已提交
MySql默認是Repeatable read可重復讀
Oracle默認是Read committed讀已提交
Mysql事務隔離級別的設置:
1. 在MySQL數據庫中查看當前事務的隔離級別:1select @@tx_isolation;
2. 在MySQL數據庫中設置事務的隔離級別:1set [glogal session] transactionisolationlevel 隔離級別名稱;
參考文章:
Spring中的七中事務傳播行為:
PROPAGATION_REQUIRED
如果當前沒有事務,就新建一個事務,如果已經存在一個事務中,加入到這個事務中。這是最常見的選擇。
PROPAGATION_SUPPORTS
支持當前事務,如果當前沒有事務,就以非事務方式執行。
PROPAGATION_MANDATORY
使用當前的事務,如果當前沒有事務,就拋出異常。;eg:話費充值業務 扣款和訂單其中一個異常則整個處理器回滾;
PROPAGATION_REQUIRES_NEW
新建事務,如果當前存在事務,把當前事務掛起。;
示例:log() 日志事務,不受當前事務當前事務失敗還是成功都需要寫入日志
PROPAGATION_NOT_SUPPORTED
以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。
PROPAGATION_NEVER
以非事務方式執行,如果當前存在事務,則拋出異常。
示例:在訂單的售后處理中,更新完訂單金額后,需要自動統計銷售報表,而統計報表太耗時,所以不在事務中操作;設置為 Never
PROPAGATION_NESTED
如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與PROPAGATION_REQUIRED類似的操作。
示例:在銀行新增銀行卡業務中,需要執行兩個操作,一個是保存銀行卡信息,一個是登記新創建的銀行卡信息,其中登記銀行卡信息成功與否不影響銀行卡的創建。登記銀行卡信息的事務不是必須的所以是否會滾不影響,可以設置為NESTED,而保存卡信息要和整個事務一起 提交或回滾 因此可以設置為required或者mandatory
只讀事務 :@Transactional(readOnly=true)
Spring 為了忽略那些不需要事務的方法,比如讀取數據,這樣可以有效的提高一些性能。
事務超時 (Transaction Timeout):@Transactional(timeout = 60)
為了解決事務執行時間太長,消耗太多資源的問題,可以設置一個超時時間。如果該事務支持超過設置的時間,就回滾該事務。