This is a real case, from a technical person together to explore, solve a distributed transaction, how dynamic management,
Switch database, suitable for large internet, and library management system. Although there are many similar problems on the Internet, but there is no reliable, effective
Solution.
1. Background information
A brief introduction to the background. A skilled man (classmate) encountered a difficult problem, sounded more attractive, happened to have a little empty hands, on a
Take a look and give yourself 2.5 hours to locate
The case comes from a large internet project involving multiple distributed databases (database based on business split, dozens of MySQL),
With popular technologies such as spring, mybatis, business operations need to span multiple databases, and the entire business requires transactional support. That sounds good.
Current problems, distributed transaction selection Open source lightweight Atomikos, dynamic management data Source selection Spring Abstractroutingdatasource,
Everything's fine. The problem is that the data source cannot be switched dynamically when the transaction is in a service with a dynamically switched data source.
Recurring problem
Description of the problem so far, with deep curiosity, we began a magical journey. 2. The question reappears hears the talent to describe good, the curiosity burst,
Suffer from remote Assistance, had to restore the site first, the problem reappeared.
We simply simulated, simulate simple business scenarios, in a method need to dynamically connect two databases, and insert records separately,
Commit, the entire process requires transactional support.
Define 2 MySQL databases, spring+transaction, JDBC (for simplicity).
We create Userdao:
Simple and clear, pure manual jdbctemplate.
Here we define the Dynamic data source, with the abstractroutingdatasource provided by spring to help us dynamically switch the data source:
We need to set a thread-level holder to save the current connection data source and return it to Routingdatasource:
You can see that we have defined a threadlocal level variable to support concurrent multithreading and to use the current data source as a dynamic variable. This, when combined with Routingdatasource, allows spring to dynamically discover the current data source Spring Bean ID.
In the spring configuration file, 2 data sources are defined DataSource1, DataSource2, and a common datasource integrates all dynamic Data sources and a default data source. and configure Datasourcetransactionmanager transaction support. Everything seems to be going well, so look at how the execution works:
It all looks so good together. We add the transaction.
Take a look at the results of this execution:
Well, when a transaction is added, it causes DB1 to insert two records, and DB2 does not have any records inserted at all.
The good part is that our case recurs. 3. After the Sunding problem recurs, we need Sunding. In fact, probably the network search will know the Xuan shut. The problem is obviously in that line. @transactional why a transaction, the method will only access a data source. Let's take a look at the specific source code of the transaction, we use Datasourcetransactionmanager here:
It turns out that when you start a transaction, because we're using Datasourcetransactionmanager, Spring will default to get the data source and cache it into the Datasourcetransactionobject object. For subsequent commit, rollback, and other transaction operations, so we follow the switch Abstractroutingdatasource, the transaction is not valid. So the db1 inserted two times before, and DB2 didn't have a record. Now I get it.
Solution
When the real reason for the problem is clear, the solution is easy to compare, of course, there seems to be no practical perfect solution. Roughly speaking, it seems that it is possible to manage transactions manually and dynamically modify data sources. Try:
Manually manage transactions, and violence directly modifies DAO data sources, so there should be no big problem, run:
Bingo! See if we can roll. We deliberately throw an exception at the end of the DB1 to see if the end will all roll.
As we expect, DB1 also rolls back:
Good, good. Things are finally out of the way, and there are some sketchy solutions. Summarize
This plan to a break down, although just a simple POC, not to mention the beautiful, not to mention perfect, here is just a draw, mainly to
Share the entire case of the recurrence, analysis, solution, as far as the use of the distributed transactions are similar, and for MyBatis may
The need for violence to modify the sqlsessionfactory, here is not to repeat.
this distributed transaction later found a bit of a problem, so it followed the series 2. Please be concerned.
http://blog.csdn.net/erixhao/article/details/52138760
Public Number: Technical Geek Techbooster