mongodb transaction and two-phase commit

Introduction

For the MongoDB database, operations on a single document are guaranteed to be atomic; however, operations designed for multiple documents (ie, multi-document transactions) are not atomic.

In fact, the atomicity of single-document operations can already provide enough support for most practical use cases, because the structure of a single document can be very complex and even include many embedded documents.

Although the function of single-document atomic operations is very powerful, there are still cases where multi-document transactions are required. Certain problems arise when executing a transaction consisting of a sequence of operations , such as:

  • Atomicity: If an operation fails, the previous operation in the transaction must be "rollback" (ie "all or nothing", either all or none)
  • Consistency: If some serious failure (such as network failure, hardware failure, etc.) interrupts the transaction, the database must be able to revert to a consistent state
    In cases where multi-document transactions are required, you can implement two-phase in your application Commit to support these multi-document updates. Two-phase commit guarantees data consistency and, in the event of an error, restores data to its pre-transaction state.

Notice

Because only single-document atomic operations are supported in MongoDB, two-phase commit can only provide transaction-like semantics. Applications can still return intermediate data at intermediate points in two-phase commit or rollback.

example

Overview

Now transfer 100 from Account A to Account B. In a traditional relational database, you can subtract an amount from account A and add a corresponding amount to account B in one transaction. In MongoDB, you can achieve a similar effect with two-phase commit.

This example uses the following two collections:

  1. A collection called accounts is used to store account information.
  2. A collection called transactions is used to store information related to transfer transactions.

Specific process

  1. https://www.jianshu.com/p/6b4f99cb5862
  2. Official documents, benefit a lot

Analyze the various states of the process

0

{_id:"A", balance:1000, pendingTransaction:[]}
{_id:"B", balance:1000, pendingTransaction:[]}

1

{_id:"tx", A->B, state:"initial", lastModified: 1}
{_id:"A", balance:1000, pendingTransaction:[]}
{_id:"B", balance:1000, pendingTransaction:[]}

2

{_id:"tx", A->B, state:"pending", lastModified: 2}
{_id:"A", balance:1000, pendingTransaction:[]}
{_id:"B", balance:1000, pendingTransaction:[]}

3

{_id:"tx", A->B, state:"pending", lastModified: 2}
{_id:"A", balance:900, pendingTransaction:["tx"]}
{_id:"B", balance:1000, pendingTransaction:[]}

4

{_id:"tx", A->B, state:"pending", lastModified: 2}
{_id:"A", balance:900, pendingTransaction:["tx"]}
{_id:"B", balance:1100, pendingTransaction:["tx"]}

5

{_id:"tx", A->B, state:"applied", lastModified: 5}
{_id:"A", balance:900, pendingTransaction:["tx"]}
{_id:"B", balance:1100, pendingTransaction:["tx"]}

6

{_id:"tx", A->B, state:"applied", lastModified: 5}
{_id:"A", balance:900, pendingTransaction:[]}
{_id:"B", balance:1100, pendingTransaction:["tx"]}

7

{_id:"tx", A->B, state:"applied", lastModified: 5}
{_id:"A", balance:900, pendingTransaction:[]}
{_id:"B", balance:1100, pendingTransaction:[]}

8

{_id:"tx", A->B, state:"done", lastModified: 8}
{_id:"A", balance:900, pendingTransaction:[]}
{_id:"B", balance:1100, pendingTransaction:[]}

Recovering from Failure Scenarios

The most important part of the transaction procedure is not the prototypical example above, but rather the possibility for recovering from the various failure scenarios when transactions do not complete successfully. This section presents an overview of possible failures and provides steps to recover from these kinds of events.

Recovery Operations

The two-phase commit pattern allows applications running the sequence to resume the transaction and arrive at a consistent state. (Let all transactions be executed and arrive at the final state)

Run the recovery operations at application startup, and possibly at regular intervals, to catch any unfinished transactions.

The time required to reach a consistent state depends on how long the application needs to recover each transaction.

The following recovery procedures uses the lastModified date as an indicator of whether the pending transaction requires recovery; specifically, if the pending or applied transaction has not been updated in the last 30 minutes, the procedures determine that these transactions require recovery. You can use different conditions to make this determination.

Transactions in Pending State

To recover from failures that occur after step “Update transaction state to pending.” but before “Update transaction state to applied.” step, retrieve from the transactions collection a pending transaction for recovery and resume from step “Apply the transaction to both accounts.”

Transactions in Applied State

To recover from failures that occur after step “Update transaction state to applied.” but before “Update transaction state to done.” step, retrieve from the transactions collection an applied transaction for recovery and resume from “Update both accounts’ list of pending transactions.”

Rollback Operations

In some cases, you may need to “roll back” or undo a transaction; e.g., if the application needs to “cancel” the transaction or if one of the accounts does not exist or stops existing during the transaction.

Transactions in Applied State

After the “Update transaction state to applied.” step, you should not roll back the transaction. Instead, complete that transaction and create a new transaction to reverse the transaction by switching the values in the source and the destination fields.

Transactions in Pending State

After the “Update transaction state to pending.” step, but before the “Update transaction state to applied.” step, you can rollback the transaction using the following procedure:

  1. Update transaction state to canceling.

  2. Undo the transaction on both accounts.

  3. Update transaction state to canceled.

Another simple example

Related github implementation

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325771865&siteId=291194637