Version:

File formats

To maintain data persistence, Tarantool writes each data change request (insert,
update, delete, replace, upsert) into a write-ahead log (WAL) file in the
wal_dir directory. A new WAL file is created for every
rows_per_wal records.
Each data change request gets assigned a continuously growing 64-bit log sequence
number. The name of the WAL file is based on the log sequence number of the first
record in the file, plus an extension .xlog.

Apart from a log sequence number and the data change request (formatted as in
Tarantool’s binary protocol),
each WAL record contains a header, some metadata, and then the data formatted
according to msgpack rules.
For example, this is what the WAL file looks like after the first INSERT request
(“s:insert({1})”) for the sandbox database created in our
“Getting started” exercises.
On the left are the hexadecimal bytes that you would see with:

Tarantool processes requests atomically: a change is either accepted and recorded
in the WAL, or discarded completely. Let’s clarify how this happens, using the
REPLACE request as an example:

The server instance attempts to locate the original tuple by primary key. If found, a
reference to the tuple is retained for later use.

The new tuple is validated. If for example it does not contain an indexed
field, or it has an indexed field whose type does not match the type
according to the index definition, the change is aborted.

The new tuple replaces the old tuple in all existing indexes.

A message is sent to the WAL writer running in a separate thread, requesting that
the change be recorded in the WAL. The instance switches to work on the next
request until the write is acknowledged.

On success, a confirmation is sent to the client. On failure, a rollback
procedure is begun. During the rollback procedure, the transaction processor
rolls back all changes to the database which occurred after the first failed
change, from latest to oldest, up to the first failed change. All rolled back
requests are aborted with ER_WAL_IO error. No new
change is applied while rollback is in progress. When the rollback procedure
is finished, the server restarts the processing pipeline.

One advantage of the described algorithm is that complete request pipelining is
achieved, even for requests on the same value of the primary key. As a result,
database performance doesn’t degrade even if all requests refer to the same
key in the same space.

The transaction processor thread communicates with the WAL writer thread using
asynchronous (yet reliable) messaging; the transaction processor thread, not
being blocked on WAL tasks, continues to handle requests quickly even at high
volumes of disk I/O. A response to a request is sent as soon as it is ready,
even if there were earlier incomplete requests on the same connection. In
particular, SELECT performance, even for SELECTs running on a connection packed
with UPDATEs and DELETEs, remains unaffected by disk load.

The WAL writer employs a number of durability modes, as defined in configuration
variable wal_mode. It is possible to turn the write-ahead
log completely off, by setting
wal_mode to none. Even
without the write-ahead log it’s still possible to take a persistent copy of the
entire data set with the box.snapshot() request.

An .xlog file always contains changes based on the primary key.
Even if the client requested an update or delete using
a secondary key, the record in the .xlog file will contain the primary key.

The format of a snapshot .snap file is nearly the same as the format of a WAL .xlog file.
However, the snapshot header differs: it contains the instance’s global unique identifier
and the snapshot file’s position in history, relative to earlier snapshot files.
Also, the content differs: an .xlog file may contain records for any data-change
requests (inserts, updates, upserts, and deletes), a .snap file may only contain records
of inserts to memtx spaces.

Primarily, the .snap file’s records are ordered by space id. Therefore the records of
system spaces – such as _schema, _space, _index, _func, _priv
and _cluster – will be at the start of the .snap file, before the records of
any spaces that were created by users.

Secondarily, the .snap file’s records are ordered by primary key within space id.