Durability

Transactions are executed until there is either a rollbackor a commit. On rollback the operations from the transaction will be reversed.

On commit, all modifications done in the transaction will be written to the collection datafiles. These writes will be synchronized to disk if any of themodified collections has the waitForSync property set to true, or if anyindividual operation in the transaction was executed with the waitForSync attribute. Additionally, transactions that modify data in more than one collection areautomatically synchronized to disk. This synchronization is done to not onlyensure durability, but to also ensure consistency in case of a server crash.

That means if you only modify data in a single collection, and that collection has its waitForSync property set to false, the whole transaction will not be synchronized to disk instantly, but with a small delay.

There is thus the potential risk of losing data between the commit of the transaction and the actual (delayed) disk synchronization. This is the same as writing into collections that have the waitForSync property set to false_outside of a transaction.In case of a crash with _waitForSync set to false, the operations performed inthe transaction will either be visible completely or not at all, depending onwhether the delayed synchronization had kicked in or not.

To ensure durability of transactions on a collection that have the waitForSync_property set to _false, you can set the waitForSync attribute of the objectthat is passed to executeTransaction. This will force a synchronization of thetransaction to disk even for collections that have waitForSync set to false:

  1. db._executeTransaction({
  2. collections: {
  3. write: "users"
  4. },
  5. waitForSync: true,
  6. action: function () { ... }
  7. });

An alternative is to perform an operation with an explicit sync request ina transaction, e.g.

  1. db.users.save({ _key: "1234" }, true);

In this case, the true value will make the whole transaction be synchronizedto disk at the commit.

In any case, ArangoDB will give users the choice of whether or not they want full durability for single collection transactions. Using the delayed synchronization(i.e. waitForSync with a value of false) will potentially increase throughput and performance of transactions, but will introduce the risk of losing the lastcommitted transactions in the case of a crash.

The call to the _executeTransaction function will only return after the data of all modified collections has been synchronized to disk and the transaction has been made fully durable. This not only reduces therisk of losing data in case of a crash but also ensures consistency after arestart.

MMFiles Storage Engine

The MMFiles storage engine continuously writes the transaction operation into a journal file on the disk (Journal is sometimes also referred to as write-ahead-log).

This means that the commit operation can be very fast because the engine only needsto write the commit marker into the journal (and perform a disk-sync if waitForSync was set to true). This also means that failed or abortedtransactions need to be rolled back by reversing every single operation.

In case of a server crash, any multi-collection transactions that were not yet committed or in preparation to be committed will be rolled back on server restart.

RocksDB Storage Engine

The RocksDB Storage Engine applies operations in a transaction only in main memoryuntil they are committed. In case of an a rollback the entire transaction is just cleared, no extra rollback steps are required.

In the event of a server-crash the storage engine will scan the write-ahead logto restore certain meta-data like the number of documents in collection or the selectivity estimates of secondary indexes.