Transactions

Introduction

An operation on a single document is atomic. This is enough in most use cases since embedded documents can capture relationships between data in a single document.

However, for situations that require atomicity for multiple write requests or consistency between multiple read requests, multi-document transactions must be used.

Multi-document transaction requires at least MongoDB v4.0 configured as a Replica Set.

Tech talk on Transaction in RESTHeart at MongoDB Live 2020

The demo application shown during the talk is available from github at restheart-txn-demo

Sessions

MongoDB v3.6 introduced sessions, defined as follows:

A session is an abstract concept that represents a set of sequential operations executed by an application that are related in some way.

Sessions allows to enforce casual consistency and are the foundation for transactions.

Sessions are available also in the OS version of RESTHeart. RESTHeart adds support for multi-document transactions on top of sessions.

Start a session

POST /_sessions HTTP/1.1
{ "causallyConsistent": true }

HTTP/1.1 201 Created
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Location, ETag, X-Powered-By
Connection: keep-alive
Content-Length: 0
Content-Type: application/json
Date: Wed, 19 Jun 2019 09:01:04 GMT
Location: http://localhost:8009/_sessions/11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0
X-Powered-By: restheart.org

The causallyConsistent property is optional, true by default.

The session id is returned via the Location response header. In this case

sid=11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0

Execute a request in a session

Requests can be executed in a session using the sid query parameter.
POST /coll?sid=11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0 HTTP/1.1
{"foo": "bar"}

HTTP/1.1 201 Created
GET /coll?sid=11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0 HTTP/1.1

HTTP/1.1 200 OK

Transactions

Transactions are handled in sessions; per each session, one transaction at a time can be started.

Transaction Status

The following tables lists all possible transactions status.

status description
IN The transaction is in progress
ABORTED The transaction has been aborted, either explicitly or due to an error or because it expired
COMMITTED The transaction has been successfully committed

Error handling

The client is responsible of handling the following errors when executing requests inside a transaction and incorporate retry logic.

The following table shows the most important error status that should be handled.

error response status description
The given transaction is not in-progress 406 A request is executed in a transaction whose status is not IN
Write conflict inside transaction 409 This error occurs when a transaction updating one of more documents tries to commit after a second transaction have been successfully committed updating the same data.

By default, a transaction must have a runtime of less than one minute. After that, the transaction is automatically ABORTED. Check MongoDB Documentation for more information.

Start the transaction

Transaction are started in sessions.

The following POST request starts the transaction in session 11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0

POST /_sessions/11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0/_txns HTTP/1.1

HTTP/1.1 201 Created
Location: http://localhost:8009/_sessions/11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0/_txns/1
...

Note that the Location response header returns the id of the transaction or txn. In this case:

txn=1

Get the current transaction status

GET /_sessions/11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0/_txns HTTP/1.1

HTTP/1.1 200 Ok
...
{
    "currentTxn": {
        "id": 1,
        "status": "IN"
    }
}

Execute requests in the transaction

Requests can be executed in the transaction using the sid and txn query parameters.

POST /coll?sid=11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0&txn=1 HTTP/1.1
{"foo": "bar"}

HTTP/1.1 201 Created
GET /coll?sid=11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0&txn=1 HTTP/1.1

HTTP/1.1 200 Ok

Commit the transaction

Use the method PATCH to commit the transaction.

PATCH /_sessions/11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0/_txns/1 HTTP/1.1

HTTP/1.1 200 OK

Abort the transaction

Use the method DELETE to abort the transaction.

DELETE /_sessions/11c3ceb6-7b97-4f34-ba3f-689ea22ce6e0/_txns/1 HTTP/1.1

HTTP/1.1 204 No Content