天天看點

Spring @Transactional - 隔離,傳播

本文翻譯自:Spring @Transactional - isolation, propagation

Can someone explain what isolation & propagation parameters are for in the

@Transactional

annotation via real-world example?

有人可以通過真實世界的例子解釋

@Transactional

注釋中的隔離和傳播參數嗎?

Basically when and why I should choose to change their default values.

基本上何時以及為什麼我應該選擇更改其預設值。

#1樓

參考:https://stackoom.com/question/ZcrE/Spring-Transactional-隔離-傳播

#2樓

PROPAGATION_REQUIRED = 0 ;

PROPAGATION_REQUIRED = 0 ;

If DataSourceTransactionObject T1 is already started for Method M1.If for another Method M2 Transaction object is required ,no new Transaction object is created .Same object T1 is used for M2

如果已經為方法M1啟動了DataSourceTransactionObject T1。如果需要另一個方法M2事務對象,則不會建立新的Transaction對象.Same對象T1用于M2

PROPAGATION_MANDATORY = 2 ;

PROPAGATION_MANDATORY = 2 ;

method must run within a transaction.

方法必須在事務中運作。

If no existing transaction is in progress, an exception will be thrown

如果沒有正在進行的事務,則會抛出異常

PROPAGATION_REQUIRES_NEW = 3 ;

PROPAGATION_REQUIRES_NEW = 3 ;

If DataSourceTransactionObject T1 is already started for Method M1 and it is in progress(executing method M1) .If another method M2 start executing then T1 is suspended for the duration of method M2 with new DataSourceTransactionObject T2 for M2.M2 run within its own transaction context

如果已經為方法M1啟動了DataSourceTransactionObject T1并且它正在進行中(執行方法M1)。如果另一個方法M2開始執行,則T1在方法M2的持續時間内被暫停,其中新的DataSourceTransactionObject T2用于M2.M2在其自己的事務上下文中運作

PROPAGATION_NOT_SUPPORTED = 4 ;

PROPAGATION_NOT_SUPPORTED = 4 ;

If DataSourceTransactionObject T1 is already started for Method M1.If another method M2 is run concurrently .Then M2 should not run within transaction context.

如果已經為方法M1啟動了DataSourceTransactionObject T1。如果另一個方法M2同時運作。那麼M2不應該在事務上下文中運作。

T1 is suspended till M2 is finished.

T1暫停直到M2完成。

PROPAGATION_NEVER = 5 ;

PROPAGATION_NEVER = 5 ;

None of the methods run in transaction context.

這些方法都不在事務上下文中運作。

An isolation level: It is about how much a transaction may be impacted by the activities of other concurrent transactions.It a supports consistency leaving the data across many tables in a consistent state.

隔離級别:它是關于事務可能受其他并發事務的活動影響的程度。它支援一緻性,使資料保持在一緻狀态的多個表中。

It involves locking rows and/or tables in a database.

它涉及鎖定資料庫中的行和/或表。

The problem with multiple transaction

多個交易的問題

Scenario 1 .If T1 transaction reads data from table A1 that was written by another concurrent transaction T2.If on the way T2 is rollback,the data obtained by T1 is invalid one.Eg a=2 is original data .If T1 read a=1 that was written by T2.If T2 rollback then a=1 will be rollback to a=2 in DB.But,Now ,T1 has a=1 but in DB table it is changed to a=2.

場景1.如果T1事務從表A1讀取由另一個并發事務T2寫入的資料。如果在T2復原的路上,T1獲得的資料是無效的.Eg a = 2是原始資料。如果T1讀取a =由T2寫入的1。如果T2復原則a = 1将在DB中復原到a = 2.但是,現在,T1具有= 1但在DB表中它變為a = 2。

Scenario2 .If T1 transaction reads data from table A1.If another concurrent transaction(T2) update data on table A1.Then the data that T1 has read is different from table A1.Because T2 has updated the data on table A1.Eg if T1 read a=1 and T2 updated a=2.Then a!=b.

場景2。如果T1事務從表A1讀取資料。如果另一個并發事務(T2)更新表A1上的資料。那麼T1已讀取的資料與表A1不同。因為T2已更新表A1.Eg上的資料,如果T1讀a = 1,T2更新a = 2.然後a!= b。

Scenario 3 .If T1 transaction reads data from table A1 with certain number of rows.

場景3.如果T1事務從表A1讀取具有特定行數的資料。

If another concurrent transaction(T2) inserts more rows on table A1.The number of rows read by T1 is different from rows on table A1

如果另一個并發事務(T2)在表A1上插入更多行.T1讀取的行數與表A1上​​的行不同

Scenario 1 is called Dirty reads.

