REPEATABLE READ
(可重複讀)
-
之前已經瞭解到, 該隔離級別可以解決
不可重複讀問題
(當然, 也能解決髒讀問題
), 那麼如果單純用鎖來實現, 可能會是如下這樣子:- 既然
REPEATABLE READ
隔離級別可以解決髒讀
,不可重複讀
的問題, 也就是它既可以讓事務只能讀其他事務已提交的的記錄, 又能在同一事務中保證多次讀取的資料即使被其他事務修改, 也是一致的。 - 解決
髒讀問題
:
試想一下, 當在事務A中讀取資料D的時候, 假設D之前已經在事務B中了, 並且事務B中對資料D做了修改, 但是事務B還沒有完成(commit/rollback), 那如何讓事務A無法讀取資料D呢?
當事務B在對資料D做寫操作的時候, 假設給資料D加上了行級的排他鎖(X lock), 那事務A自然只能阻塞等事務A完成後才能讀取資料D了, 這樣就解決了髒讀問題
。 - 解決
不可重複讀問題
:
試想一下, 當在事務A中第一次讀取了資料D之後, 直接給該資料D加S共享鎖, 那其他事務自然只能阻塞等事務A完成後才能對資料D做修改操作了, 這樣就解決了不可重複讀
, 在事務A中多次讀取資料D, 都是一樣的。
- 既然
上面使用
S鎖+X鎖
確實可以實現READ COMMITTED
隔離級別的效果, 也就避免了髒讀問題
和不可重複讀問題
, 當然, 這裡的問題仍然是低效!!!!-
因為 MySQL 在事務隔離級別Read committed 、Repeatable Read下,InnoDB 儲存引擎採用
非鎖定
的一致性讀
--即讀取資料不用加鎖,即採用的是MVCC中一致性非鎖定讀
模式, 所以, InnoDB的做法是: 讀不影響寫,寫不影響讀。- 讀不影響寫: 當資料正在執行讀操作時,其他事務的寫操作不會因此去等待當前事務行上S鎖的釋放,而是會去讀取行的一個快照資料。
- 寫不影響讀:當資料正在執行寫操作時,其他事務的讀操作不會因此去等待當前事務行上X鎖的釋放,而是會去讀取行的一個快照資料。
- 所以總結來看,
READ UNCOMMITTED
和REPEATABLE READ
這兩個隔離級別都是使用寫用排他鎖 + 讀用MVCC
, 區別可以參考 MySQL-InnoDB-MVCC多版本併發控制