ShardingSphere 4.x Distributed Transaction- Principle

Apache ShardingSphere
4 min readSep 2, 2020

--

Navigation

This chapter mainly introduces the principles of the distributed transactions:

  • 2PC transaction-XA
  • Seata BASE transaction

2PC Transaction- XA

Principle

ShardingSphere has defined an SPI for distributed transactions, ShardingTransactionManager. Sharding-JDBC and Sharding-Proxy are two accesses for distributed transactions. XAShardingTransactionManager is its XA implementation, which can be added to ShardingSphere distributed ecology by introducing sharding-transaction-xa-core dependency. XAShardingTransactionManager manages and adapts to actual data source; it delegates begin/commit/rollback in access transactions to XA managers.

1.Begin

Receiving set autoCommit=0 in the access, XAShardingTransactionManager will use XA transaction managers to start overall XA transactions, which is usually marked by XID.

2.Execute sharding physical SQLs

After ShardingSphere parses, optimizes or routes, it will generate sharding SQLUnit of logic SQL. The execution engine will both create connection for each actual SQL and register the corresponding XAResource to the current XA transaction. In this phase, the transaction manager will send XAResource.start to the database and all the SQL before XAResource.end will be marked as XA transactions.

For example:

XAResource1.start             ## execute in the enlist phase
statement.execute("sql1");
statement.execute("sql2");
XAResource1.end ## execute in the commit phase

sql1 and sql2 in it will be marked as XA transactions.

3.Commit/rollback

After XAShardingTransactionManager receives the commit command in the access, it will delegate it to the actual XA manager. It will collect all the registered XAResource in the thread, before sending XAResource.end to mark the boundary for the XA transaction. Then it will send prepare command one by one to collect votes from XAResource. If all the XAResource feedback is OK, it will send commit command to finally finish it. If there is any No XAResource feedback, it will send rollback command to roll back. After sending the commit command, all XAResource exceptions will be submitted again according to the recovery log to ensure the atomicity and high consistency.

For example:

XAResource1.prepare           ## ack: yes
XAResource2.prepare ## ack: yes
XAResource1.commit
XAResource2.commit

XAResource1.prepare ## ack: yes
XAResource2.prepare ## ack: no
XAResource1.rollback
XAResource2.rollback

BASE Transaction Saga

Principle

The implementation class of Saga is SagaShardingTransactionManager. ShardingSphere intercepts the parsing and routing results of logical SQL by Hook. In this way, reverse SQL can be generated before physical SQL is executed, and then the SQL call chain is handed over to Saga engine at the transaction submission stage.

1.Init(Init Saga component)

When an application containing SagaShardingTransactionManager startup, saga-actuator engined will be initialized through saga.properties configuration.

2.Begin(Begin Saga global transaction)

Every time a saga global transaction is created, the context of this global transaction (SagaTransactionContext) is generated. The transaction context records the forward and reverse SQL of all sub-transactions, which is used as metadata to generate SQL call graph processed by saga engine.

3.Execute sharding physical SQLs

Before physical SQL is executed, ShardingSphere generates reverse SQL according to the type of SQL, which is implemented by intercepting parsing results by Hook.

4.Commit/rollback(submitting saga transaction)

The commit phase generates the SQL call graph required by the saga engine, the commit operation generates the Forward Recovery (forward SQL compensation) task, and the rollback operation generates the Backward Recovery task (reverse SQL compensation).

Seata BASE Transaction

Principle

When integrating Seata AT transaction, we need to integrate TM, RM and TC component into ShardingTransactionManager. Seata have proxied DataSource in order to communication with TC throng RPC protocal. Similarly, we can wrap user configured datasource into seata DataSource proxy to make sure distribute transaction after sharding.

1.Init(Init Seata component)

When an application containing ShardingTransactionBaseSeataAT startup, the user-configured DataSource will be wrapped into seata DataSourceProxy through seata.conf, then registered into RM.

2.Begin(begin global transaction)

TM controls the boundaries of global transactions. TM obtains the global transaction ID by sending Begin instructions to TC. All branch transactions participate in the global transaction through this global transaction ID. The context of the global transaction ID will be stored in the thread local variable.

3.Execute sharding physical SQLs

Physical SQL in Seata global transaction will be intercepted to generate undo snapshots by RM and sends participate instructions to TC to join global transaction. since sharding physical SQLs executed in multi-threads, global transaction context should transfer from main thread to child thread, which is exactly the same as context transfer between services.

4.Commit/rollback(submit seata transaction)

When submitting a seata transaction, TM sends TC the commit and rollback instructions of the global transaction. TC coordinates all branch transactions for commit and rollback according to the global transaction ID.

--

--

Apache ShardingSphere
Apache ShardingSphere

Written by Apache ShardingSphere

Distributed SQL transaction & query engine for data sharding, scaling, encryption, and more - on any database. https://linktr.ee/ApacheShardingSphere

No responses yet