Distributed transaction

1. What is the XA specification


1.1 What is two-phase commit
Let's start with a little recap of two-phase commit.
First look at the following picture:

There are three concepts involved in this picture:

AP: Needless to say, AP is the application itself.
RM: RM is a resource manager, that is, a participant in a transaction. In most cases, it refers to a database. A distributed transaction often involves multiple RMs.
TM: TM is the transaction manager, which creates distributed transactions and coordinates the execution and status of each sub-transaction in the distributed transaction. Sub-transactions refer to specific operations performed on RM.

So what is a two-phase (Two-Phase Commit, referred to as 2PC) commit?
The two-stage submission is very simple to put it bluntly. Song Ge will give you a simple example to explain the two-stage submission:
For example the following picture:

We call Storage, Order, and Account respectively in Business. The operations in these three must succeed or fail at the same time, but since these three are in different services, we can only let the operations in these three services be executed separately. , the execution of each transaction in the three services is the first of the two phases.
After the first stage is executed, do not rush to submit, because some of the three services may fail to execute. At this time, each of the three services needs to report their first-stage execution results to a transaction coordinator (that is, the previous article). Seata Server), after the transaction coordinator receives the message, if the first stage of the three services is successfully executed, it will notify the three transactions to submit respectively. Notify the three transactions to roll back separately.
This is called a two-phase commit.
To sum up: In the two-phase commit, the transaction is divided into participants (such as the specific services in the figure above) and the coordinator (Seata Server in the above case). The feedback intelligence of the participants determines whether each participant wants to submit the operation or abort the operation. The participant here can be understood as RM, and the coordinator can be understood as TM.
However, the various distributed transaction modes in Seata are basically evolved on the basis of the two-phase commit, so they are not exactly the same, which requires the attention of small partners.
1.2 What is the XA specification
The XA specification is the Distributed Transaction Processing (DTP) standard defined by the X/Open organization.
The XA specification describes the interface between the global transaction manager and the local resource manager. The purpose of the XA specification is to allow multiple resources (such as databases, application servers, message queues, etc.) to be accessed within the same transaction, so that ACID properties remain valid across applications.
The XA specification uses two-phase commit to guarantee that all resources commit or rollback any particular transaction at the same time.
The XA specification was proposed in the early 1990s. Currently, almost all major databases provide support for the XA specification.
The basis of XA transactions is the two-phase commit protocol. A transaction coordinator is required to ensure that all transaction participants have completed their preparations (phase 1). If the coordinator receives a message that all participants are ready, it will notify that all transactions are ready to commit (phase 2). MySQL plays the role of a participant in this XA transaction, not a coordinator (transaction manager).
MySQL's XA transactions are divided into internal XA and external XA. External XA can participate in external distributed transactions, requiring the application layer to intervene as a coordinator; internal XA transactions are used for cross-engine transactions under the same instance, and Binlog is used as the coordinator. For example, when a storage engine submits, it needs to submit Information is written to the binary log, which is a distributed internal XA transaction, except that the participant in the binary log is MySQL itself. MySQL plays the role of a participant in an XA transaction, not a coordinator.

2. XA in MySQL


Next, Song Ge will show you how XA in MySQL works through a simple example.
2.1 Two-phase transaction commit
For example, for transfer operations, I use the XA transaction in MySQL to demonstrate to you how to transfer 10 yuan from an account:

The above transaction commit is a case of two-phase transaction commit.
The specific steps are as follows:

XA START "transfer_money": This means to open an XA transaction, the following string is the xid of the transaction, which is a unique string. After it is opened, the status of the transaction becomes ACTIVE.
update account set amount=amount-10 where account_no='A'; This means executing specific SQL.
XA END "transfer_money": This means to end an XA transaction, and the state of the transaction changes to IDLE.
XA PREPARE "transfer_money": This puts the transaction in PREPARE state.
XA COMMIT "transfer_money": This is used to commit the transaction. After the commit, the state of the transaction is COMMITED.

