# Distributed Transactions (Continued...)

![left](./student-guide/diagram/PercolatorTiKV03_aa_001_20220511.png)

------------------------------------------------------------
Let's say we want to complete the following transaction:
```
Begin
 < 1,Tom > -> < 1,Jack >
< 2,Andy > -> < 2, Candy > 
Commit;
```

Note: Assume that key = 1 and key = 2 are on different TiKV regions.

First, at the beginning of the transaction, we get a StartTS from PD. Assuming 100, we enter the first stage of Percolator, PreWrite. At this time, since there is no commit, we need to write the two column family (CF) Lock and Default. As you can see from the figure, we are writing When entering Default, we added a timestamp (startTS) to the key, and the values of the two modify Lock column family (CF) are not quite the same, mainly including lock type and startTS.

The figure below:

```
+****************************************************************************+
|                                              Key = 1                       |
+***********************+*********************************+******************+
|   Default CF      |            Lock CF             ｜      Write CF         |
+***********************+*******+**************************+*******+*********+
|   key  |  value   |  key |       value             |   key   |   value     |
+***********************+*******+********************************************+
| 1_100  |   Jack   |   1  |  W, primary key,100...  |         |             |
+***********************+*******+**************************+*****************+

+****************************************************************************+
|                                              Key = 2                       |
+***********************+*********************************+******************+
|        Default CF          |               Lock CF        ｜   Write CF     |
+***********************+*******+**************************+*******+********+
|   key        |  value      |    key  |         value      |   key |  value |
+***********************+*******+********************************************+
|   2_100      |   Candy     |     2   |  W, @key = 1,00... |       |        |
+***********************+*******+**************************+*****************+
```

(W: write, D: delete)

There is an important point here, that is, modify key = 1 and key = 2 in the transaction. In the Lock column family (CF), we only use the first modify, that is, key = 1 as the primary key, and the lock with key = 2 points to key = 1. (that is, the value in the Lock column family (CF))

At the same time, we also noticed that the Default column family (CF), whether data is modify or deleted, is a new insertion key-value pair, rather than modify or deleting the stored data. This will be explained later in the introduction of MVCC technology.

Second, let's go to the second stage Commit of Percolator. At this time, we will get a commitTs from PD, assuming 110, and then it will be written in the Write column family (CF), key plus timestamp (commit_ts), and value is the startTs of this transaction. , The primary key was deleted in the Lock column family (CF) record.

The figure below:


```
+************************************************************************************+
|                                              Key = 1                               |
+***********************+*********************************+**************************+
|        Default CF         |               Lock CF              ｜     Write CF     |
+***********************+*******+**************************+*******+*****************+
|   key       |  value      |    key  |         value            |   key   |   value |
+***********************+*******+****************************************************+
| 1_100       |   Jack      |     1   |  W, primary key,100...   |         |         |
+***********************+*******+**************************+*************************+
|             |             |     1   |  D,  primary key,100...  |         |         |
+***********************+*******+**************************+*************************+

+**************************************************************************************+
|                                              Key = 2                                 |
+***********************+*********************************+****************************+
|        Default CF         |               Lock CF          ｜           Write CF      |
+***********************+*******+**************************+*******+*******************+
|   key        |  value     |    key  |        value         |   key   |   value       |
+***********************+*******+******************************************************+
| 2_100        |   Candy    |     2   |  W, @key = 1,00...   |         |               |
+***********************+*******+**************************+***************************+
|              |            |     2   |  D,  @key = 1,00...  |  2_110  | start_ts=100  |
+***********************+*******+**************************+***************************+
```

(W: write, D: delete)

After the Commit phase is complete, when we want to read the data, we will find out whether key = 1 or key = 2, we only need to find if there is a lock in the corresponding lock CF. If there is no lock or the lock is deleted (marked D), we can read it, otherwise the read will fail.

Finally, we found that during the commit phase of Percolator, we only had to delete a primary key with key = 1, because Lock CF with key = 2 stores a pointer to the primary key with key = 1. Suppose, if at the commit stage, only key = 1 is deleted due to an error, and there is no time to delete key = 2. After recover, when key = 2 is read, it is found that there is a lock in Lock CF (not deleted due to an error) pointing to key = 1, and the lock corresponding to key = 1 has been deleted, we I know that there was no time to update (delete) the lock with key = 2 before the error, but the transaction was actually committed successfully. As a result, the problem of distributed transaction mentioned earlier is solved.

We have only briefly introduced the Percolator model here. The actual implement will be complicated, and we have omitted some details. If you want to know more about it, you can refer to the Distributed Transactions course.