Transaction Overview

Transactions

MatrixOne supports bundling multiple SQL statements into a single all-or-nothing transaction. Each transaction guarantees ACID semantics spanning arbitrary tables and rows. If a transaction succeeds, all mutations are applied together with virtual simultaneity. If any part of a transaction fails, the entire transaction is aborted, and the database is left unchanged. MatrixOne guarantees that while a transaction is pending, it is isolated from other concurrent transactions with snapshot isolation.

In 0.5.1 version, MatrixOne supports standalone database transaction. MatrixOne supports optimistic transaction mode.

This document introduces commonly used transaction-related statements, explicit and implicit transactions, isolation levels, lazy check for constraints, and transaction sizes.

SQL statements

The following SQL statements control transactions:

  • START TRANSACTION or BEGIN start a new transaction.
  • COMMIT commits the current transaction, making its changes permanent.
  • ROLLBACK rolls back the current transaction, canceling its changes.
  • SET autocommit disables or enables the default autocommit mode for the current session. (It’s not fully implemented in 0.5.1 version, MatrixOne only supports autocommit mode enabled, it cannot be switched off yet).

Starting a transaction

The statements BEGIN and START TRANSACTION can be used interchangeably to explicitly start a new transaction.

Syntax:

  1. BEGIN;
  1. START TRANSACTION;

With START TRANSACTION or BEGIN , autocommit remains disabled until you end the transaction with COMMIT or ROLLBACK. The autocommit mode then reverts to its previous state. Unlike MySQL, START TRANSACTION in MatrixOne doesn’t have a modifier that control transaction characteristics.

Committing a transaction

The statement COMMIT instructs MatrixOne to apply all changes made in the current transaction.

Syntax:

  1. COMMIT;

Rolling back a transaction

The statement ROLLBACKrolls back and cancels all changes in the current transaction.

Syntax:

  1. ROLLBACK;

Transactions are also automatically rolled back if the client connection is aborted or closed.

Autocommit

By default, MatrixOne runs with autocommit mode enabled. This means that, when not otherwise inside a transaction, each statement is atomic, as if it were surrounded by START TRANSACTION and COMMIT. You cannot use ROLLBACK to undo the effect; however, if an error occurs during statement execution, the statement is rolled back.

For example:

  1. mysql> SELECT @@autocommit;
  2. +--------------+
  3. | @@autocommit |
  4. +--------------+
  5. | on |
  6. +--------------+
  7. 1 row in set (0.01 sec)
  8. mysql> create table test (c int primary key,d int);
  9. Query OK, 0 rows affected (0.03 sec)
  10. mysql> Insert into test values(1,1);
  11. Query OK, 1 row affected (0.04 sec)
  12. mysql> rollback;
  13. ERROR 1105 (HY000): the txn has not been began
  14. mysql> select * from test;
  15. +------+------+
  16. | c | d |
  17. +------+------+
  18. | 1 | 1 |
  19. +------+------+
  20. 1 row in set (0.01 sec)

In the above example, the ROLLBACK statement has no effect. This is because the INSERT statement is executed in autocommit. ROLLBACK only works with a BEGIN or START TRANSACTION. That is, it was the equivalent of the following single-statement transaction:

  1. START TRANSACTION;
  2. Insert into test values(1,1);
  3. COMMIT;

Autocommit will not apply if a transaction has been explicitly started. In the following example, the ROLLBACK statement successfully reverts the INSERT statement:

  1. mysql> SELECT @@autocommit;
  2. +--------------+
  3. | @@autocommit |
  4. +--------------+
  5. | on |
  6. +--------------+
  7. 1 row in set (0.01 sec)
  8. mysql> create table test (c int primary key,d int);
  9. Query OK, 0 rows affected (0.03 sec)
  10. mysql> BEGIN;
  11. Query OK, 0 rows affected (0.00 sec)
  12. mysql> Insert into test values(1,1);
  13. Query OK, 1 row affected (0.01 sec)
  14. mysql> ROLLBACK;
  15. Query OK, 0 rows affected (0.03 sec)
  16. mysql> SELECT * from test;
  17. Empty set (0.01 sec)

The autocommit system variable cannot be changed on either a global nor session basis for now.

Explicit and implicit transaction

MatrixOne supports explicit transactions (use [BEGIN|START TRANSACTION] and COMMIT to define the start and end of the transaction) and implicit transactions (by default).

If you start a new transaction through the [BEGIN|START TRANSACTION] statement, the autocommit is disabled before COMMIT or ROLLBACK which makes the transaction becomes explicit.

Statement rollback

