聊聊Java中的事物-Transaction

首先說下什麼是事物(數據庫):
事物是數據庫中一些列的連續的邏輯操做,事物具備ACID特性。(ACID:原子性、一致性、隔離性、持久性)
在處理平常數據時會出現的三類問題:髒讀、不可重複讀、幻讀。java

髒讀 一個事物讀取了另外一個事物中未提交的數據。
不可重複讀 一個事物內讀取表中某一行數據,屢次讀取結果不一樣。(更新操做)
幻讀 一個事物內讀取到了別的事物插入的數據,致使先後不一致。(新增、刪除操做)

在數據庫中能夠設置不一樣的隔離級別解決上述問題,即:Read uncommitted 、Read committed 、Repeatable read 、Serializable(隔離級別低-->高)
           髒讀 不可重複讀 幻讀
Read uncommitted
Read committed ×
Repeatable read × ×
Serializable × × ×
  • Read uncommitted 未提交讀,會形成讀取其它事物中未提交的事物(形成髒讀)。
  • Read committed 提交讀,會形成不可重複讀,事物提交可是存在update操做。
  • Repeatable read 可重複讀,可能會出現幻讀。
  • Serializable 序列化,可避免以上的全部問題(性能低)。

Oracle:默認系統事務隔離級別是READ-COMMITTED。
Mysql:默認的事務處理級別是REPEATABLE-READ。
SQL Server:默認系統事務隔離級別是READ-COMMITTED。spring

Spring 事務管理
Spring中的事物是經過TransactionDefiniton 接口定義的
該接口包含了與事物相關的屬性和方法sql

public interface TransactionDefinition{
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    int getIsolationLevel();
    int getPropagationBehavior();
    int getTimeout();
    boolean isReadOnly();
}
複製代碼

TransactionDefinition接口中定義了五種表示隔離級別的常量數據庫

ISOLATION_DEFAULT(默認) 底層數據庫的默認隔離級別。 對大部分數據庫而言,
常量值是 TransactionDefinition.ISOLATION_READ_COMMITTED
ISOLATION_READ_UNCOMMITTED 該隔離級別表示一個事物能夠讀取另外一個事物中修改可是尚未提交的數據。
該隔離級別不能防止髒讀和不可重複讀。(不多使用)
ISOLATION_READ_COMMITTED 該隔離表示一個事物能夠讀取另外一個事物中已經提交的數據。
該隔離級別能夠防止髒讀。(推薦)
ISOLATION_REPEATABLE_READ 全部事物一次逐個執行,這樣事物之間就徹底不可能產生干擾。
該隔離級別能夠防止髒讀、不可重複讀和幻讀。(不推薦,影響性能)
事物的傳播行爲:一個事物的上下文已存在,此時有若干選項能夠指定一個事物性方法的執行行爲。
事物超時:一個事物所容許的最長時間。若是在超過此時間,事物還未完成,則自動回滾。
事物只讀屬性:對事物性資源進行只讀操做或讀寫操做。若是是隻讀性質的事物,可標記爲只讀,以加強事物的處理能力。
事物的回滾規則:事物中拋出未檢查的異常(RuntimeException),則默認將回滾事務。

事物管理主要分爲兩大類:
(一)、編程式事物管理。
基於 TransactionDefinition、PlatformTransactionManager、TransactionStatus 編程式事務管理是 Spring 提供的最原始的方式。
基於 TransactionTemplate 的編程式事務管理是對上一種方式的封裝,使得編碼更簡單、清晰。
例:Hibernate中,咱們須要在代碼中顯式調用beginTransaction()、commit()、rollback()等事務管理相關的方法。
(二)、聲明式事物管理。
基於 TransactionInterceptor 的聲明式事務是 Spring 聲明式事務的基礎。
基於 TransactionProxyFactoryBean 的聲明式事務。( Spring 2.0 中已不推薦)
基於 和 命名空間的聲明式事務管理(推薦),與 Spring AOP 結合緊密,使得管理事務更加靈活。
例:express

<tx:advice id="txAdvice" transaction-manager="transactionManager">  
    <tx:attributes>  
        <tx:method name="bulk*" propagation="REQUIRED" isolation="DEFAULT" />  
        <tx:method name="load*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>  
    </tx:attributes>  
</tx:advice>  
<aop:config>  
        <aop:advisor pointcut="execution(**.services(..))" advice-ref="txAdvice" />  
</aop:config>  
  
或  
  
<aop:config>  
    <aop:pointcut id="allServiceMethods"  
                  expression="execution(**.services(..))"/>  
    <aop:advisor advice-ref="defaultTransactionAdvice"  
                 pointcut-ref="allServiceMethods"/>  
</aop:config>  
  
<tx:advice id="defaultTransactionAdvice" transaction-manager="transactionManager">  
    <tx:attributes>  
        <tx:method  
                name="*"  
                isolation="DEFAULT"  
                propagation="REQUIRED"  
                rollback-for="java.lang.RuntimeException"  
                timeout="100"/>  
        <tx:method  
                name="get*"  
                read-only="true"/>  
    </tx:attributes>  
</tx:advice> 
複製代碼

基於 @Transactional 的方式將聲明式事務管理
注:
做用於接口、接口方法、類、類中的方法。不推薦在接口中使用該註解,由於只有基於接口的代理時纔會生效。
只能夠用在public方法上,在protected、private使用時,會被忽略。 沒法重用,只能做用於單個類或方法上,需逐個制定。編程

如我的理解有誤差:還請指正。
參考:https://www.ibm.com/developerworks/cn/education/opensource/os-cn-spring-trans/bash

相關文章
相關標籤/搜索