本文只先簡單的介紹下Spring中的事務與DB中鎖的關系。
首先總結:Spring事務的實現本質上是使用的DB中的事務,而DB中的事務實現又主要依靠DB中的鎖。所以spring事務本質上使用數據庫鎖,開啟spring事務意味着使用數據庫鎖。
所以大家一定要厘清DB事務與DB各種鎖的原理與概念。后續我也研究一下DB鎖,並結合具體的生產環境監控數據來談談。
《以下是轉載部分內容。主要是Spring事務的使用方式、隔離級別之類的》
那么事務的隔離級別與鎖有什么關系呢?本人認為事務的隔離級別是通過鎖的機制實現的,事務的隔離級別是數據庫開發商根據業務邏輯的實際需要定義的一組鎖的使用策略。當我們將數據庫的隔離級別定義為某一級別后如仍不能滿足要求,我們可以自定義 sql 的鎖來覆蓋事務隔離級別默認的鎖機制。
spring事務實際使用AOP攔截注解方法,然后使用動態代理處理事務方法,捕獲處理過程中的異常,spring事務其實是把異常交給spring處理;
spring事務只有捕獲到異常才會終止或回滾,如果你在程序中try/catch后自己處理異常而沒有throw,那么事務將不會終止或回滾,失去事務本來的作用;
spring事務會捕獲所有的異常,但只會回滾數據庫相關的操作,並且只有在聲明了rollbackForClassName="Exception"之類的配置才會回滾;
spring事務會回滾同一事務中的所有數據庫操作,本質上是回滾同一數據庫連接上的數據庫操作;
spring事務總結:
spring事務本質上使用數據庫鎖;
spring事務只有在方法執行過程中出現異常才會回滾,並且只回滾數據庫相關的操作;
對象鎖和spring事務的對比:
對象鎖可以保證數據一致性和業務邏輯正確性,但不能保證並發性;
spring事務不能嚴格保證數據一致性和業務邏輯正確性,但具有較好的並發性,因為只鎖數據庫行數據;
建議:
如果只有insert操作,可以使用事務;
如果涉及update操作但不涉及其他業務邏輯,可以保守使用事務;
如果涉及update操作及其他業務邏輯,慎用事務,
並且數據庫查詢跟數據庫更新之間盡量間隔較短,中間不宜插入太多其他邏輯,減少數據一致性的風險;
對數據一致性要求不高的情況下可以使用事務結合樂觀鎖,否則建議用鎖;
spring事務為什么不能保證數據一致性和業務邏輯正確性:
1.如果事務方法拋異常,此時會回滾數據庫操作,但已經執行的其他方法不會回滾,因此無法保證業務邏輯正確性;
2.即使事務方法不拋異常,也不能保證數據一致性(因為事務接口里的數據庫操作在整個接口邏輯執行結束后才提交到數據 庫,在接口最后提交到數據庫的前后很有可能帶來數據一致性的問題),從而不能保證業務邏輯正確性;
Spring 事務的傳播屬性
所謂spring事務的傳播屬性,就是定義在存在多個事務同時存在的時候,spring應該如何處理這些事務的行為。這些屬性在TransactionDefinition中定義,具體常量的解釋見下表:
常量名稱 | 常量解釋 |
PROPAGATION_REQUIRED | 支持當前事務,如果當前沒有事務,就新建一個事務。這是最常見的選擇,也是 Spring 默認的事務的傳播。 |
PROPAGATION_REQUIRES_NEW | 新建事務,如果當前存在事務,把當前事務掛起。新建的事務將和被掛起的事務沒有任何關系,是兩個獨立的事務,外層事務失敗回滾之后,不能回滾內層事務執行的結果,內層事務失敗拋出異常,外層事務捕獲,也可以不處理回滾操作 |
PROPAGATION_SUPPORTS | 支持當前事務,如果當前沒有事務,就以非事務方式執行。 |
PROPAGATION_MANDATORY | 支持當前事務,如果當前沒有事務,就拋出異常。 |
PROPAGATION_NOT_SUPPORTED | 以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。 |
PROPAGATION_NEVER | 以非事務方式執行,如果當前存在事務,則拋出異常。 |
PROPAGATION_NESTED | 如果一個活動的事務存在,則運行在一個嵌套的事務中。如果沒有活動事務,則按REQUIRED屬性執行。它使用了一個單獨的事務,這個事務擁有多個可以回滾的保存點。內部事務的回滾不會對外部事務造成影響。它只對DataSourceTransactionManager事務管理器起效。 |
數據庫隔離級別
隔離級別 | 隔離級別的值 | 導致的問題 |
Read-Uncommitted | 0 | 導致臟讀 |
Read-Committed | 1 | 避免臟讀,允許不可重復讀和幻讀 |
Repeatable-Read | 2 | 避免臟讀,不可重復讀,允許幻讀 |
Serializable | 3 | 串行化讀,事務只能一個一個執行,避免了臟讀、不可重復讀、幻讀。執行效率慢,使用時慎重 |
Spring中的隔離級別
常量 | 解釋 |
ISOLATION_DEFAULT | 這是個 PlatfromTransactionManager 默認的隔離級別,使用數據庫默認的事務隔離級別。另外四個與 JDBC 的隔離級別相對應。 |
ISOLATION_READ_UNCOMMITTED | 這是事務最低的隔離級別,它充許另外一個事務可以看到這個事務未提交的數據。這種隔離級別會產生臟讀,不可重復讀和幻像讀。 |
ISOLATION_READ_COMMITTED | 保證一個事務修改的數據提交后才能被另外一個事務讀取。另外一個事務不能讀取該事務未提交的數據。 |
ISOLATION_REPEATABLE_READ | 這種事務隔離級別可以防止臟讀,不可重復讀。但是可能出現幻像讀。 |
ISOLATION_SERIALIZABLE | 這是花費最高代價但是最可靠的事務隔離級別。事務被處理為順序執行。 |