場景1稱為髒讀。

Scenario 2 is called Non-repeatable reads.

場景2稱為非可重複讀取。

Scenario 3 is called Phantom reads.

場景3稱為幻影讀取。

So, isolation level is the extend to which Scenario 1, Scenario 2, Scenario 3 can be prevented.

是以,隔離級别是可以防止場景1,場景2,場景3的擴充。

You can obtain complete isolation level by implementing locking.That is preventing concurrent reads and writes to the same data from occurring.But it affects performance .The level of isolation depends upon application to application how much isolation is required.

您可以通過實作鎖定來獲得完整的隔離級别。這會阻止對同一資料的并發讀取和寫入。但它會影響性能。隔離級别取決于應用程式對應用程式需要多少隔離。

ISOLATION_READ_UNCOMMITTED :Allows to read changes that haven't yet been committed.It suffer from Scenario 1, Scenario 2, Scenario 3

ISOLATION_READ_UNCOMMITTED :允許讀取尚未送出的更改。它受場景1,場景2,場景3的影響

ISOLATION_READ_COMMITTED :Allows reads from concurrent transactions that have been committed.

ISOLATION_READ_COMMITTED :允許從已送出的并發事務中讀取。

It may suffer from Scenario 2 and Scenario 3. Because other transactions may be updating the data.

它可能會受到場景2和場景3的影響。因為其他事務可能正在更新資料。

ISOLATION_REPEATABLE_READ :Multiple reads of the same field will yield the same results untill it is changed by itself.It may suffer from Scenario 3.Because other transactions may be inserting the data

ISOLATION_REPEATABLE_READ :同一字段的多次讀取将産生相同的結果,直到它自身更改。它可能會受到場景3的影響。因為其他事務可能正在插入資料

ISOLATION_SERIALIZABLE : Scenario 1,Scenario 2,Scenario 3 never happens.It is complete isolation.It involves full locking.It affets performace because of locking.

ISOLATION_SERIALIZABLE :場景1,場景2,場景3永遠不會發生。它是完全隔離的。它涉及完全鎖定。它因鎖定而影響性能。

You can test using

你可以測試使用
public class TransactionBehaviour {
   // set is either using xml Or annotation
    DataSourceTransactionManager manager=new DataSourceTransactionManager();
    SimpleTransactionStatus status=new SimpleTransactionStatus();
   ;


    public void beginTransaction()
    {
        DefaultTransactionDefinition Def = new DefaultTransactionDefinition();
        // overwrite default PROPAGATION_REQUIRED and ISOLATION_DEFAULT
        // set is either using xml Or annotation
        manager.setPropagationBehavior(XX);
        manager.setIsolationLevelName(XX);

        status = manager.getTransaction(Def);

    }

    public void commitTransaction()
    {


            if(status.isCompleted()){
                manager.commit(status);
        } 
    }

    public void rollbackTransaction()
    {

            if(!status.isCompleted()){
                manager.rollback(status);
        }
    }
    Main method{
        beginTransaction()
        M1();
        If error(){
            rollbackTransaction()
        }
         commitTransaction();
    }

}
           

You can debug and see the result with different values for isolation and propagation.

您可以調試并檢視具有不同隔離和傳播值的結果。

#3樓

Enough explanation about each parameter is given by other answers;

其他答案給出了對每個參數的充分解釋;

However you asked for a real world example, here is the one that clarifies the purpose of different propagation options:

但是你要求一個真實世界的例子,這裡是澄清不同傳播選項目的的例子:

Suppose you're in charge of implementing a signup service in which a confirmation e-mail is sent to the user.

假設您負責實施注冊服務 ,其中向使用者發送确認電子郵件。

You come up with two service objects, one for enrolling the user and one for sending e-mails, which the latter is called inside the first one.

您提出了兩個服務對象,一個用于注冊使用者,另一個用于發送電子郵件,後者在第一個内部調用。

For example something like this:

例如這樣的事情:
/* User DAO */
@Transactional(Propagation=MANDATORY)
class UserDAO{
 // some CRUD methods
}
           

You may have noticed that the second service is of propagation type REQUIRES_NEW and moreover chances are it throws an exception (SMTP server down ,invalid e-mail or other reasons).You probably don't want the whole process to roll-back, like removing the user information from database or other things;

您可能已經注意到第二個服務的傳播類型為REQUIRES_NEW ,而且它可能會抛出異常(SMTP伺服器關閉,無效的電子郵件或其他原因)。您可能不希望整個過程復原,如從資料庫或其他東西中删除使用者資訊;

therefore you call the second service in a separate transaction.

是以,您在單獨的事務中調用第二個服務。