MatrixOne supports atomic rollback after statement execution failure. If a statement results in an error, the changes it made will not take effect. The transaction will remain open, and additional changes can be made before issuing a COMMIT or ROLLBACK statement.

  1. mysql> CREATE TABLE t1 (id INT NOT NULL PRIMARY KEY);
  2. Query OK, 0 rows affected (0.04 sec)
  3. mysql> INSERT INTO t1 VALUES (1);
  4. Query OK, 1 row affected (0.16 sec)
  5. mysql> BEGIN;
  6. Query OK, 0 rows affected (0.00 sec)
  7. mysql> INSERT INTO t1 VALUES (1);
  8. ERROR 1105 (HY000): tae data: duplicate
  9. mysql> INSERT INTO t1 VALUES (2);
  10. Query OK, 1 row affected (0.03 sec)
  11. mysql> INSERT INTO t1_1 VALUES (3);
  12. ERROR 1105 (HY000): tae catalog: not found
  13. mysql> INSERT INTO t1 VALUES (3);
  14. Query OK, 1 row affected (0.00 sec)
  15. mysql> commit;
  16. Query OK, 0 rows affected (0.03 sec)
  17. mysql> select * from t1;
  18. +------+
  19. | id |
  20. +------+
  21. | 1 |
  22. | 2 |
  23. | 3 |
  24. +------+
  25. 3 rows in set (0.02 sec)

In the above example, the transaction remains open after the failed INSERT statements. The final insert statement is then successful and changes are committed.

Snapshot Isolation Level

Transaction isolation is one of the foundations of database transaction processing. Isolation is one of the four key properties of a transaction (commonly referred as ACID).

The SQL-92 standard defines four levels of transaction isolation: Read Uncommitted, Read Committed, Repeatable Read, and Serializable. See the following table for details:

Isolation LevelDirty WriteDirty ReadFuzzy ReadPhantom
READ UNCOMMITTEDNot PossiblePossiblePossiblePossible
READ COMMITTEDNot PossibleNot possiblePossiblePossible
REPEATABLE READNot PossibleNot possibleNot possiblePossible
SERIALIZABLENot PossibleNot possibleNot possibleNot possible

MatrixOne implements Snapshot Isolation (SI) consistency, this level of isolation is between REPEATABLE READ and SERIALIZABLE for SQL-92 standard.

In a snapshot isolated system, each transaction appears to operate on an independent, consistent snapshot of the database. Its changes are visible only to that transaction until commit time, when all changes become visible atomically to any transaction which begins at a later time.If transaction T1 has modified an object x, and another transaction T2 committed a write to x after T1’s snapshot began, and before T1’s commit, then T1 must abort.

If we look at the isolation levels with the possible anomalies allowed proposed by A Critique of ANSI SQL Isolation Levels, we can conclude MatrixOne’s isolation level with such a following table, which is slightly different with the Snapshot Isolation in the article.

Isolation LevelP0 Dirty WriteP1 Dirty ReadP4C Cursor Lost UpdateP4 Lost UpdateP2 Fuzzy ReadP3 PhantomA5A Read SkewA5B Write Skew
MatrixOne’s Snapshot IsolationNot PossibleNot PossibleNot PossibleNot PossibleNot PossibleNot PossibleNot PossiblePossible

Optimistic Transaction Model

MatrixOne supports an optimistic transaction model. Users who use optimistic concurrency do not lock a row when reading it. When a user wants to update a row, the application must determine whether another user has changed the row since it was read. Optimistic concurrency is generally used in environments with a low contention for data.

In an optimistic concurrency model, a violation is considered to have occurred if, after a user receives a value from the database, another user modifies the value before the first user has attempted to modify it. How the server resolves a concurrency violation is best shown by first describing the following example.

The following tables follow an example of optimistic concurrency.

At 1:00 p.m., User1 reads a row from the database with the following values:

CustID LastName FirstName

101 Smith Bob

Column nameOriginal valueCurrent valueValue in database
CustID101101101
LastNameSmithSmithSmith
FirstNameBobBobBob

At 1:01 p.m., User2 reads the same row.

At 1:03 p.m., User2 changes FirstName from “Bob” to “Robert” and updates the database.

Column nameOriginal valueCurrent valueValue in database
CustID101101101
LastNameSmithSmithSmith
FirstNameBobRobertBob

The update succeeds because the values in the database at the time of update match the original values that User2 has.

At 1:05 p.m., User1 changes “Bob”‘s first name to “James” and tries to update the row.

Column nameOriginal valueCurrent valueValue in database
CustID101101101
LastNameSmithSmithSmith
FirstNameBobJamesRobert

At this point, User1 encounters an optimistic concurrency violation because the value in the database (“Robert”) no longer matches the original value that User1 was expecting (“Bob”). The concurrency violation simply lets you know that the update failed. The decision now needs to be made whether to overwrite the changes supplied by User2 with the changes supplied by User1, or to cancel the changes by User1.