資料庫的隔離級別和傳播行為

2022-09-06 13:27:18 字數 3010 閱讀 3827

@transactional註解原始碼:

@target()

@retention(retentionpolicy.runtime)

@inherited

@documented

public @inte***ce transactional ;

//方法在發生指定名稱的異常時回滾

string rollbackforclassname() default {};

//方法在發生指定名稱的異常時不回滾

class<? extends throwable> norollbackfor() default {};

//方法在發生指定名稱的異常時不回滾

string norollbackforclassname() default {};

}

在這裡聊聊這裡面的隔離級別和傳播行為。

先提一下資料庫事務的4個基本特徵acid:

atomic(原子性)、consistency(一致性)、isolation(隔離性)、durability(永續性)

這裡的隔離性就是資料庫定義的乙個概念,當多個應用執行緒去操作同一資料時,可能發生髒讀、不可重複讀、幻讀這三種問題。假如我們不考慮事務的隔離性,當併發發生時上述三種問題就很可能會發生,但我們想要完全杜絕上述問題,就要保證對同一資料只能有乙個事務存在,也就是加鎖,當已經有人在操作時,其他事務都要阻塞等待,這樣就會造成效能太渣。在效能和資料一致性之間資料庫定義了四種策略,將選擇權給了使用者,你想要效能還是要資料一致性?這四種策略分別是:未提交讀、讀寫提交、可重複讀、序列化,這四種隔離級別解決了那些問題:

隔離級別和可能發生的現象

隔離級別

髒 讀

不可重複讀

幻 讀

未提交讀

讀寫提交

×

可重複讀

×

×

序列化

×

×

×

先說一下,這三種問題分別是什麼:

髒讀:髒讀意味著乙個事務讀取了另乙個事務未提交的資料,而這個資料是有可能回滾。例如:

兩個事務同時在操作同乙個資料時,乙個事務在查詢,很可能查詢到的是其他事務未提交的資料,也就是髒資料,這就發生了髒讀。

不可重複讀:在乙個事務範圍內兩個相同的查詢卻返回了不同資料。例如:

a使用者讀取該資料為1,b使用者去修改了這個資料為2,b提交了該資料,這時a認為資料應該是1,a去修改這個資料,造成操作失敗,這就是不可重複讀。

幻讀:是指當事務不是獨立執行時發生的一種現象,例如:

第乙個事務對乙個表中的資料進行了修改,這種修改涉及到表中的全部資料行。同時,第二個事務也修改這個表中的資料,這種修改是向表中插入一行新資料。那麼,以後就會發生操作第乙個事務的使用者發現表中還有沒有修改的資料行,就好象發生了幻覺一樣。

針對這三種問題資料庫提出四個策略(隔離級別):

未提交讀:可以讀取別人未提交的資料,相當於不考慮三種問題的發生,無所謂。

獨寫提交:只能讀取被提交的資料,避免了髒讀問題,但可能發生不可重複讀和幻讀問題。

可重複讀:有乙個事務在對這個資料進行讀寫操作時,其他對這個資料操作的事務阻塞等待,避免了不可重複讀的問題,但可能                    發生幻讀問題。

序列化:當有乙個事務在執行的過程中,把其他所有的事務都阻塞掉,都等著,乙個乙個來,我怕亂。(都等去吧)

為了保證資料的一致性,不得不對資料加鎖。隔離級別越高,效能就會直線的下降。不同的資料庫對隔離級別的支援是不同的,oracle支援:讀寫提交和序列化,預設是讀寫提交,mysql四種都支援,預設是可重複讀。

在每乙個@transactional上指定隔離界別太麻煩,也可以在spring的配置檔案中新增乙個預設的隔離級別。

在聊聊傳播行為:

傳播行為是spring存在的乙個概念,每個事務方法(也就是標記有@transaction的方法)都有他自己的事務策略(隔離級別等等),當乙個事務方法呼叫另乙個事務方法時,可能乙個有事務乙個沒事務,也可能都有事務或者都沒事務,這時應該採用那種策略?spring提供了7中傳播行為供你選擇(第一種是預設的,第二種要看一下,其他的我認為很少能用上):

required:主方法有事務就用該事務,沒有就就看子方法有沒有事務。(主方法沒事務,子方法有事務,那子方法的事務不傳遞給主方法。)

nestrd:當前方法呼叫子方法時,如果子方法發生異常,只回滾子方法的事務,而不回滾當前的方法。(事務之間相互獨立)

supports:如果當前存在事務,就沿用當前事務,如果不存在事務,則採用無事務的方式執行子方法。(忽略子方法事務,只看主方法是否有事務)

mandatory:主方法沒有事務就會丟擲異常,有事務就使用主方法事務。

requires_new:無論當前事務是否存在,都會建立新事務執行方法。

not_supported:不支援事務,不開啟事務,執行方法。

never:不支援事務,有事務的話,就拋異常。

這7中傳播行為定義在propagation這個列舉類中。

資料庫事務的隔離級別和傳播行為

事務的性質 acid a 原子性 c 一致性 i 隔離性 d 永續性 隔離級別 read uncommitted 未提交讀 可讀取其他事務未提交的資料,髒讀 幻讀 不可重複讀 read committed 已提交讀 只能讀取其他事務已提交的資料,解決髒讀 repeatable read 可重複讀 在...

事務的隔離級別和傳播行為

size medium 事務的隔離級別和傳播行為 事務的隔離級別 資料庫系統提供了4種事務隔離級別,在這4種隔離級別中,serializable的隔離級別最高,read uncommitted的隔離級別最低 read uncommitted 讀未提交資料 會出現髒讀 read committed 讀...

Spring傳播行為 隔離級別

傳播行為定義了被呼叫方法的事務邊界。傳播行為 意義 propergation mandatory 表示方法必須執行在乙個事務中,如果當前事務不存在,就丟擲異常 propagation nested 表示如果當前事務存在,則方法應該執行在乙個巢狀事務中。否則,它看起來和 propagation req...