Back to our example, this time you are concerned about the database security, so you define your DAO classes this way:

回到我們的示例,這次您關注資料庫安全性,是以您可以通過以下方式定義DAO類:

Meaning that whenever a DAO object, and hence a potential access to db, is created, we need to reassure that the call was made from inside one of our services, implying that a live transaction should exist;

這意味着每當建立DAO對象并是以建立對db的潛在通路時,我們需要確定調用是從我們的一個服務内部進行的,這意味着應該存在實時事務;

otherwise an exception occurs.Therefore the propagation is of type MANDATORY .

否則會發生異常。是以傳播的類型為MANDATORY 。

#4樓

Transaction Isolation and Transaction Propagation although related but are clearly two very different concepts.

事務隔離和事務傳播雖然相關但顯然是兩個非常不同的概念。

In both cases defaults are customized at client boundary component either by using Declarative transaction management or Programmatic transaction management .

在這兩種情況下,預設值都是通過使用聲明式事務管理或程式化事務管理在用戶端邊界元件上自定義的。

Details of each isolation levels and propagation attributes can be found in reference links below.

每個隔離級别和傳播屬性的詳細資訊可以在下面的參考連結中找到。

Transaction Isolation

交易隔離

For given two or more running transactions/connections to a database, how and when are changes made by queries in one transaction impact/visible to the queries in a different transaction.

對于給定的兩個或多個正在運作的事務/資料庫連接配接,一個事務中的查詢所做的更改如何以及何時對另一個事務中的查詢産生影響/可見。

It also related to what kind of database record locking will be used to isolate changes in this transaction from other transactions and vice versa.

它還涉及将使用何種資料庫記錄鎖定來隔離此事務中的更改與其他事務,反之亦然。

This is typically implemented by database/resource that is participating in transaction.

這通常由參與事務的資料庫/資源​​實作。

.

Transaction Propagation

交易傳播

In an enterprise application for any given request/processing there are many components that are involved to get the job done.

在任何給定請求/處理的企業應用程式中,有許多元件可以完成工作。

Some of this components mark the boundaries (start/end) of a transaction that will be used in respective component and it's sub components.

其中一些元件标記将在各個元件及其子元件中使用的事務的邊界(開始/結束)。

For this transactional boundary of components, Transaction Propogation specifies if respective component will or will not participate in transaction and what happens if calling component already has or does not have a transaction already created/started.

對于元件的此事務邊界,Transaction Propogation指定相應元件是否将參與事務以及如果調用元件已經或者沒有已建立/已啟動的事務會發生什麼。

This is same as Java EE Transaction Attributes.

這與Java EE Transaction Attributes相同。

This is typically implemented by the client transaction/connection manager.

這通常由用戶端事務/連接配接管理器實作。

Reference:

參考:
  • Spring Transaction Management 春季交易管理
  • Wiki Transaction Isolation (database systems) Wiki事務隔離(資料庫系統)
  • Oracle on Transaction Isolation Levels Oracle在事務隔離級别上的應用
  • Java EE Transaction Attributes (propagation) Java EE事務屬性(傳播)
  • Spring Framework Transaction propagation Spring Framework事務傳播

#5樓

I have run

outerMethod

,

method_1

and

method_2

with different propagation mode.

我使用不同的傳播模式運作

outerMethod

method_1

method_2

Below is the output for different propagation mode.

以下是不同傳播模式的輸出。
  • Outer Method 外部方法
  • Method_1 Method_1
  • Method_2 Method_2
      • outerMethod - Without transaction outerMethod - 沒有事務
      • method_1 - Propagation.MANDATORY) - method_1 - Propagation.MANDATORY) -
      • method_2 - Transaction annotation only method_2 - 僅限交易注釋
      • Output: method_1 will throw exception that no existing transaction 輸出:method_1将抛出沒有現有事務的異常
      • outerMethod - Without transaction outerMethod - 沒有事務
      • method_1 - Transaction annotation only method_1 - 僅限交易注釋
      • method_2 - Propagation.MANDATORY) method_2 - Propagation.MANDATORY)
      • Output: method_2 will throw exception that no existing transaction 輸出:method_2将抛出沒有現有事務的異常
      • Output: method_1 will persist record in database. 輸出:method_1将在資料庫中保留記錄。
      • outerMethod - With transaction outerMethod - 使用事務
      • method_1 - Transaction annotation only method_1 - 僅限交易注釋
      • method_2 - Propagation.MANDATORY) method_2 - Propagation.MANDATORY)
      • Output: method_2 will persist record in database. 輸出:method_2将在資料庫中保留記錄。
      • Output: method_1 will persist record in database. 輸出:method_1将在資料庫中保留記錄。 -- Here Main Outer existing transaction used for both method 1 and 2 - 此處主外部現有事務用于方法1和2
      • outerMethod - With transaction outerMethod - 使用事務
      • method_1 - Propagation.MANDATORY) - method_1 - Propagation.MANDATORY) -
      • method_2 - Transaction annotation only and throws exception method_2 - 僅限事務注釋并抛出異常
      • Output: no record persist in database means rollback done. 輸出:資料庫中沒有記錄持續存在意味着復原完成。
      • outerMethod - With transaction outerMethod - 使用事務
      • method_1 - Propagation.REQUIRES_NEW) method_1 - Propagation.REQUIRES_NEW)
      • method_2 - Propagation.REQUIRES_NEW) and throws 1/0 exception method_2 - Propagation.REQUIRES_NEW)并抛出1/0異常
      • Output: method_2 will throws exception so method_2 record not persisted. 輸出:method_2将抛出異常,是以method_2記錄不會持久化。
      • Output: method_1 will persist record in database. 輸出:method_1将在資料庫中保留記錄。
      • Output: There is no rollback for method_1 輸出:method_1沒有復原