The last step can be committed through XA COMMIT or rolled back through XA ROLLBACK. The status of the transaction after rollback is ROLLBACK.
In addition, the fourth step can be omitted, that is, an XA transaction in IDLE state can be directly committed or rolled back.
Let's look at the following flowchart:

From this figure, we can see that transactions can be committed in one step or in two phases, both of which are supported. If it is a two-phase commit, after prepare, it is actually waiting for the feedback from other resource managers (RM).
2.2 Transaction commits directly
Song Ge will show you the one-step transaction submission:

This is relatively simple, nothing to say.
This section will introduce another XA transaction related command XA RECOVER, as shown below:

XA RECOVER can list all XA transactions in PREPARE state, and transactions in other states will not be listed, as shown above.
2.3 Transaction rollback
Another example of transaction rollback:

As you can see, xa recover can view transactions in the prepare state. There are three parameters for transaction rollback: the first parameter is the value intercepted from the data string based on gtrid_length; the second parameter is After the first value is intercepted from data, the remaining value of data, in this case, after the first interception, there is no left, so the second parameter is an empty string; the third parameter is formatID value of .
After the rollback, execute xa recover again to see nothing.
2.4 Summary
In a client-side environment, XA transactions and local (non-XA) transactions are mutually exclusive. If a transaction has been started via XA START, the local transaction will not be started until the XA transaction is committed or rolled back.
Conversely, if a local transaction has been started using START TRANSACTION, XA statements cannot be used until the transaction is committed or rolled back, and XA transactions are only supported by the InnoDB storage engine.
3. XA in Seata

3.1 XA Mode in Seata


Let's look at a little theoretical knowledge first, and then we'll look at code practice in Section 3.3.
Through the above introduction, you already know what is going on in the XA transaction in MySQL. The XA mode in Seata is actually implemented on the basis of the XA mode in MySQL. The XA mode in Seata is a transaction mode that uses transaction resources (databases, message services, etc.) to support the XA protocol within the distributed transaction framework defined by Seata, and uses the mechanism of the XA protocol to manage branch transactions.
Let's look at the following picture:

Let me briefly describe the steps of this implementation:

The global distributed transaction is first started by the TM.
Each business SQL is placed in different XA branches. The specific execution process is XA Start->Business SQL->XA End. This process is consistent with the process of XA transactions in MySQL that I demonstrated in Section 2.1 and you.
After the execution of the XA transaction in the branch is completed, XA prepare is executed, and the status of its own execution is reported to the TC.
Other branch transactions are executed in accordance with steps 2 and 3.
When all branch transactions are executed, TC also receives the execution status reported by each branch transaction. If all the statuses are OK, TC notifies all RMs to execute XA Commit to complete the final commit of the transaction, otherwise TC notifies all RMs to execute XA Rollback Do a transaction rollback.

This is XA mode in Seata! As long as the friends understand the XA mode of MySQL in Section 2.2, then the XA mode in Seata is easy to understand.
3.2 Features
The previous friends have learned two different distributed transaction modes, AT and TCC. Now we will add another XA. Let's compare these three together.

Both AT and TCC restore data through reverse compensation, that is, restore data through an update statement; because XA is MySQL's own function, it is not reverse compensation, but a serious rollback (in The data in the prepare state does not have a commit. In the future, you can choose to commit or rollback in the second stage).
AT and XA modes are non-intrusive distributed transaction solutions, suitable for scenarios that do not want to transform the business, with almost zero learning cost; TCC has certain code intrusion.
Both AT and XA are fully automatic, whether it is submission or rollback (whether it is true rollback or reverse compensation), it is fully automatic, that is, the developer basically does not need to do anything extra; TCC It is a manual distributed transaction, one-stage prepare, two-stage commit or rollback, all the logic is written by the developer himself.
When Song Ge published the previous article, a small partner mentioned the consistency of distributed transactions. XA mode is a solution for distributed strong consistency, but it is used less because of low performance.

