开发者

How ACID is the two-phase commit protocol?

I came across a situation where I started doubting whether the two-phase commit protocol really guarantees the ACID properties, especially the 'A' part of it.

Let's look at a theoretical distributed transaction involving 2 resources. (More practical description of the problem I had to deal with you can find in my blog). The scenario is a normal execution of a distributed transaction (no failures or recovery). An application starts a transaction, updates both resources, and issues a commit() call. After the commit is completed the application checks both resources and sees all the changes from the completed transaction. Everything is fine, the 2PC protocol did its job, right?

Now, a small change to the scenario. While the distributed transaction is doin开发者_开发百科g commit(), another application is going to the same 2 resources. Can it see only part of the changes from the transaction? Let's say, changes to one resource are already visible while the changes to the second resource are not yet visible.

In all the information I have read on the 2PC protocol I could not find any guarantees about the visibility of the changes in the individual resources relative to each other. And I could not find anything that says that all the resources finish their individual commits at exactly the same time.


I think you are confusing topics. 2PC ensures that transactions commit with a certain visibility. I.e. in your transaction the data you commit will be ordered in a specific way and commits with that transactions will commit serially.

Outside of your transaction the behaviour you see will depend on how locking works in your database. Typically you would expect that a read-only query would either see the before transaction state or the after transaction state (with no guarantee per-se as to which it receives unless it is using the same locking semantics). Write semantics would typically result in locking all items in the transaction, but again this really depends on how your database is configured.

2PC really only promises that an operation is Atomic, and even then it is only necessarily atomic within the scope of that transaction depending on how your database is configured.


I think you're confusing 2PC with concurrency control. Two-phase commit ensures that all the participating threads in a transaction either commit or abort. Concurrency control ensures some sort of ordering of transactions in the same or separate applications. There are various ways of handling this depending on your requirements, but fully serialized transactions are certainly possible.


From Wikipedia

The article explicitly states early-on that 2PC is not resilient to all possible failure configurations. More specific reference here: Three phase commit protocol:

3PC was originally described by Dale Skeen and Michael Stonebraker in their paper, “A Formal Model of Crash Recovery in a Distributed System”.[1] In that work, they modeled 2PC as a system of non-deterministic finite state automata and proved that it is not resilient to a random single site failure.

EDIT: This can be used to disrupt all 4 of ACID properties. My initial answer was wrong.

The visibility of the changes

is an orthogonal issue and depends on involved cohort configuration (see Isolation levels).

The main body of your question and the blog is about Isolation, not Atomicity. Atomicity means the transaction always finishes to the end, committing all changes eventually (or rolling all back).

Even if all cohorts are Serializable and use the same TransactionManager, I still see the possibility to circumvent isolation by starting new transactions at the right time.

After studying your blog, I would say, two-phase commit protocol will not solve your problem, MDB communication must be redesigned more creatively.

From personal experience

Due to blocking nature, 2PC is an overkill in almost any practical situation and a wise design of storage locations and data flows can give a better solution. Basically, you need a unique most authoritative source of any kind of information and all other involved parties must be able to update themselves to that authoritative state. http://en.wikipedia.org/wiki/Communicating_sequential_processes is a great inspiration, especially as implemented in Go. Modern distributed databases are BASE instead of ACID (http://en.wikipedia.org/wiki/Eventual_consistency).


Distributed Acid Transactions are achieved by the Two-Phase Commit protocol. in 2PC any transaction happens in two phases. let's say you have an ecommerce app and your Order Service received an order request. Order service will act as the coordinator of this transaction. In the first phase, it will ask the inventory service and shipment service if they are ready to do this transaction. These 2 services will take logs on their database and once those logs are taken and if they are sure that those transactions can be done, they will promise transaction to the order service. once the Order service receives the confirmations then it will ask its own database if transaction can be done and then it will commit the transaction. committing is the second phase of the transaction. Now Order Service will issue requests to all the participant services to let them know that this order will be taken. then those services will do their own commitment. If the "Inventory" and "Shipment" Service both sent confirmation to the "Order" Service then the response will be returned to the customer.

the problem is communication with the database will take a long time. since more services are involved and taking logs from their own database take time, meanwhile other requests are blocked if they need to modify or access to data for which we have taken the logs. So in the case of second scenario, nothing can access to the currently processed data.

Those transactions do not scale very well. those are useful in the cases where the scalability requirements are not very high. in microservices we have high scalability requirements. Because ACID transactions do not ensure availability and scalability, Compensating Transactions are used in microservices.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