# Mvcc
__*MVCC*__
```13
- Transaction 1:
  Begin（start_ts = 100）
    < 1,Tom > -> < 1,Jack >
    < 2,Andy > -> < 2, Candy > 
  Commit;（commit_ts = 110）

- Transaction 2:
  Begin（start_ts = 115）
    < 1,Jack > -> < 1,Tim >
    < 4,Tony > -> < 4, Jerry > 
```

------------------------------------------------------------
From the implement of distributed transactions, we have learned that if a row of data is in a transaction (uncommitted), then reading it return an error. In other words, writes not only block writes, but also read. Although there is no problem in theory, for systems with high concurrency, if a row of data is in a transaction, then the operation on that row of data will immediately become serial, which is very inefficient.

The solution to the method problem is called multi-version concurrency control (multi-version concurrency control, hereinafter referred to as MVCC). Databases such as Oracle, MySQL, and PostgreSQL also use this method. Let's take a look at how TiKV uses MVCC.

In MVCC technology, whenever you want to change or delete a data object, the database does not delete or modify the existing data object itself, but creates a new version of the data object. In this way, concurrent read operations can still read the old version of data, and write operations can be performed at the same time. The advantage of this mode is that reads are no longer blocked, and in fact there is no need for a lock at all. 

In the Distributed Transaction section, we have seen that TiKV actually only adds (PUT, DELETE) to modify or delete data, instead of modify or deleting the original data. So, in TiKV we have data from previous versions, so the next question is how to find the right version of data.

Let's assume a scenario:

There are currently 2 transactions, transaction 1 has committed, with start_ts of 100 and commit_ts of 110; transaction 2 has started, but has not committed, and its start_ts is 105.

transaction 1:

```
Begin（start_ts = 100）
 < 1,Tom > -> < 1,Jack >
< 2,Andy > -> < 2, Candy > 
Commit;（commit_ts = 110）
```

transaction 2:

```
Begin（start_ts = 115）
 < 1,Jack > -> < 1,Tim >
< 4,Tony > -> < 4, Jerry >
```

At this point, when the TSO is 120, we start a query to query the values of key = 1, key = 2, and key = 4. According to common sense, if there is no MVCC mechanism, then key = 1 and key = 4 will return an error or be blocked because they are in transaction 2, and key = 2 can query the result, value = Candy, because transaction 1 is already completed.

However, if there is an MVCC mechanism, we know that a read with a TSO of 120 can not only be read out < 2, Candy >, but also read the < 1,Jack > sum < 4,Tony >, because transaction 1 is not committed, we can read the value before the commit.