Optimistic Concurrency Control

Table of Contents

Introduction

Even though CrateDB does not support transactions, Optimistic Concurrency Control can be achieved by using the internal system column _version.

Every new row has an initial version of 1. This value is increased by 1 on every update.

It’s possible to fetch the _version by selecting it:

  1. cr> select name, id, "_version" from locations
  2. ... where kind = 'Star System' order by name asc;
  3. +----------------+----+----------+
  4. | name | id | _version |
  5. +----------------+----+----------+
  6. | Aldebaran | 4 | 3 |
  7. | Algol | 5 | 3 |
  8. | Alpha Centauri | 6 | 3 |
  9. | Altair | 7 | 1 |
  10. +----------------+----+----------+
  11. SELECT 4 rows in set (... sec)

These _version values can now be used on updates and deletes.

Note

Optimistic concurrency control only works using the = operator, checking for the exact _version your update/delete is based on.

Optimistic Update

Querying for the correct _version ensures that no concurrent update has taken place:

  1. cr> update locations set description = 'Updated description'
  2. ... where id=5 and "_version" = 3;
  3. UPDATE OK, 1 row affected (... sec)

Updating a row with a wrong or outdated version number will not execute the update and results in 0 affected rows:

  1. cr> update locations set description = 'Updated description'
  2. ... where id=5 and "_version" = 2;
  3. UPDATE OK, 0 rows affected (... sec)

Optimistic Delete

Of course the same can be done when deleting a row:

  1. cr> delete from locations where id = '6' and "_version" = 3;
  2. DELETE OK, 1 row affected (... sec)

Known Limitations

  • The _version column can only be used when specifying the whole primary key in a query. For example, the query below is not possible with our used testing data because name is not declared as a primary key and results in an error:

    1. cr> delete from locations where name = 'Aldebaran' and "_version" = 3;
    2. SQLActionException... "_version" column can only be used in the WHERE ...

Note

Both, DELETE and UPDATE, commands will return a row count of 0 if the given required version does not match the actual version of the relevant row.