可重復讀的實現
Repeatable Read(可重復讀):一個事務在執行過程中可以看到其他事務已經提交的新插入的記錄(讀已經提交的,其實是讀早於本事務開始且已經提交的),但是不能看到其他事務對已有記錄的更新(即晚於本事務開始的),並且,該事務不要求與其他事務是“可串行化”的。
這句話的核心,是“但是不能看到其他事務對已有記錄的更新”,那么RR隔離級別是怎么保證這一點的呢?使用MVCC(多版本並發控制)。InnoDB為每行記錄添加了一個版本號(系統版本號),每當修改數據時,版本號加一。
在讀取事務開始時,系統會給事務一個當前版本號,事務會讀取版本號<=當前版本號的數據,這時就算另一個事務插入一個數據,並立馬提交,新插入這條數據的版本號會比讀取事務的版本號高,因此讀取事務讀的數據還是不會變。
如果數據庫並發控制引擎是單純的封鎖協議機制,則應該在讀取數據的時候,判斷數據項是不是其他事務更新過的。可是InnoDB沒有這么做,而是通過如下方式,在RR隔離級別下為事務設置了一個“一致性讀視圖(即快照)”,之后讀取數據,就是根據這個快照來獲取,這樣,就不能看到他晚於本事務的事務對已有記錄的更新(更新生成新版本,必然不在舊的快照所限定的范圍內)。(也就是基於快照讀,而不是當前讀來實現的)
總結:可重復讀就是在讀事務里面,兩次讀取數據的時候(同一條記錄)是相同的,在兩次讀取數據的時候,其他線程可能修改了數據,但是第二次讀取數據的時候還是讀取的老的數據,其實mysql也就是通過MVCC機制來保證可重復讀。