mysql(InnoDB)事務隔離級別(REPEATABLE READ) 與 鎖,MVCC

weixin_33840661發表於2018-01-01

REPEATABLE READ

(可重複讀)

  1. 之前已經瞭解到, 該隔離級別可以解決不可重複讀問題 (當然, 也能解決髒讀問題), 那麼如果單純用鎖來實現, 可能會是如下這樣子:

    • 既然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, 都是一樣的。
  2. 上面使用S鎖+X鎖確實可以實現 READ COMMITTED 隔離級別的效果, 也就避免了髒讀問題不可重複讀問題, 當然, 這裡的問題仍然是低效!!!!

  3. 因為 MySQL 在事務隔離級別Read committed 、Repeatable Read下,InnoDB 儲存引擎採用非鎖定一致性讀--即讀取資料不用加鎖,即採用的是MVCC中一致性非鎖定讀模式, 所以, InnoDB的做法是: 讀不影響寫,寫不影響讀

    • 讀不影響寫: 當資料正在執行讀操作時,其他事務的寫操作不會因此去等待當前事務行上S鎖的釋放,而是會去讀取行的一個快照資料。
    • 寫不影響讀:當資料正在執行寫操作時,其他事務的讀操作不會因此去等待當前事務行上X鎖的釋放,而是會去讀取行的一個快照資料。
  4. 所以總結來看, READ UNCOMMITTEDREPEATABLE READ 這兩個隔離級別都是使用 寫用排他鎖 + 讀用MVCC, 區別可以參考 MySQL-InnoDB-MVCC多版本併發控制

相關文章