Spring事務傳播機制和資料庫隔離等級

來源:互聯網
上載者:User

先看下Spring的
事務傳播行為類型

 

事務傳播行為類型

說明

PROPAGATION_REQUIRED

如果當前沒有事務,就建立一個事務,如果已經存在一個事務中,加入到這個事務中。這是
最常見的選擇。

PROPAGATION_SUPPORTS

支援當前事務,如果當前沒有事務,就以非事務方式執行。

PROPAGATION_MANDATORY

使用當前的事務,如果當前沒有事務,就拋出異常。

PROPAGATION_REQUIRES_NEW

建立事務,如果當前存在事務,把當前事務掛起。

PROPAGATION_NOT_SUPPORTED

以非事務方式執行操作,如果當前存在事務,就把當前事務掛起。

PROPAGATION_NEVER

以非事務方式執行,如果當前存在事務,則拋出異常。

PROPAGATION_NESTED

如果當前存在事務,則在嵌套事務內執行。如果當前沒有事務,則執行與
PROPAGATION_REQUIRED
類似的操作。

當使用
PROPAGATION_NESTED
時,
底層的資料來源必須基於
JDBC 3.0
,並且實現者需要支援儲存點事務機制。

 

readOnly

     
事務屬性中的readOnly標誌表示對應的事務應該被最佳化為唯讀事務。這
是一個最佳化提示
。在一些情況下,一些事務策略能夠起到顯著的最佳化效果,例如在使用Object/Relational映射工具
(如:Hibernate或TopLink)時避免dirty checking(試圖“重新整理”)。

 

Timeout      
在事務屬性中還有定義“timeout”值的選項,指定事務逾時為幾秒。在JTA中,這將被簡單地傳遞到J2EE伺服器的事務協調程式,並據此得到相應的
解釋。在xml中的設定應該是 timeout_11 表示逾時為11秒。。為什麼呢。。看下面的源碼可知。。Java代碼 /**
 * PropertyEditor for TransactionAttribute objects. Takes Strings of form
 * <p><code>PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2</code>
 * <p>where only propagation code is required. For example:
 * <p><code>PROPAGATION_MANDATORY,ISOLATION_DEFAULT</code>
 *
 * <p>The tokens can be in <strong>any</strong> order. Propagation and isolation codes
 * must use the names of the constants in the TransactionDefinition class. Timeout values
 * are in seconds. If no timeout is specified, the transaction manager will apply a default
 * timeout specific to the particular transaction manager.
 *
 * <p>A "+" before an exception name substring indicates that
 * transactions should commit even if this exception is thrown;
 * a "-" that they should roll back.
 *
 * @author Rod Johnson
 * @author Juergen Hoeller
 * @since 24.04.2003
 * @see org.springframework.transaction.TransactionDefinition
 * @see org.springframework.core.Constants
 */
public class TransactionAttributeEditor extends PropertyEditorSupport {

    /**
     * Format is PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2.
     * Null or the empty string means that the method is non transactional.
     * @see java.beans.PropertyEditor#setAsText(java.lang.String)
     */
    public void setAsText(String s) throws IllegalArgumentException {
        if (s == null || "".equals(s)) {
            setValue(null);
        }
        else {   
            // tokenize it with ","
            String[] tokens = StringUtils.commaDelimitedListToStringArray(s);
            RuleBasedTransactionAttribute attr = new RuleBasedTransactionAttribute();

            for (int i = 0; i < tokens.length; i++) {
                String token = tokens[i].trim();
                if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_PROPAGATION)) {
                    attr.setPropagationBehaviorName(token);
                }
                else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_ISOLATION)) {
                    attr.setIsolationLevelName(token);
                }
                else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_TIMEOUT)) {
                    String value = token.substring(DefaultTransactionAttribute.PREFIX_TIMEOUT.length());
                    attr.setTimeout(Integer.parseInt(value));
                }
                else if (token.equals(RuleBasedTransactionAttribute.READ_ONLY_MARKER)) {
                    attr.setReadOnly(true);
                }
                else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_COMMIT_RULE)) {
                    attr.getRollbackRules().add(new NoRollbackRuleAttribute(token.substring(1)));
                }
                else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_ROLLBACK_RULE)) {
                    attr.getRollbackRules().add(new RollbackRuleAttribute(token.substring(1)));
                }
                else {
                    throw new IllegalArgumentException("Illegal transaction attribute token: [" + token + "]");
                }
            }

            setValue(attr);
        }
    }

}

