1. 程式人生 > >從MySQL預設事務隔離級別(RR)到InnoDB非鎖定一致性讀

從MySQL預設事務隔離級別(RR)到InnoDB非鎖定一致性讀

說到資料庫的隔離級別,我想大家都能說出一二,但是很多時候都是從網上看來的,很多都點到為止不夠詳細,並且沒有經過實踐的檢驗,所以有時候我們會發現有些東西並沒有按照我們預期的來工作,這裡就是一個例子。

MySQL目前流行的版本預設的事務隔離級別一般是可重複讀,一般我們理解在這個隔離級別下,我們新建兩個事務A和事務B,事務A的修改是不影響事務B的,也就是說A事務修改資料後,B事務讀到的資料是不變的,也就是可重複讀,同時在next-key鎖的作用下,又解決了幻讀。不過這裡有一個問題就是B事務讀到的資料是什麼時候的資料?這句話隱藏著一個操作,就是在事務A提交前,事務B已經進行過一次查詢,否則,事務B會讀取最新的資料,因為事務是在begin後第一次select等操作時才開啟的。文字描述的可能不太好理解,所以,直接通過操作的截圖來理解這一過程。

首先是兩個場景

+------+------+------+------+
| id   | name | addr | fk   |
+------+------+------+------+
|    2 | ss1  | 111  |    2 |
|    5 | ss2  | 111  |    3 |
|    6 | ss3  | 111  |    4 |
|  999 | ss4  | 111  |    5 |
| 1000 | ss5  | 111  |    6 |
| 1008 | ssx  | 111  |  100 |
| 1014 | xx   | 111  |    7 |
| 1015 | xx   | 111  |    8 |
| 1012 | xx   | 111  |  101 |
| 1013 | xx   | 111  |  101 |
|  888 | xxx  | 111  |    7 |
|    1 | yy   | 111  |    9 |

+------+------+------+------+

圖1中左邊事務A,右邊事務B,在此情況下,我們稱事務B是可重複讀的,因為兩次讀的結果是一樣的,注意事務B讀取的值是事務A修改後的值。

                                                                        圖1

那我們再來看一下圖2,在已經執行begin的前提下,事務B讀到的是事務A修改後的值。


                                                                          圖2

這是為什麼呢?按照我們通常的理解,事務A的提交應該對事務B沒有影響才對,怕不是我們對可重複有什麼誤解?

先來看這樣一個操作,查詢當前事務的trx_id

SELECT TRX_ID FROM INFORMATION_SCHEMA.INNODB_TRX  WHERE TRX_MYSQL_THREAD_ID = CONNECTION_ID();
那麼我們來嘗試一下

可以看到,在執行begin後並沒有生成TRX_ID,也就是說此時事務還沒有開始,根據此篇文章http://www.cnblogs.com/su-han/p/begin.html的說法,只有在執行了select或者以start transaction with consistent snapshot開始事務,才能夠正式開啟事務。這個過程涉及到了非鎖定一致性讀,也就是在事務第一次讀取的時候生成了一個快照,在RR隔離級別下,該快照是事務開始時的資料,也即是產生了TRX_ID之後。更多關於非鎖定一致性讀和鎖定一致性讀可參考https://www.linuxidc.com/Linux/2017-08/146216.htm

參考文獻:[1] https://www.cnblogs.com/Mr-Dawei/p/7460909.html?utm_source=debugrun&utm_medium=referral

               [2] http://www.cnblogs.com/su-han/p/begin.html

               [3] https://blog.csdn.net/skiof007/article/details/53376751

               [4] https://blog.csdn.net/zyz511919766/article/details/49451255

               [5] https://www.linuxidc.com/Linux/2017-08/146216.htm