概念
Repeatable Read(可重復讀):即:事務A在讀到一條數據之后,此時事務B對該數據進行了修改並提交,那么事務A再讀該數據,讀到的還是原來的內容。
實現原理(MVCC [ 多版本並發控制 ])
InnoDB在每行記錄后面保存兩個隱藏的列來,分別保存了這個行的創建時間和行的刪除時間。這里存儲的並不是實際的時間值,而是系統版本號,當數據被修改時,版本號加1
在讀取事務開始時,系統會給當前讀事務一個版本號,事務會讀取版本號<=當前版本號的數據
此時如果其他寫事務修改了這條數據,那么這條數據的版本號就會加1,從而比當前讀事務的版本號高,讀事務自然而然的就讀不到更新后的數據了
現在通過實驗,對問題進行下分析:
1.在終端A開啟事務A,查詢一下。
START TRANSACTION; select spt.id,spt.audit_status,spt.is_deleted from stat_point_task spt limit 5;
結果如下:
2.在終端B開啟事務B,進行同樣的查詢,可見結果和事務A中的結果是一樣的。
START TRANSACTION; select spt.id,spt.audit_status,spt.is_deleted from stat_point_task spt limit 5;
3. 在事務A中,更新一下,將id=3的audit_status更新為3,查詢一下,發現更新成功,然后提交事務A;
update stat_point_task set audit_status=3,is_deleted=0 where id=3; select spt.id,spt.audit_status,spt.is_deleted from stat_point_task spt limit 5; commit;
4. 此時,事務A更新了數據,並進行了提交,返回來再看事務B,在事務B中進行查詢,發現查詢到的還是事務A更新之前的數據。
/*再查詢下,因為可重復讀,發現查詢到的還是事務A更新之前的數據*/ select spt.id,spt.audit_status,spt.is_deleted from stat_point_task spt limit 5;
上面我們對MySQL的默認隔離級別可重復讀通過進行實驗進行了解釋,但是,此時我有一個問題,就是事務B在進行更新的時候,是在事務A更新后的基礎上更新,還是A更新前(和B通過查詢得到的數據保持一致)的基礎上更新,下面通過實驗來分析這個問題。
5.在事務B中更新數據,假設A的更新影響到事務B,在事務A的查詢結果中id=3的這條數據對應的audit_status為3,在事務B中的這條語句影響的行數應該為0,不會將audit_status設為4。
update stat_point_task set audit_status=4 where id=3 and audit_status=1; select spt.id,spt.audit_status,spt.is_deleted from stat_point_task spt limit 5;
我們通過下面的語句再次驗證下 ‘對事務B進行更新時,事務A提交的更新影響到了事務B’ ,此時事務A中提交的更新已經將id=3的audit_status更新為3,雖然因為可重復讀,事務B中查詢到的id=3的audit_status為1,但是在事務B中進行如下的更新的時候,卻更新成功了,成功將audit_status更新為5.
update stat_point_task set audit_status=5 where id=3 and audit_status=3; select spt.id,spt.audit_status,spt.is_deleted from stat_point_task spt limit 5; /*最后記得提交B事務*/ commit;
綜上:
因為MySQL的可重復讀,對事務B進行查詢時,事務A提交的更新不會影響到事務B。
但是對事務B進行更新時,事務A提交的更新會影響到事務B。
出處:https://www.cnblogs.com/Allen-win/p/8283102.html