#6樓

Isolation level defines how the changes made to some data repository by one transaction affect other simultaneous concurrent transactions, and also how and when that changed data becomes available to other transactions.

隔離級别定義了一個事務對某些資料存儲庫所做的更改如何影響其他并發并發事務,以及這些更改後的資料如何以及何時可用于其他事務。

When we define a transaction using the Spring framework we are also able to configure in which isolation level that same transaction will be executed.

當我們使用Spring架構定義事務時,我們還能夠配置将在哪個隔離級别執行相同的事務。
@Transactional(isolation=Isolation.READ_COMMITTED)
public void someTransactionalMethod(Object obj) {

}
           

READ_UNCOMMITTED isolation level states that a transaction may read data that is still uncommitted by other transactions.

READ_UNCOMMITTED隔離級别指出事務可能讀取其他事務仍未送出的資料。

READ_COMMITTED isolation level states that a transaction can't read data that is not yet committed by other transactions.

READ_COMMITTED隔離級别指出事務無法讀取其他事務尚未送出的資料。

REPEATABLE_READ isolation level states that if a transaction reads one record from the database multiple times the result of all those reading operations must always be the same.

REPEATABLE_READ隔離級别指出,如果事務多次從資料庫中讀取一條記錄,則所有這些讀取操作的結果必須始終相同。

SERIALIZABLE isolation level is the most restrictive of all isolation levels.

SERIALIZABLE隔離級别是所有隔離級别中最嚴格的。

Transactions are executed with locking at all levels (read, range and write locking) so they appear as if they were executed in a serialized way.

事務在所有級别執行鎖定(讀取,範圍和寫入鎖定),是以它們看起來好像是以序列化方式執行的。

Propagation is the ability to decide how the business methods should be encapsulated in both logical or physical transactions.

傳播是決定如何在邏輯或實體事務中封裝業務方法的能力。

Spring REQUIRED behavior means that the same transaction will be used if there is an already opened transaction in the current bean method execution context.

Spring REQUIRED行為意味着如果目前bean方法執行上下文中已經打開的事務,将使用相同的事務。

REQUIRES_NEW behavior means that a new physical transaction will always be created by the container.

REQUIRES_NEW行為意味着容器将始終建立新的實體事務。

The NESTED behavior makes nested Spring transactions to use the same physical transaction but sets savepoints between nested invocations so inner transactions may also rollback independently of outer transactions.

NESTED行為使嵌套的Spring事務使用相同的實體事務,但在嵌套調用之間設定儲存點,是以内部事務也可以獨立于外部事務復原。

The MANDATORY behavior states that an existing opened transaction must already exist.

MANDATORY行為表明現有已打開的事務必須已存在。

If not an exception will be thrown by the container.

如果不是,容器将抛出異常。

The NEVER behavior states that an existing opened transaction must not already exist.

NEVER行為表明現有的已打開事務必須不存在。

If a transaction exists an exception will be thrown by the container.

如果存在事務,則容器将抛出異常。

The NOT_SUPPORTED behavior will execute outside of the scope of any transaction.

NOT_SUPPORTED行為将在任何事務的範圍之外執行。

If an opened transaction already exists it will be paused.

如果已打開的交易已存在,則會暫停。

The SUPPORTS behavior will execute in the scope of a transaction if an opened transaction already exists.

如果已打開的事務已存在,則SUPPORTS行為将在事務範圍内執行。

If there isn't an already opened transaction the method will execute anyway but in a non-transactional way.

如果沒有已經打開的事務,該方法将以任何方式執行,但是以非事務方式執行。