<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-204  評(píng)論-149  文章-0  trackbacks-0
    http://www.javaeye.com/topic/78674
    回帖中也有些需要注意的地方。。可以仔細(xì)看看

    先了解一下數(shù)據(jù)庫(kù)并發(fā)操作帶來的數(shù)據(jù)不一致性包括三類:丟失修改,不可重復(fù)讀(第二個(gè)事務(wù)修改,或插入,或刪除,應(yīng)該說幻讀是指插入或刪除的情況),臟讀。
     

    T1

    T2

    T1

    T2

    T1

    T2

    A=16

    ①讀A=50

    讀B=150

    求和150

    ①讀C=100

    CC*2

    寫回C

    A=16

    B=100

    B=B*2

    寫回B=200

    C=200

    A=A-1

    寫回A=15

    ③讀A=50

    B200

    求和250

    ROLLBACk

    C恢復(fù)到100

    A=A-1

    寫回A=15

    丟失修改

    不可重復(fù)讀

    臟讀



    一般數(shù)據(jù)庫(kù)原理的書中通過“鎖”來解決這種并發(fā)操作帶來的問題

    基本的鎖類型有兩種:排它鎖Exclusive Locks簡(jiǎn)稱X鎖和共享鎖Share Locks,簡(jiǎn)稱S鎖

    排它鎖又稱寫鎖,若事務(wù)T對(duì)數(shù)據(jù)對(duì)象A加上X鎖,則只允許T讀取和修改A,其他任何事務(wù)都不能再對(duì)A加任何類型的鎖,直到T釋放A上的鎖。這就保證了其他事務(wù)在T釋放A上的鎖之前不能再讀取和修改A
    共享鎖又稱讀鎖,若事務(wù)T對(duì)數(shù)據(jù)對(duì)象A加上S鎖,則事務(wù)T可以讀A但不能修改A,其他事務(wù)只能再對(duì)A加S鎖,而不能加X鎖,直到T釋放A上的S鎖。這就保證了其他事務(wù)可以讀A,但在T釋放A上的S鎖之前不能對(duì)A做任何的修改。

    一級(jí)封鎖協(xié)議:事務(wù)T在修改數(shù)據(jù)R之前必須先對(duì)其加X鎖,直到事務(wù)結(jié)束才釋放,這里的事務(wù)結(jié)束包括正常結(jié)束COMMIT和非正常結(jié)束ROLLBACK
    一級(jí)封鎖協(xié)議可以防止丟失修改,并保證事務(wù)T是可恢復(fù)的
    在一級(jí)鎖協(xié)議中,如果僅僅是讀數(shù)據(jù)不對(duì)其進(jìn)行修改,是不需要加鎖的,所以它不能保證可重復(fù)讀和不讀臟數(shù)據(jù)

    二級(jí)封鎖協(xié)議:一級(jí)鎖協(xié)議加上事務(wù)T在讀取數(shù)據(jù)R之前必須先對(duì)其加S鎖,讀完后即可釋放S鎖
    二級(jí)封鎖協(xié)議除了防止丟失修改,還可以進(jìn)一步防止讀“臟”數(shù)據(jù)
    在二級(jí)鎖協(xié)議中,由于讀完數(shù)據(jù)后即可釋放S鎖,所以它不能保證可重復(fù)讀


    三級(jí)鎖協(xié)議:一級(jí)封鎖協(xié)議加上事務(wù)T在讀取數(shù)據(jù)R之前必須對(duì)其加S鎖,直到事務(wù)結(jié)束才釋放S鎖
    三級(jí)封鎖協(xié)議除防止了丟失修改和不讀“臟”數(shù)據(jù)外,還進(jìn)一步防止了不可重復(fù)讀



    Spring聲明式事務(wù)讓我們從復(fù)雜的事務(wù)處理中得到解脫。使得我們?cè)僖矡o需要去處理獲得連接、關(guān)閉連接、事務(wù)提交和回滾等這些操作。再也無需要我們?cè)谂c事務(wù)相關(guān)的方法中處理大量的try…catch…finally代碼。
    我們?cè)谑褂肧pring聲明式事務(wù)時(shí),有一個(gè)非常重要的概念就是事務(wù)屬性。事務(wù)屬性通常由事務(wù)的傳播行為,事務(wù)的隔離級(jí)別,事務(wù)的超時(shí)值和事務(wù)只讀標(biāo)志組成。我們?cè)谶M(jìn)行事務(wù)劃分時(shí),需要進(jìn)行事務(wù)定義,也就是配置事務(wù)的屬性。
    Spring在TransactionDefinition接口中定義這些屬性,以供PlatfromTransactionManager使用, PlatfromTransactionManager是spring事務(wù)管理的核心接口。
    Java代碼 復(fù)制代碼
    1. TransactionDefinition   
    2. public interface TransactionDefinition {   
    3.     int getPropagationBehavior();   
    4.     int getIsolationLevel();   
    5.     int getTimeout();   
    6.     boolean isReadOnly();   
    7. }  


    getTimeout()方法,它返回事務(wù)必須在多少秒內(nèi)完成。
    isReadOnly(),事務(wù)是否只讀,事務(wù)管理器能夠根據(jù)這個(gè)返回值進(jìn)行優(yōu)化,確保事務(wù)是只讀的。
    getIsolationLevel()方法返回事務(wù)的隔離級(jí)別,事務(wù)管理器根據(jù)它來控制另外一個(gè)事務(wù)可以看到本事務(wù)內(nèi)的哪些數(shù)據(jù)。

    在TransactionDefinition接口中定義了五個(gè)不同的事務(wù)隔離級(jí)別
    ISOLATION_DEFAULT 這是一個(gè)PlatfromTransactionManager默認(rèn)的隔離級(jí)別,使用數(shù)據(jù)庫(kù)默認(rèn)的事務(wù)隔離級(jí)別.另外四個(gè)與JDBC的隔離級(jí)別相對(duì)應(yīng)
    ISOLATION_READ_UNCOMMITTED 這是事務(wù)最低的隔離級(jí)別,它充許別外一個(gè)事務(wù)可以看到這個(gè)事務(wù)未提交的數(shù)據(jù)。這種隔離級(jí)別會(huì)產(chǎn)生臟讀,不可重復(fù)讀和幻像讀。
    例如:
    Mary的原工資為1000,財(cái)務(wù)人員將Mary的工資改為了8000,但未提交事務(wù)
    Java代碼 復(fù)制代碼
    1. Connection con1 = getConnection();   
    2. con.setAutoCommit(false);   
    3. update employee set salary = 8000 where empId ="Mary";  

    與此同時(shí),Mary正在讀取自己的工資
    Java代碼 復(fù)制代碼
    1. Connection con2 = getConnection();   
    2. select   salary from employee where empId ="Mary";   
    3. con2.commit();  


    Mary發(fā)現(xiàn)自己的工資變?yōu)榱?000,歡天喜地!
    而財(cái)務(wù)發(fā)現(xiàn)操作有誤,而回滾了事務(wù),Mary的工資又變?yōu)榱?000
    Java代碼 復(fù)制代碼
    1. //con1   
    2.    con1.rollback();  

    像這樣,Mary記取的工資數(shù)8000是一個(gè)臟數(shù)據(jù)。

    ISOLATION_READ_COMMITTED 保證一個(gè)事務(wù)修改的數(shù)據(jù)提交后才能被另外一個(gè)事務(wù)讀取。另外一個(gè)事務(wù)不能讀取該事務(wù)未提交的數(shù)據(jù)。這種事務(wù)隔離級(jí)別可以避免臟讀出現(xiàn),但是可能會(huì)出現(xiàn)不可重復(fù)讀和幻像讀。

    ISOLATION_REPEATABLE_READ 這種事務(wù)隔離級(jí)別可以防止臟讀,不可重復(fù)讀。但是可能出現(xiàn)幻像讀。它除了保證一個(gè)事務(wù)不能讀取另一個(gè)事務(wù)未提交的數(shù)據(jù)外,還保證了避免下面的情況產(chǎn)生(不可重復(fù)讀)。

    在事務(wù)1中,Mary 讀取了自己的工資為1000,操作并沒有完成
    Java代碼 復(fù)制代碼
    1. con1 = getConnection();   
    2. select salary from employee empId ="Mary";  


    在事務(wù)2中,這時(shí)財(cái)務(wù)人員修改了Mary的工資為2000,并提交了事務(wù).
    Java代碼 復(fù)制代碼
    1. con2 = getConnection();   
    2. update employee set salary = 2000;   
    3. con2.commit();  


    在事務(wù)1中,Mary 再次讀取自己的工資時(shí),工資變?yōu)榱?000
    Java代碼 復(fù)制代碼
    1. //con1   
    2. select salary from employee empId ="Mary";  


    在一個(gè)事務(wù)中前后兩次讀取的結(jié)果并不致,導(dǎo)致了不可重復(fù)讀。
    使用ISOLATION_REPEATABLE_READ可以避免這種情況發(fā)生。

    ISOLATION_SERIALIZABLE 這是花費(fèi)最高代價(jià)但是最可靠的事務(wù)隔離級(jí)別。事務(wù)被處理為順序執(zhí)行。除了防止臟讀,不可重復(fù)讀外,還避免了幻像讀。

    目前工資為1000的員工有10人。
    事務(wù)1,讀取所有工資為1000的員工。
    Java代碼 復(fù)制代碼
    1. con1 = getConnection();   
    2. Select * from employee where salary =1000;  
    共讀取10條記錄

    這時(shí)另一個(gè)事務(wù)向employee表插入了一條員工記錄,工資也為1000
    Java代碼 復(fù)制代碼
    1. con2 = getConnection();   
    2. Insert into employee(empId,salary) values("Lili",1000);   
    3. con2.commit();  


    事務(wù)1再次讀取所有工資為1000的員工
    Java代碼 復(fù)制代碼
    1. //con1   
    2. select * from employee where salary =1000;  


    共讀取到了11條記錄,這就產(chǎn)生了幻像讀。
    ISOLATION_SERIALIZABLE能避免這樣的情況發(fā)生。但是這樣也耗費(fèi)了最大的資源。

    getPropagationBehavior()返回事務(wù)的傳播行為,由是否有一個(gè)活動(dòng)的事務(wù)來決定一個(gè)事務(wù)調(diào)用。

    在TransactionDefinition接口中定義了七個(gè)事務(wù)傳播行為

    PROPAGATION_REQUIRED 如果存在一個(gè)事務(wù),則支持當(dāng)前事務(wù)。如果沒有事務(wù)則開啟一個(gè)新的事務(wù)。

    Java代碼 復(fù)制代碼
    1. //事務(wù)屬性 PROPAGATION_REQUIRED   
    2. methodA{   
    3. ……   
    4. methodB();   
    5. ……   
    6. }   
    7.   
    8. //事務(wù)屬性 PROPAGATION_REQUIRED   
    9. methodB{   
    10.     ……   
    11. }  


    使用spring聲明式事務(wù),spring使用AOP來支持聲明式事務(wù),會(huì)根據(jù)事務(wù)屬性,自動(dòng)在方法調(diào)用之前決定是否開啟一個(gè)事務(wù),并在方法執(zhí)行之后決定事務(wù)提交或回滾事務(wù)。

    單獨(dú)調(diào)用methodB方法

    Java代碼 復(fù)制代碼
    1. main{   
    2.    metodB();   
    3. }  


    相當(dāng)于

    Java代碼 復(fù)制代碼
    1. Main{   
    2. Connection con=null;   
    3.   
    4.     rry{   
    5.        con = getConnection();   
    6.        con.setAutoCommit(false);   
    7. //方法調(diào)用   
    8. methodB();   
    9. //提交事務(wù)   
    10. con.commit();   
    11. }   
    12. Catch(RuntimeException ex){   
    13.   //回滾事務(wù)   
    14.    con.rollback();     
    15. }   
    16. finally{   
    17.   //釋放資源   
    18.    closeCon();   
    19. }   
    20. }  


    Spring保證在methodB方法中所有的調(diào)用都獲得到一個(gè)相同的連接。在調(diào)用methodB時(shí),沒有一個(gè)存在的事務(wù),所以獲得一個(gè)新的連接,開啟了一個(gè)新的事務(wù)。

    單獨(dú)調(diào)用MethodA時(shí),在MethodA內(nèi)又會(huì)調(diào)用MethodB.

    執(zhí)行效果相當(dāng)于

    Java代碼 復(fù)制代碼
    1. main{   
    2.     Connection con = null;   
    3.    try{   
    4.        con = getConnection();   
    5.        methodA();   
    6.        con.commit();   
    7. }   
    8. cathc(RuntimeException ex){   
    9. con.rollback();   
    10. }   
    11. finally{   
    12.    closeCon();   
    13. }   
    14. }  


    調(diào)用MethodA時(shí),環(huán)境中沒有事務(wù),所以開啟一個(gè)新的事務(wù).
    當(dāng)在MethodA中調(diào)用MethodB時(shí),環(huán)境中已經(jīng)有了一個(gè)事務(wù),所以methodB就加入當(dāng)前事務(wù)。

    PROPAGATION_SUPPORTS 如果存在一個(gè)事務(wù),支持當(dāng)前事務(wù)。如果沒有事務(wù),則非事務(wù)的執(zhí)行。但是對(duì)于事務(wù)同步的事務(wù)管理器,PROPAGATION_SUPPORTS與不使用事務(wù)有少許不同。

    Java代碼 復(fù)制代碼
    1. //事務(wù)屬性 PROPAGATION_REQUIRED   
    2. methodA(){   
    3.    methodB();   
    4. }   
    5.   
    6. //事務(wù)屬性 PROPAGATION_SUPPORTS   
    7. methodB(){   
    8.    ……   
    9. }  


    單純的調(diào)用methodB時(shí),methodB方法是非事務(wù)的執(zhí)行的。
    當(dāng)調(diào)用methdA時(shí),methodB則加入了methodA的事務(wù)中,事務(wù)地執(zhí)行。

    PROPAGATION_MANDATORY 如果已經(jīng)存在一個(gè)事務(wù),支持當(dāng)前事務(wù)。如果沒有一個(gè)活動(dòng)的事務(wù),則拋出異常。

    Java代碼 復(fù)制代碼
    1. //事務(wù)屬性 PROPAGATION_REQUIRED   
    2. methodA(){   
    3.    methodB();   
    4. }   
    5.   
    6. //事務(wù)屬性 PROPAGATION_MANDATORY   
    7. methodB(){   
    8.    ……   
    9. }  


    當(dāng)單獨(dú)調(diào)用methodB時(shí),因?yàn)楫?dāng)前沒有一個(gè)活動(dòng)的事務(wù),則會(huì)拋出異常
    throw new IllegalTransactionStateException("Transaction propagation 'mandatory' but no existing transaction found");

    當(dāng)調(diào)用methodA時(shí),methodB則加入到methodA的事務(wù)中,事務(wù)地執(zhí)行。

    PROPAGATION_REQUIRES_NEW 總是開啟一個(gè)新的事務(wù)。如果一個(gè)事務(wù)已經(jīng)存在,則將這個(gè)存在的事務(wù)掛起。

    Java代碼 復(fù)制代碼
    1. //事務(wù)屬性 PROPAGATION_REQUIRED   
    2. methodA(){   
    3.    doSomeThingA();   
    4. methodB();   
    5. doSomeThingB();   
    6. }   
    7.   
    8. //事務(wù)屬性 PROPAGATION_REQUIRES_NEW   
    9. methodB(){   
    10.    ……   
    11. }  


    當(dāng)單獨(dú)調(diào)用methodB時(shí),相當(dāng)于把methodB聲明為REQUIRED。開啟一個(gè)新的事務(wù),事務(wù)地執(zhí)行。

    當(dāng)調(diào)用methodA時(shí)

    Java代碼 復(fù)制代碼
    1. main(){   
    2.    methodA();   
    3. }  

    情況有些大不一樣.相當(dāng)于下面的效果。

    Java代碼 復(fù)制代碼
    1. main(){   
    2. TransactionManager tm = null;   
    3. try{   
    4.   //獲得一個(gè)JTA事務(wù)管理器   
    5.     tm = getTransactionManager();   
    6.     tm.begin();//開啟一個(gè)新的事務(wù)   
    7.     Transaction ts1 = tm.getTransaction();   
    8.     doSomeThing();   
    9.     tm.suspend();//掛起當(dāng)前事務(wù)   
    10.    try{   
    11.       tm.begin();//重新開啟第二個(gè)事務(wù)   
    12.       Transaction ts2 = tm.getTransaction();   
    13.       methodB();   
    14.       ts2.commit();//提交第二個(gè)事務(wù)   
    15.         
    16.     }   
    17.    Catch(RunTimeException ex){   
    18.       ts2.rollback();//回滾第二個(gè)事務(wù)   
    19.    }   
    20.   finally{   
    21.     //釋放資源   
    22.    }   
    23.    //methodB執(zhí)行完后,復(fù)恢第一個(gè)事務(wù)   
    24.     tm.resume(ts1);   
    25. doSomeThingB();   
    26.     ts1.commit();//提交第一個(gè)事務(wù)   
    27. }   
    28. catch(RunTimeException ex){   
    29.    ts1.rollback();//回滾第一個(gè)事務(wù)   
    30. }   
    31. finally{   
    32.   //釋放資源   
    33. }   
    34. }  


    在這里,我把ts1稱為外層事務(wù),ts2稱為內(nèi)層事務(wù)。從上面的代碼可以看出,ts2與ts1是兩個(gè)獨(dú)立的事務(wù),互不相干。Ts2是否成功并不依賴于ts1。如果methodA方法在調(diào)用methodB方法后的doSomeThingB方法失敗了,而methodB方法所做的結(jié)果依然被提交。而除了methodB之外的其它代碼導(dǎo)致的結(jié)果卻被回滾了。
    使用PROPAGATION_REQUIRES_NEW,需要使用JtaTransactionManager作為事務(wù)管理器。

    PROPAGATION_NOT_SUPPORTED 總是非事務(wù)地執(zhí)行,并掛起任何存在的事務(wù)。

    Java代碼 復(fù)制代碼
    1. //事務(wù)屬性 PROPAGATION_REQUIRED   
    2. methodA(){   
    3.    doSomeThingA();   
    4. methodB();   
    5. doSomeThingB();   
    6. }   
    7.   
    8. //事務(wù)屬性 PROPAGATION_NOT_SUPPORTED   
    9. methodB(){   
    10.    ……   
    11. }  


    當(dāng)單獨(dú)調(diào)用methodB時(shí),不啟用任何事務(wù)機(jī)制,非事務(wù)地執(zhí)行。
    當(dāng)調(diào)用methodA時(shí),相當(dāng)于下面的效果

    Java代碼 復(fù)制代碼
    1. main(){   
    2. TransactionManager tm = null;   
    3. try{   
    4.   //獲得一個(gè)JTA事務(wù)管理器   
    5.     tm = getTransactionManager();   
    6.     tm.begin();//開啟一個(gè)新的事務(wù)   
    7.     Transaction ts1 = tm.getTransaction();   
    8.     doSomeThing();   
    9.     tm.suspend();//掛起當(dāng)前事務(wù)   
    10.       methodB();   
    11.    //methodB執(zhí)行完后,復(fù)恢第一個(gè)事務(wù)   
    12.     tm.resume(ts1);   
    13. doSomeThingB();   
    14.     ts1.commit();//提交第一個(gè)事務(wù)   
    15. }   
    16. catch(RunTimeException ex){   
    17.    ts1.rollback();//回滾第一個(gè)事務(wù)   
    18. }   
    19. finally{   
    20.   //釋放資源   
    21. }   
    22. }  

    使用PROPAGATION_NOT_SUPPORTED,也需要使用JtaTransactionManager作為事務(wù)管理器。

    PROPAGATION_NEVER 總是非事務(wù)地執(zhí)行,如果存在一個(gè)活動(dòng)事務(wù),則拋出異常

    Java代碼 復(fù)制代碼
    1. //事務(wù)屬性 PROPAGATION_REQUIRED   
    2. methodA(){   
    3.    doSomeThingA();   
    4. methodB();   
    5. doSomeThingB();   
    6. }   
    7.   
    8. //事務(wù)屬性 PROPAGATION_NEVER   
    9. methodB(){   
    10.    ……   
    11. }  

    單獨(dú)調(diào)用methodB,則非事務(wù)的執(zhí)行。
    調(diào)用methodA則會(huì)拋出異常
    throw new IllegalTransactionStateException(
    "Transaction propagation 'never' but existing transaction found");


    PROPAGATION_NESTED如果一個(gè)活動(dòng)的事務(wù)存在,則運(yùn)行在一個(gè)嵌套的事務(wù)中. 如果沒有活動(dòng)事務(wù), 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執(zhí)行

    這是一個(gè)嵌套事務(wù),使用JDBC 3.0驅(qū)動(dòng)時(shí),僅僅支持DataSourceTransactionManager作為事務(wù)管理器。需要JDBC 驅(qū)動(dòng)的java.sql.Savepoint類。有一些JTA的事務(wù)管理器實(shí)現(xiàn)可能也提供了同樣的功能。

    使用PROPAGATION_NESTED,還需要把PlatformTransactionManager的nestedTransactionAllowed屬性設(shè)為true;
    而nestedTransactionAllowed屬性值默認(rèn)為false;

    Java代碼 復(fù)制代碼
    1. //事務(wù)屬性 PROPAGATION_REQUIRED   
    2. methodA(){   
    3.    doSomeThingA();   
    4. methodB();   
    5. doSomeThingB();   
    6. }   
    7.   
    8. //事務(wù)屬性 PROPAGATION_NESTED   
    9. methodB(){   
    10.    ……   
    11. }  


    如果單獨(dú)調(diào)用methodB方法,則按REQUIRED屬性執(zhí)行。

    如果調(diào)用methodA方法,相當(dāng)于下面的效果

    Java代碼 復(fù)制代碼
    1. main(){   
    2. Connection con = null;   
    3. Savepoint savepoint = null;   
    4. try{   
    5.    con = getConnection();   
    6.    con.setAutoCommit(false);   
    7.    doSomeThingA();   
    8.    savepoint = con2.setSavepoint();   
    9.   try  
    10.        methodB();   
    11.    }catch(RuntimeException ex){   
    12.       con.rollback(savepoint);   
    13.    }   
    14.   finally{   
    15.     //釋放資源   
    16.    }   
    17.   
    18.    doSomeThingB();   
    19.    con.commit();   
    20. }   
    21. catch(RuntimeException ex){   
    22.    con.rollback();   
    23. }   
    24. finally{   
    25.   //釋放資源   
    26. }   
    27. }  

    當(dāng)methodB方法調(diào)用之前,調(diào)用setSavepoint方法,保存當(dāng)前的狀態(tài)到savepoint。如果methodB方法調(diào)用失敗,則恢復(fù)到之前保存的狀態(tài)。但是需要注意的是,這時(shí)的事務(wù)并沒有進(jìn)行提交,如果后續(xù)的代碼(doSomeThingB()方法)調(diào)用失敗,則回滾包括methodB方法的所有操作。

    嵌套事務(wù)一個(gè)非常重要的概念就是內(nèi)層事務(wù)依賴于外層事務(wù)。外層事務(wù)失敗時(shí),會(huì)回滾內(nèi)層事務(wù)所做的動(dòng)作。而內(nèi)層事務(wù)操作失敗并不會(huì)引起外層事務(wù)的回滾

    PROPAGATION_NESTED 與PROPAGATION_REQUIRES_NEW的區(qū)別:它們非常類似,都像一個(gè)嵌套事務(wù),如果不存在一個(gè)活動(dòng)的事務(wù),都會(huì)開啟一個(gè)新的事務(wù)。使用PROPAGATION_REQUIRES_NEW時(shí),內(nèi)層事務(wù)與外層事務(wù)就像兩個(gè)獨(dú)立的事務(wù)一樣,一旦內(nèi)層事務(wù)進(jìn)行了提交后,外層事務(wù)不能對(duì)其進(jìn)行回滾。兩個(gè)事務(wù)互不影響。兩個(gè)事務(wù)不是一個(gè)真正的嵌套事務(wù)。同時(shí)它需要JTA事務(wù)管理器的支持。
    使用PROPAGATION_NESTED時(shí),外層事務(wù)的回滾可以引起內(nèi)層事務(wù)的回滾。而內(nèi)層事務(wù)的異常并不會(huì)導(dǎo)致外層事務(wù)的回滾,它是一個(gè)真正的嵌套事務(wù)。DataSourceTransactionManager使用savepoint支持PROPAGATION_NESTED時(shí),需要JDBC 3.0以上驅(qū)動(dòng)及1.4以上的JDK版本支持。其它的JTA TrasactionManager實(shí)現(xiàn)可能有不同的支持方式。

    PROPAGATION_REQUIRED應(yīng)該是我們首先的事務(wù)傳播行為。它能夠滿足我們大多數(shù)的事務(wù)需求。


    posted on 2009-08-01 14:17 Frank_Fang 閱讀(2752) 評(píng)論(3)  編輯  收藏 所屬分類: SSH+JQuery+DWR

    評(píng)論:
    # re: 【轉(zhuǎn)】詳解spring事務(wù)屬性 2009-08-01 19:17 | Frank_Fang
    關(guān)于事務(wù)傳播屬性還有一個(gè)常見的誤解:

    java 代碼

    class A{

    //事務(wù)屬性 PROPAGATION_REQUIRED

    methodA(){

    ......
    ......

    methodB();
    }

    //事務(wù)屬性 PROPAGATION_REQUIRES_NEW

    methodB(){
    .......
    }

    }

    此時(shí)外部程序?qū)ethodA的調(diào)用只會(huì)發(fā)起一個(gè)事務(wù),methodB的PROPAGATION_REQUIRES_NEW屬性不會(huì)起作用
    因?yàn)閙ethodA是在內(nèi)部對(duì)methodB直接調(diào)用,AOP聲明式事務(wù)自然就不起作用了
    所以外部程序?qū)ethodB的調(diào)用仍然是PROPAGATION_REQUIRES_NEW的   回復(fù)  更多評(píng)論
      
    # re: 【轉(zhuǎn)】詳解spring事務(wù)屬性 2009-08-26 00:10 | Frank_Fang
    二、Isolation Level(事務(wù)隔離等級(jí)):
    1、Serializable:最嚴(yán)格的級(jí)別,事務(wù)串行執(zhí)行,資源消耗最大;
    2、REPEATABLE READ:保證了一個(gè)事務(wù)不會(huì)修改已經(jīng)由另一個(gè)事務(wù)讀取但未提交(回滾)的數(shù)據(jù)。避免了“臟讀取”和“不可重復(fù)讀取”的情況,但是帶來了更多的性能損失。
    3、READ COMMITTED:大多數(shù)主流數(shù)據(jù)庫(kù)的默認(rèn)事務(wù)等級(jí),保證了一個(gè)事務(wù)不會(huì)讀到另一個(gè)并行事務(wù)已修改但未提交的數(shù)據(jù),避免了“臟讀取”。該級(jí)別適用于大多數(shù)系統(tǒng)。
    4、Read Uncommitted:保證了讀取過程中不會(huì)讀取到非法數(shù)據(jù)。隔離級(jí)別在于處理多事務(wù)的并發(fā)問題。
    我們知道并行可以提高數(shù)據(jù)庫(kù)的吞吐量和效率,但是并不是所有的并發(fā)事務(wù)都可以并發(fā)運(yùn)行,這需要查看數(shù)據(jù)庫(kù)教材的可串行化條件判斷了。
    這里就不闡述。
    我們首先說并發(fā)中可能發(fā)生的3中不討人喜歡的事情
    1: Dirty reads--讀臟數(shù)據(jù)。也就是說,比如事務(wù)A的未提交(還依然緩存)的數(shù)據(jù)被事務(wù)B讀走,如果事務(wù)A失敗回滾,會(huì)導(dǎo)致事務(wù)B所讀取的的數(shù)據(jù)是錯(cuò)誤的。
    2: non-repeatable reads--數(shù)據(jù)不可重復(fù)讀。比如事務(wù)A中兩處讀取數(shù)據(jù)-total-的值。在第一讀的時(shí)候,total是100,然后事務(wù)B就把total的數(shù)據(jù)改成200,事務(wù)A再讀一次,結(jié)果就發(fā)現(xiàn),total竟然就變成200了,造成事務(wù)A數(shù)據(jù)混亂。
    3: phantom reads--幻象讀數(shù)據(jù),這個(gè)和non-repeatable reads相似,也是同一個(gè)事務(wù)中多次讀不一致的問題。但是non-repeatable reads的不一致是因?yàn)樗〉臄?shù)據(jù)集被改變了(比如total的數(shù)據(jù)),但是phantom reads所要讀的數(shù)據(jù)的不一致卻不是他所要讀的數(shù)據(jù)集改變,而是他的條件數(shù)據(jù)集改變。比如Select account.id where account.name="ppgogo*",第一次讀去了6個(gè)符合條件的id,第二次讀取的時(shí)候,由于事務(wù)b把一個(gè)帳號(hào)的名字由"dd"改成"ppgogo1",結(jié)果取出來了7個(gè)數(shù)據(jù)。 Dirty reads non-repeatable reads phantom reads
    Serializable 不會(huì) 不會(huì) 不會(huì)
    REPEATABLE READ 不會(huì) 不會(huì) 會(huì)
    READ COMMITTED 不會(huì) 會(huì) 會(huì)
    Read Uncommitted 會(huì) 會(huì) 會(huì)

    三、readOnly
    事務(wù)屬性中的readOnly標(biāo)志表示對(duì)應(yīng)的事務(wù)應(yīng)該被最優(yōu)化為只讀事務(wù)。這是一個(gè)最優(yōu)化提示。在一些情況下,一些事務(wù)策略能夠起到顯著的最優(yōu)化效果,例如在使用Object/Relational映射工具(如:Hibernate或TopLink)時(shí)避免dirty checking(試圖“刷新”)。

    四、Timeout 在事務(wù)屬性中還有定義“timeout”值的選項(xiàng),指定事務(wù)超時(shí)為幾秒。在JTA中,這將被簡(jiǎn)單地傳遞到J2EE服務(wù)器的事務(wù)協(xié)調(diào)程序,并據(jù)此得到相應(yīng)的解釋。
      回復(fù)  更多評(píng)論
      
    # re: 【轉(zhuǎn)】詳解spring事務(wù)屬性 2009-08-26 00:30 | Frank_Fang
    數(shù)據(jù)庫(kù)提供了四種事務(wù)隔離級(jí)別, 不同的隔離級(jí)別采用不同的鎖類開來實(shí)現(xiàn).

    在四種隔離級(jí)別中, Serializable的級(jí)別最高, Read Uncommited級(jí)別最低.

    大多數(shù)數(shù)據(jù)庫(kù)的默認(rèn)隔離級(jí)別為: Read Commited,如Sql Server , Oracle.

    少數(shù)數(shù)據(jù)庫(kù)默認(rèn)的隔離級(jí)別為Repeatable Read, 如MySQL InnoDB存儲(chǔ)引擎


    Read Uncommited :讀未提交數(shù)據(jù)( 會(huì)出現(xiàn)臟讀,不可重復(fù)讀,幻讀)

    Read Commited :讀已提交的數(shù)據(jù)(會(huì)出現(xiàn)不可重復(fù)讀,幻讀)

    Repeatable Read :可重復(fù)讀(會(huì)出現(xiàn)幻讀)

    Serializable :串行化


    丟失 更新 :
    當(dāng)兩個(gè)或多個(gè)事務(wù)選擇同一行,然后基于最初選定的值更新該行時(shí),會(huì)發(fā)生丟失更新問題。每個(gè)事務(wù)都不知道其它事務(wù)的存在。最后的更新將重寫由其它事務(wù)所做的更新,這將導(dǎo)致數(shù)據(jù)丟失。   
    例:
    事務(wù)A和事務(wù)B同時(shí)修改某行的值,
    1.事務(wù)A將數(shù)值改為1并提交
    2.事務(wù)B將數(shù)值改為2并提交。
    這時(shí)數(shù)據(jù)的值為2,事務(wù)A所做的更新將會(huì)丟失。
    解決辦法:對(duì)行加鎖,只允許并發(fā)一個(gè)更新事務(wù)。



    臟讀: 一個(gè)事務(wù)讀到另一個(gè)事務(wù)未提交的更新數(shù)據(jù)

    例:


    1.Mary的原工資為1000, 財(cái)務(wù)人員將Mary的工資改為了8000(但未提交事務(wù))
    2.Mary讀取自己的工資 ,發(fā)現(xiàn)自己的工資變?yōu)榱?000,歡天喜地!
    3.而財(cái)務(wù)發(fā)現(xiàn)操作有誤,回滾了事務(wù),Mary的工資又變?yōu)榱?000, 像這樣,Mary記取的工資數(shù)8000是一個(gè)臟數(shù)據(jù)。



    不可重復(fù)讀: 在同一個(gè)事務(wù)中,多次讀取同一數(shù)據(jù),返回的結(jié)果有所不同. 換句話說就是,后續(xù)讀取可以讀到另一個(gè)事務(wù)已提交的更新數(shù)據(jù). 相反"可重復(fù)讀"在同一事務(wù)多次讀取數(shù)據(jù)時(shí),能夠保證所讀數(shù)據(jù)一樣,也就是后續(xù)讀取不能讀到另一事務(wù)已提交的更新數(shù)據(jù).

    例:


    1.在事務(wù)1中,Mary 讀取了自己的工資為1000,操作并沒有完成
    2.在事務(wù)2中,這時(shí)財(cái)務(wù)人員修改了Mary的工資為2000,并提交了事務(wù).
    3.在事務(wù)1中,Mary 再次讀取自己的工資時(shí),工資變?yōu)榱?000
    解決辦法:如果只有在修改事務(wù)完全提交之后才可以讀取數(shù)據(jù),則可以避免該問題。



    幻讀: 一個(gè)事務(wù)讀取到另一個(gè)事務(wù)已提交的insert數(shù)據(jù).

    例:

    第一個(gè)事務(wù)對(duì)一個(gè)表中的數(shù)據(jù)進(jìn)行了修改,這種修改涉及到表中的全部數(shù)據(jù)行。同時(shí) (此時(shí)第一事務(wù)還未提交) ,第二個(gè)事務(wù)向表中插入一行新數(shù)據(jù)。這時(shí)第一個(gè)事務(wù)再去讀取表時(shí),發(fā)現(xiàn)表中還有沒有修改的數(shù)據(jù)行,就好象發(fā)生了幻覺一樣。

      回復(fù)  更多評(píng)論
      
    主站蜘蛛池模板: 亚洲男人的天堂www| 免费无码成人AV片在线在线播放| 黄床大片免费30分钟国产精品| 国产精品亚洲а∨无码播放麻豆 | 亚洲AV日韩AV永久无码久久| 国产亚洲一区二区三区在线不卡| 久久精品国产亚洲AV不卡| 亚洲一区二区三区在线观看精品中文 | 黄床大片免费30分钟国产精品| 国产免费一区二区三区免费视频| 国产高清对白在线观看免费91| 岛国精品一区免费视频在线观看| 国产午夜无码片免费| 免费视频一区二区| 中文字幕亚洲免费无线观看日本 | 最近中文字幕完整免费视频ww | 一个人看的www视频免费在线观看| www成人免费视频| 无码免费一区二区三区免费播放| 99久9在线|免费| 免费精品国产日韩热久久| 日本特黄特色免费大片| 亚洲男女内射在线播放| 亚洲国产精品无码成人片久久| 亚洲激情视频在线观看| 亚洲制服在线观看| 丰满亚洲大尺度无码无码专线 | 亚洲欧美日本韩国| 天堂亚洲免费视频| 亚洲视频在线免费观看| 亚洲人成电影网站免费| 亚洲精品视频在线观看你懂的| 亚洲乱码日产一区三区| 亚洲精品福利网泷泽萝拉| 亚洲码和欧洲码一码二码三码| 十八禁的黄污污免费网站| 污视频在线免费观看| 四虎成人免费观看在线网址 | 我要看WWW免费看插插视频| 亚洲日本一区二区一本一道| 久久丫精品国产亚洲av|