一珍手、事務(wù)級別
SQL標(biāo)準(zhǔn)定義了以下4種事務(wù)隔離級別:
READ?UNCOMMITTED(未提交讀)?幻想讀提陶、不可重復(fù)讀和臟讀都允許框都。一個會話可以讀取其他事務(wù)未提交的更新結(jié)果确丢,如果這個事務(wù)最后以回滾結(jié)束茫多,這時的讀取結(jié)果就可能是不正確的祈匙,所以多數(shù)的數(shù)據(jù)庫都不會運用這種隔離級別。
READ?COMMITTED(已提交讀)?允許幻想讀天揖、不可重復(fù)讀夺欲,不允許臟讀。一個會話只能讀取其他事務(wù)已提交的更新結(jié)果今膊,否則些阅,發(fā)生等待,但是其他會話可以修改這個事務(wù)中被讀取的記錄斑唬,而不必等待事務(wù)結(jié)束市埋,顯然黎泣,在這種隔離級別下,一個事務(wù)中的兩個相同的讀取操作缤谎,其結(jié)果可能不同抒倚。
REPEATABLE?READ(可重復(fù)讀)?允許幻想讀,不允許不可重復(fù)讀和臟讀坷澡。在一個事務(wù)中托呕,如果在兩次相同條件的讀取操作之間沒有添加記錄的操作,也沒有其他更新操作導(dǎo)致在這個查詢條件下記錄數(shù)增多频敛,則兩次讀取結(jié)果相同项郊。換句話說,就是在一個事務(wù)中第一次讀取的記錄保證不會在這個事務(wù)期間發(fā)生改動姻政。SQL?Server是通過在整個事務(wù)期間給讀取的記錄加鎖實現(xiàn)這種隔離級別的呆抑,這樣岂嗓,在這個事務(wù)結(jié)束前汁展,其他會話不能修改事務(wù)中讀取的記錄,而只能等待事務(wù)結(jié)束厌殉,但是SQL?Server不會阻礙其他會話向表中添加記錄食绿,也不阻礙其他會話修改其他記錄。
SERIALIZABLE(可序列化讀)?幻想讀公罕、不可重復(fù)讀和臟讀都不允許器紧。在一個事務(wù)中,讀取操作的結(jié)果是在這個事務(wù)開始之前其他事務(wù)就已經(jīng)提交的記錄楼眷,SQL?Server通過在整個事務(wù)期間給表加鎖實現(xiàn)這種隔離級別铲汪。在這種隔離級別下,對這個表的所有DML操作都是不允許的罐柳,即要等待事務(wù)結(jié)束掌腰,這樣就保證了在一個事務(wù)中的兩次讀取操作的結(jié)果肯定是相同的。SQL標(biāo)準(zhǔn)所定義的默認(rèn)事務(wù)隔離級別是SERIALIZABLE张吉。
二齿梁、事務(wù)的傳播屬性
1: PROPAGATION_REQUIRED
加入當(dāng)前正要執(zhí)行的事務(wù)不在另外一個事務(wù)里,那么就起一個新的事務(wù)
比如說肮蛹,ServiceB.methodB的事務(wù)級別定義為PROPAGATION_REQUIRED, 那么由于執(zhí)行ServiceA.methodA的時候勺择,
ServiceA.methodA已經(jīng)起了事務(wù),這時調(diào)用ServiceB.methodB伦忠,ServiceB.methodB看到自己已經(jīng)運行在ServiceA.methodA
的事務(wù)內(nèi)部省核,就不再起新的事務(wù)。而假如ServiceA.methodA運行的時候發(fā)現(xiàn)自己沒有在事務(wù)中昆码,他就會為自己分配一個事務(wù)气忠。
這樣邓深,在ServiceA.methodA或者在ServiceB.methodB內(nèi)的任何地方出現(xiàn)異常,事務(wù)都會被回滾笔刹。即使ServiceB.methodB的事務(wù)已經(jīng)被
提交芥备,但是ServiceA.methodA在接下來fail要回滾,ServiceB.methodB也要回滾
2: PROPAGATION_SUPPORTS
如果當(dāng)前在事務(wù)中舌菜,即以事務(wù)的形式運行萌壳,如果當(dāng)前不再一個事務(wù)中,那么就以非事務(wù)的形式運行
3: PROPAGATION_MANDATORY
必須在一個事務(wù)中運行日月。也就是說袱瓮,他只能被一個父事務(wù)調(diào)用。否則爱咬,他就要拋出異常
4: PROPAGATION_REQUIRES_NEW
這個就比較繞口了尺借。 比如我們設(shè)計ServiceA.methodA的事務(wù)級別為PROPAGATION_REQUIRED,ServiceB.methodB的事務(wù)級別為PROPAGATION_REQUIRES_NEW精拟,
那么當(dāng)執(zhí)行到ServiceB.methodB的時候燎斩,ServiceA.methodA所在的事務(wù)就會掛起,ServiceB.methodB會起一個新的事務(wù)蜂绎,等待ServiceB.methodB的事務(wù)完成以后栅表,
他才繼續(xù)執(zhí)行。他與PROPAGATION_REQUIRED 的事務(wù)區(qū)別在于事務(wù)的回滾程度了师枣。因為ServiceB.methodB是新起一個事務(wù)怪瓶,那么就是存在
兩個不同的事務(wù)。如果ServiceB.methodB已經(jīng)提交践美,那么ServiceA.methodA失敗回滾洗贰,ServiceB.methodB是不會回滾的。如果ServiceB.methodB失敗回滾陨倡,
如果他拋出的異常被ServiceA.methodA捕獲敛滋,ServiceA.methodA事務(wù)仍然可能提交。
5: PROPAGATION_NOT_SUPPORTED
當(dāng)前不支持事務(wù)玫膀。比如ServiceA.methodA的事務(wù)級別是PROPAGATION_REQUIRED 矛缨,而ServiceB.methodB的事務(wù)級別是PROPAGATION_NOT_SUPPORTED ,
那么當(dāng)執(zhí)行到ServiceB.methodB時帖旨,ServiceA.methodA的事務(wù)掛起箕昭,而他以非事務(wù)的狀態(tài)運行完,再繼續(xù)ServiceA.methodA的事務(wù)解阅。
6: PROPAGATION_NEVER
不能在事務(wù)中運行落竹。假設(shè)ServiceA.methodA的事務(wù)級別是PROPAGATION_REQUIRED, 而ServiceB.methodB的事務(wù)級別是PROPAGATION_NEVER 货抄,
那么ServiceB.methodB就要拋出異常了述召。
7: PROPAGATION_NESTED
理解Nested的關(guān)鍵是savepoint朱转。他與PROPAGATION_REQUIRES_NEW的區(qū)別是,PROPAGATION_REQUIRES_NEW另起一個事務(wù)积暖,將會與他的父事務(wù)相互獨立藤为,
而Nested的事務(wù)和他的父事務(wù)是相依的,他的提交是要等和他的父事務(wù)一塊提交的夺刑。也就是說缅疟,如果父事務(wù)最后回滾,他也要回滾的遍愿。
而Nested事務(wù)的好處是他有一個savepoint存淫。
三、事務(wù)的隔離級別
1沼填、Serializable:最嚴(yán)格的級別桅咆,事務(wù)串行執(zhí)行,資源消耗最大
2坞笙、REPEATABLE READ:保證了一個事務(wù)不會修改已經(jīng)由另一個事務(wù)讀取但未提交(回滾)的數(shù)據(jù)岩饼。避免了“臟讀取”和“不可重復(fù)讀取”的情況,但是帶來了更多的性能損失羞海。
3忌愚、READ COMMITTED:大多數(shù)主流數(shù)據(jù)庫的默認(rèn)事務(wù)等級,保證了一個事務(wù)不會讀到另一個并行事務(wù)已修改但未提交的數(shù)據(jù)却邓,避免了“臟讀取”。該級別適用于大多數(shù)系統(tǒng)院水。
4腊徙、Read Uncommitted:保證了讀取過程中不會讀取到非法數(shù)據(jù)。隔離級別在于處理多事務(wù)的并發(fā)問題檬某。