Okay, the comparison is over, let’s go to the code!
3.3 Code Practice
Friends only need to understand the previous AT mode, the XA mode is actually similar to the AT mode! Just replace the data source! That being said, there are still a lot of pitfalls in practice, let's take a look at it together.
In order to facilitate your understanding, I will not repeat the case in this article. We will also use the case of placing an order in the previous article to demonstrate.
This is a case of placing an order for a product. There are five services in total. Let me explain a little to you:

eureka: This is the service registry.
account: This is the account service, which can query/modify the user's account information (mainly account balance).
order: This is the order service, where an order can be placed.
storage: This is a warehousing service that can query/modify the inventory quantity of the product.
bussiness: This is business, where users place orders.

What is this case about?
When the user wants to place an order, the interface in the business is called, and the interface in the business calls its own service. In the service, the global distributed transaction is first opened, and then the interface in the storage is called through feign to deduct Inventory, and then call the interface in order through feign to create an order (when order creates an order, it will not only create an order, but also deduct the balance of the user account). problems caused by insufficient inventory, insufficient inventory, etc.), it will trigger the overall transaction rollback.
The specific structure of this case is as follows:

This case is a typical distributed transaction problem. The transactions in storage, order and account belong to different microservices, but we want them to succeed or fail at the same time.
I will not repeat the construction of the basic structure of this case. Friends can refer to the previous article. Here we mainly look at how XA transactions are added.
3.3.1 Database Configuration
Since the XA mode uses MySQL's own implementation of the XA specification, the XA mechanism does not actually need the undo_log table. You can delete the undo_log table in your AT mode. If the Java program reports an error after deletion, then It shows that your XA mode is inauthentic! Pay attention to the explanation behind Song Ge.
Next I will make a few points.

database driven

This is a pit. After repeated tests, Songge found that the XA mode in seata is not compatible with the latest version of MySQL driver, and there will be errors during operation. After testing, the driver of MySQL 8.0.11 version is no problem, so in account, storage and order three For a service that requires database calls, remember to modify the version number that the database driver depends on:

mysql
mysql-connector-java
runtime
8.0.11



druid dependencies

Some friends see that Ali's Dru is used here id database connection pool, join this dependency quickly! As everyone knows, this has fallen into the pit of version compatibility again. The spring-cloud-starter-alibaba-seata dependency actually contains the druid dependency, and the version number is no problem! So friends, don't add druid dependencies manually, you may fall into the pit because of the version number problem.

Turn off the data source code

The next step is to close the seata data source proxy, change the account, storage and order, and add the following configuration:
seata.enable-auto-data-source-proxy=false


Configure a custom data source

The next step is to configure the custom data source, account, order and storage must be configured, as follows:
@Configuration
public class DataSourceConfiguration {

@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DruidDataSource druidDataSource() {
return new DruidDataSource();
}

@Bean("dataSourceProxy")
@Primary
public DataSource dataSource(DruidDataSource druidDataSource) {
return new DataSourceProxyXA(druidDataSource);
}


@Bean
public SqlSessionFactory sqlSessionFactory(DataSource dataSourceProxy) throws Exception{
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSourceProxy);
sqlSessionFactoryBean.setTransactionFactory(new SpringManagedTransactionFactory());
return sqlSessionFactoryBean.getObject();
}

}

Configure DruidDataSource first, but this is not our ultimate goal. The ultimate goal is to configure DataSourceProxyXA. You can see by the name, which will switch the transaction to XA mode. Finally, you need to configure MyBatis based on DataSourceProxyXA. It is a normal operation, not much. Say.
Well, just like that, our seata XA mode is configured~ The other codes are the same as the AT mode, so I won't repeat them.

Related Articles

Explore More Special Offers

  1. Short Message Service(SMS) & Mail Service

    50,000 email package starts as low as USD 1.99, 120 short messages start at only USD 1.00