The Abstract Truth

What is One-and-a-half Phase Commit (1.5PC)? Or, how do I use JMS and JDBC without JTA?

Posted by rbpasker on October 21, 2010

Somebody tweeted Distributed transactions in Spring, with and without XA today, and I read it with interest because of my fascination with distributed transactions.

One of the patterns the author left out is how to provide the 2PC-like atomicity for a database and a messaging resource, but without using XA.

This is called “1.5PC” or “one-and-a-half phase commit.”

In a simple application that takes messages from a queue and updates a database, there are four combinations of behavior when things go wrong, two of which are acceptable and two of which are not:

  • The message is still on the queue but the database has not been updated, which means the crash happened before the database was updated and the message was removed from the queue. These operations can be safely be reissued. This is considered acceptable.
  • The message is no longer on the queue, and the database is updated, which means that both operations completed properly before the crash. This is considered acceptable.
  • The message is still on the queue, and the database is updated, a bad scenario that happens when the crash happens after the database is updated but before the message is removed.
  • The message is no longer on the queue, and the database hasn’t been updated, a bad scenario which happens when the message is removed from the queue before the database is updated.
    Scenarios 3 and 4 are really the same problem – one resource gets updated, but not the other – and can really be considered one problem, with the order of the resource operations reversed.

    1.5PC requires that the messaging system and the database share a unique identifier. It could be an SequenceID or a TransactionID, but it has to be unique for all time, and the unique identifier does not have to be monotonically increasing (but it helps).

    After a crash, the receiver recovers by looking at the head of the message queue, and using the unique identifier to determine if the message was already applied to the database. If the database updated has been applied, the message can be safely removed from the queue. If it has not been applied, the database is updated with the contents of the message, and the message removed from the queue.

    If you’re using Mule, you can get the same effect declaratively using its Multi-TX feature (although shame on Mule for the registration wall).

    But this is only one half of the equation: it prevents duplicate application of the same message to the database, but it doesn’t prevent the message sender from putting two copies of the same messages on the queue (“dupes”) or failing to put a message on the queue (“gaps”). This can be fixed in the sender with similar coordination between the source database and the message queuing system, which is left as an exercise for the reader.

    (Thanks to @RossMason of MuleSoft for providing feedback on an earlier version of this post.)

About these ads

6 Responses to “What is One-and-a-half Phase Commit (1.5PC)? Or, how do I use JMS and JDBC without JTA?”

  1. David Rowley said

    For item 4, don’t you mean to say “The message is no longer on the queue, and the database has not been updated”? i.e. the item was removed from the queue before the db transaction completed.

  2. rbpasker said

    yep, thanks Dave, it was a typo. fixed now.

  3. Or use the JMSRedelivered flag to check if the application has seen the message before.

  4. rbpasker said

    Thanks Ashwin, but the redelivered flag is not guaranteed to be accurate. It also doesnt tell you if the message had already been applied to the database. You can see how the redelivered flag would be set in scenario #3 above.

  5. Brad Merrill said

    But Bob, why would you consider this 1.5PC? Isn’t it just 2 seperate full 2pc transactions, but to seperate resources. Eg, A full 2pc commit to the message queue, and then a full 2pc on the message queue removal. The fact that you have to perform a recovery on the queue (from the databases’ perspective), to determine if the transaction is complete, would be evidence of transaction recovery behavior.

  6. rbpasker said

    Brad, you bring up a really good point: there really arent “1.5” phases of commit. The phrase is meant to convey the idea that the algoritm permits a distributed transaction across to separate resources, but without two-phase (2PC) commit and the need for an external resource manager.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: