Introduction
Multi version concurrency control (MVCC) is a popular optimistic technique used in modern databases for concurrency control.
MVCC does not use locking. In that regard it is an optimistic technique but distinct from what is know as the optimistic concurrency control (OCC).
MVCC is timestamp based.
MVCC does its concurrency control by keeping multiple copies or versions of each data item. Every transaction sees data only of a specific version , also known as snapshot. Changes made by a transaction will not be seen by others, until the changes are committed.
Concepts
Versioning
Versioning tuples is at the core of how MVCC does its concurrency control.
Consider the table
id, balance
A, 500
B, 1000
Now logically assume that under the hood, the database adds 2 hidden columns - start time (st) and end time (et)
id, balance, st. , et
A, 500 , 1 , -
B, 1000, 2, -
Let us assume that increasing numbers 1,2 ..... represent time and a - implies infinity or no end time. The version number can be a timestamp or something analogous to a timestamp.
In the above example, we are saying that the first tuple (A, 500) is valid from time 1 to infinity. The second tuple (B, 1000) is valid from 2 to infinity.
With versioning, when a tuple is updated, the original one is unchanged. Instead a new row is added.
Let us say at time 3, A is updated to 550. Logically the table would look like
A, 500 , 1 , 3
A, 550 , 3 , -
B, 1000, 2, -
The latest committed version has an end time of infinity. When a new update for a tuple is committed, the end timestamp of the previous latest is changed to the start timestamp of the new latest.
A transaction reads the latest committed version at the time it starts. A transaction that starts at time 2 and reads A will read 500. But a transaction that starts at 4 and reads A will read 550.
Snapshot isolation
Every transaction only reads committed values at the time it starts. It is a snapshot of the database at that time. This referred to as Snapshot isolation.
However it will read any changes that it makes within the scope of its transaction.
Use cases
Lost update problem
id, balance, st. , et
A, 500 , 1 , -
Write Skew
A, 500 , 1 , -
B, 1000, 2, -
A, 500 , 1 , -,
A, 600 , 3 , - , uncommitted
B, 1000, 2, -
At time 4, transaction T2 reads A. The latest committed record is still at timestamp 1. It will read 500 ( not 600 ).
At time 5, T1 commits. The write set to T1 does not intersect with the write set of any other transaction. So it allowed to commit. So we have
A, 500 , 1 , 5,
A, 600 , 5 , - ,
B, 1000, 2, -,
At time 6, T2 updates B to 1200
B, 1200, 6, -, uncommitted
At time 7, T2 tries to commit. It is disallowed and T2 is forced to abort. The reason is that T2 read A which was committed after T2 started. Even though T2 does not update A. It might be using A (that is read earlier) to update say B and that update could be incorrect.This is the write skew problem.
We can thus deduce rule 2: The read set of a committing transaction T should not intersect with the write set of any transaction that has committed after T started.
Phantom reads
id, balance, st. , et
A, 500 , 1 , -
B, 1000, 2, -
At time 3 , transaction T1 runs the query "select sum(balance) from table where balance >=500 ". It gets a result 1500.
At time 4, transaction T2 inserts a new row, (C, 600) and commits
id, balance, st. , et
A, 500 , 1 , -
B, 1000, 2, -
C, 600, 4 , -
At time 5, transaction T1 inserts the 1500 value it read into another table.
At time 6, T1 tries to commit. The transaction is not allowed to proceed and aborts.
The reason is that the 1500 value is no longer accurate. At time 4 , another transaction committed a new row and the value should be 2100.
Rule 3 : If the committing transaction T has predicate queries (where clause ) that depend to number of rows and affected by inserts/deletes, then just before committing the queries need to be run again. The commit is allowed only if the results are the same as before.
Obviously running the queries a second time can be expensive. But that is implementation detail and databases do various optimization.
Garbage collection
Maintaining versions for each and every record can take up a lot of disk space. Databases have background process or other method to remove old versions that have no active transaction depending on them.
Algorithm
#1 : Write set of a committing transaction T should not intersect with Write set of any committed transaction that committed after T started.
#4 Write set of a committing transaction T should not intersect with Read set of any transaction that committed after T started.
Commercial Databases supporting MVCC
PostgreSql
Advantages of MVCC
- Readers do not block readers. Writers do not block readers.
- Each transaction works under a consistent snapshot of data.
- High concurrency is possible.
- Databases can allow querying of old versions, which are known as time travel queries.
Disadvantages of MVCC
- Increased storage requirement because we are storing older version.
- Need to do garbage collection.
- When conflicts are detect and transactions aborted, applications need to retry.
No comments:
Post a Comment