/** * PropertyEditor for TransactionAttribute objects. Takes Strings of form * <p><code>PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2</code> * <p>where only propagation code is required. For example: * <p><code>PROPAGATION_MANDATORY,ISOLATION_DEFAULT</code> * * <p>The tokens can be in <strong>any</strong> order. Propagation and isolation codes * must use the names of the constants in the TransactionDefinition class. Timeout values * are in seconds. If no timeout is specified, the transaction manager will apply a default * timeout specific to the particular transaction manager. * * <p>A "+" before an exception name substring indicates that * transactions should commit even if this exception is thrown; * a "-" that they should roll back. * * @author Rod Johnson * @author Juergen Hoeller * @since 24.04.2003 * @see org.springframework.transaction.TransactionDefinition * @see org.springframework.core.Constants */public class TransactionAttributeEditor extends PropertyEditorSupport {/** * Format is PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2. * Null or the empty string means that the method is non transactional. * @see java.beans.PropertyEditor#setAsText(java.lang.String) */public void setAsText(String s) throws IllegalArgumentException {if (s == null || "".equals(s)) {setValue(null);}else {// tokenize it with ","String[] tokens = StringUtils.commaDelimitedListToStringArray(s);RuleBasedTransactionAttribute attr = new RuleBasedTransactionAttribute();for (int i = 0; i < tokens.length; i++) {String token = tokens[i].trim();if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_PROPAGATION)) {attr.setPropagationBehaviorName(token);}else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_ISOLATION)) {attr.setIsolationLevelName(token);}else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_TIMEOUT)) {String value = token.substring(DefaultTransactionAttribute.PREFIX_TIMEOUT.length());attr.setTimeout(Integer.parseInt(value));}else if (token.equals(RuleBasedTransactionAttribute.READ_ONLY_MARKER)) {attr.setReadOnly(true);}else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_COMMIT_RULE)) {attr.getRollbackRules().add(new NoRollbackRuleAttribute(token.substring(1)));}else if (token.startsWith(RuleBasedTransactionAttribute.PREFIX_ROLLBACK_RULE)) {attr.getRollbackRules().add(new RollbackRuleAttribute(token.substring(1)));}else {throw new IllegalArgumentException("Illegal transaction attribute token: [" + token + "]");}}setValue(attr);}}}

 

從上面可以看出  token.substring() 這個方法把首碼timeout_給去掉了。。所以只剩下11了從源碼可看出來,PREFIX_XXXX 
大都是這樣寫的,但首碼卻是寫在後面的。。覺得是不是命名有點古怪了,應該是XXXX_PREFIX,害我分析了一段時間。不過在源碼上面的解釋倒很清
楚: * PropertyEditor for TransactionAttribute objects. Takes
Strings of form
 *
<p><code>PROPAGATION_NAME,ISOLATION_NAME,readOnly,timeout_NNNN,+Exception1,-Exception2</code>
 *
<p>where only propagation code is required. For example:
 *
<p><code>PROPAGATION_MANDATORY,ISOLATION_DEFAULT</code>文筆不好。。就給出個執行個體,我想一看就該明白了。Xml代碼     <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">
        <!--  事務攔截器bean需要依賴注入一個交易管理員 -->
        <property name="transactionManager" ref="transactionManager"/>
        <property name="transactionAttributes">
            <!--  下面定義事務傳播屬性-->
            <props>
                <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>
                <prop key="*">PROPAGATION_REQUIRED,timeout_11</prop>
            </props>
        </property>
    </bean>
    <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor">    <!--  事務攔截器bean需要依賴注入一個交易管理員 -->        <property name="transactionManager" ref="transactionManager"/>    <property name="transactionAttributes">    <!--  下面定義事務傳播屬性-->    <props>    <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop>    <prop key="*">PROPAGATION_REQUIRED,timeout_11</prop>    </props>    </property></bean>

 

總結先到這裡。。等深入研究的時候再把寫詳細些。。。   交易隔離等級       資料庫並行作業存在的異常情況:
1.
更新丟失(Lost update):
兩個事務都同時更新一行資料但是第二個事務卻中途失敗退出導致對資料兩個修改都失效了這是系統沒有執
行任何鎖操作因此並發事務並沒有被隔離開來。2. 髒讀取(Dirty Reads):
一個事務開始讀取
了某行資料但是另外一個事務已經更新了此資料但沒有能夠及時提交。這是相當危險很可能所有操作都被復原。3. 不可重複讀取(Non-repeatable Reads):

個事務對同一行資料重複讀取兩次但是卻得到了不同結果。例如在兩次讀取中途有另外一個事務對該行資料進行了修改並提交。4. 兩次更新問題(Second lost updates
problem):
無法重複讀取特例,有兩個並發事務同時讀取同一行資料然後其中一個對它進行修改提交而另一個也進行了修改提交這就會造成
第一次寫操作失效。5. 幻讀(Phantom Reads):
也稱為幻像(幻
影)。事務在操作過程中進行兩次查詢,第二次查詢結果包含了第一次查詢中未出現的資料(這裡並不要求兩次查詢SQL語句相同)這是因為在兩次查詢過程中有
另外一個事務插入資料造成的。      為了避免上面出現幾種情況在標準SQL規範中定義了4個交易隔離等級,不同隔離等級對交易處理不同 。1.未授權讀取(Read Uncommitted):
也稱
未提交讀。允許髒讀取但不允許更新丟失,如果一個事務已經開始寫資料則另外一個資料則不允許同時進行寫操作但允許其他事務讀此行資料。該隔離等級可以通過
“排他寫鎖”實現。事務隔離的最低層級,僅可保證不讀取物理損壞的資料。與READ COMMITTED
隔離級相反,它允許讀取已經被其它使用者修改但尚未提交確定的資料。2. 授權讀取(Read Committed):
也稱提交
讀。允許不可重複讀取但不允許髒讀取。這可以通過“瞬間共用讀鎖”和“排他寫鎖”實現,讀取資料的事務允許其他事務繼續訪問該行資料,但是未提交寫事務將
會禁止其他事務訪問該行。SQL Server 預設的層級。在此隔離級下,SELECT 命令不會返回尚未提交(Committed)
的資料,也不能返回髒資料。3. 可重複讀取(Repeatable Read):
禁止
不可重複讀取和髒讀取。但是有時可能出現幻影資料,這可以通過“共用讀鎖”和“排他寫鎖”實現,讀取資料事務將會禁止寫事務(但允許讀事務),寫事務則禁
止任何其他事務。在此隔離級下,用SELECT 命令讀取的資料在整個命令執行過程中不會被更改。此選項會影響系統的效能,非必要情況最好不用此隔離級。4. 串列(Serializable):
也稱可串列讀。提
供嚴格的事務隔離,它要求事務序列化執行,事務只能一個接著一個地執行,但不能並發執行。如果僅僅通過“行級鎖”是無法實現事務序列化的,必須通過其他機
制保證新插入的資料不會被剛執行查詢操作事務訪問到。事務隔離的最進階別,事務之間完全隔離。如果事務在可串列讀隔離等級上運行,則可以保證任何並發重疊
事務均是串列的。
隔離等級     更新丟失 髒讀取 重複讀取 幻讀
未授權讀取     N            Y        
Y          Y
授權讀取        N            N         Y          Y
可重複
讀取     N            N         N         Y
串列              
N            N         N         N

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.