歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

深入理解 Spring 事務原理

一、事務的基本原理

Spring事務的本質其實就是數據庫對事務的支持,沒有數據庫的事務支持,spring是無法提供事務功能的。對於純JDBC操作數據庫,想要用到事務,可以按照以下步驟進行:

  1. 獲取連接 Connection con = DriverManager.getConnection()
  2. 開啟事務con.setAutoCommit(true/false);
  3. 執行CRUD
  4. 提交事務/回滾事務 con.commit() / con.rollback();
  5. 關閉連接 conn.close();

使用Spring的事務管理功能後,我們可以不再寫步驟 2 和 4 的代碼,而是由Spirng 自動完成。
那麼Spring是如何在我們書寫的 CRUD 之前和之後開啟事務和關閉事務的呢?解決這個問題,也就可以從整體上理解Spring的事務管理實現原理了。下面簡單地介紹下,注解方式為例子

  1. 配置文件開啟注解驅動,在相關的類和方法上通過注解@Transactional標識。
  2. spring 在啟動的時候會去解析生成相關的bean,這時候會查看擁有相關注解的類和方法,並且為這些類和方法生成代理,並根據@Transaction的相關參數進行相關配置注入,這樣就在代理中為我們把相關的事務處理掉了(開啟正常提交事務,異常回滾事務)。
  3. 真正的數據庫層的事務提交和回滾是通過binlog或者redo log實現的。

二、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 串行化讀,事務只能一個一個執行,避免了髒讀、不可重復讀、幻讀。執行效率慢,使用時慎重

髒讀:一事務對數據進行了增刪改,但未提交,另一事務可以讀取到未提交的數據。如果第一個事務這時候回滾了,那麼第二個事務就讀到了髒數據。

不可重復讀:一個事務中發生了兩次讀操作,第一次讀操作和第二次操作之間,另外一個事務對數據進行了修改,這時候兩次讀取的數據是不一致的。

幻讀:第一個事務對一定范圍的數據進行批量修改,第二個事務在這個范圍增加一條數據,這時候第一個事務就會丟失對新增數據的修改。

總結:

隔離級別越高,越能保證數據的完整性和一致性,但是對並發性能的影響也越大。

大多數的數據庫默認隔離級別為 Read Commited,比如 SqlServer、Oracle

少數數據庫默認隔離級別為:Repeatable Read 比如: MySQL InnoDB

Copyright © Linux教程網 All Rights Reserved