Mysql MVCC

思考一個問題

MVCC是什麼

MVCC: Multiversion concurrency control (多版本併發控制)
解釋:併發訪問(讀或寫)數據庫時,對正在事務內處理的數據做多版本的管理,以達到用來避免寫操作的堵塞,從而引發讀操作的併發問題。

  • MVCC邏輯流程-插入

    假如一張表user有三個字段id,name,age,MySQL會默認的給每行後面加上一些隱藏的列,跟mvcc相關的有兩列:DB_TRX_ID(數據行的版本號:本行數據入庫時的版本號),DB_ROLL_PT(刪除版本號)。這兩列的值怎麼來呢?開啓一個事務(整個InnoDB的引擎有一個事務管理的地方,即全局事務id,自增型的),給表中插入兩條數據,此時數據行的版本號就是全局事務id。

  • MVCC邏輯流程-刪除

    假如當前進行了很多次的事務操作,要刪除其中一條數據,MySQL就會找到要刪除的這條數據,並把它的刪除版本號記錄爲當前的事務id號。

  • mysql中MVCC邏輯流程-修改

    先將命中行的數據行copy一份到新的數據行,新的數據行的版本號是當前事務的id,將原行數據的刪除版本號的值設置爲當前事務的id。

  • MVCC邏輯流程-查詢

    要同時滿足兩條規則:
    (1) 是查找數據行版本號早於當前事務版本的數據行,即行的系統版本號小於等於當前事務的系統版本號,這樣可以確保事務讀取的行,要麼是在事務開始前已經存在的,要麼是事務自身插入或者修改過的
    (2) 查找刪除版本號要麼是Null,要麼大於當前事務版本號的記錄,確保取出來的行記錄在事務開啓之前沒有被刪除。

    解決不可重複讀問題的不是mvcc,而是undo log和redo log。

mvcc版本控制案例

  • 數據準備
  • mvcc版本控制案例一
  • mvcc版本控制案例二
  • 結論
    事務能夠看到比自己ID號小的事務搞出來的數據結果,而無法感知到比自己ID號大的事務幹了啥

Undo log

  • undo log 原理解析
    (1) Undo Log 是什麼: undo意爲取消,以撤銷操作爲目的,返回指定某個狀態的操作 undo log指事務開始之前,在操作任何數據之前,首先將需操作的數據備份到一個地方 (Undo Log)
    (2) Undo Log是爲了實現事務的原子性而出現的產物
    (3) Undo Log實現事務原子性: 事務處理過程中如果出現了錯誤或者用戶執行了 ROLLBACK語句,Mysql可以利用Undo Log中的備份將數據恢復到事物開始之前的狀態
    (4) Undo Log在Mysql innodb存儲引擎中用來實現多版本併發控制
    (5) Undo log實現多版本併發控制: 事務未提交之前,Undo保存了未提交之前的版本數據,Undo 中的數據可作爲數據舊版本快照供其他併發事務進行快照讀
    (6) IBD文件存放在磁盤中,undo放在磁盤的表空間裏面,MySQL把磁盤中的數據加載到緩衝區裏面,我們要操作的數據全部在緩存區裏面,操作完以後,MySQL可以通過一些策略將緩衝區裏面的數據持久化到ibd文件裏面去。undo buffer可以通過一定的策略定時的寫到undo log裏面去。

    undo log的工作原理:把buffer區的數據先備份。一旦事務提交了,undo在這裏就沒有意義了。

  • 當前讀,快照讀

    • 快照讀
      SQL讀取的數據是快照版本,也就是歷史版本,普通的SELECT就是快照讀 innodb快照
    • 當前讀
      SQL讀取的數據是最新版本。通過鎖機制來保證讀取的數據無法通過其他事務進行修改 UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE都是當前讀
  • 總結
    (1) 在整個InnoDB引擎裏面,通過快照讀的mvcc解決不可重複讀問題,通過當前讀的next-key(臨鍵鎖)解決幻讀問題。
    (2) 如果在寫數據的時候,不讓其他人去讀,那麼併發性能會受到影響。如果完全按照mvcc的方式的話,讀取的數據有可能和預期的結果不一致。
    (3) update的時候上了X鎖,就會把數據拷貝到undo log裏面, select的時候讀快照,快照就是通過讀Undo日誌返回數據。

Redo log

  • redo log原理解析
    (1) Redo Log 是什麼: Redo,顧名思義就是重做。以恢復操作爲目的,重現操作; Redo log指事務中操作的任何數據,將最新的數據備份到一個地方 (Redo Log)
    (2) Redo log的持久: 不是隨着事務的提交才寫入的,而是在事務的執行過程中,便開始寫入redo 中。具體的落盤策略可以進行配置
    (3) RedoLog是爲了實現事務的持久性而出現的產物
    (4) Redo Log實現事務持久性: 防止在發生故障的時間點,尚有髒頁未寫入磁盤,在重啓mysql服務的時候,根據redo log進行重做,從而達到事務的未入磁盤數據進行持久化這一特性。
    (5) 圖例

    如果teacher.ibd有一個Update的操作加載到cache裏面,update之後,沒有提交,此時會立刻把這個數據更新到redo buffer裏面,按照一定的策略寫到redo log裏面,(cache裏面的數據相當於數據表在內存中的映射,每次提交的時候並不是把所有的數據都能刷到硬盤上,這樣的話在commit的時候效率就會很低,因爲要做很多次隨機的io(redo buffer->log是順序IO,log->ibd是隨機IO,但是已經不影響效率了。)。

    每次cache裏面的數據做了更新後,就會迅速更新到redo buffer裏面,只要把redo buffer裏面的數據寫到了redo log裏面,MySQL引擎就會認爲此次事務提交成功了(持久化了),不會在乎髒頁有沒有刷到磁盤,髒頁刷到磁盤的動作是在後臺慢慢做的,(如果通過隨機IO直接把數據包括髒頁持久化到磁盤了,那麼redo也就沒有意義了,)但是數據並不一定已經刷到了磁盤裏面。

    如果發生斷電事故,只要redo buffer的數據寫到了redo log裏面,當再次重啓的時候,MySQL會基於redo log日誌進行數據的重做,會把提交過的數據全部恢復到teacher.ibd文件裏面)。

  • Redo log補充知識點(參數配置)
    (1) 指定Redolog記錄在{datadir}/ib_logfile1&ib_logfile2 可通innodb_log_group_home_dir配置指定目錄存儲
    (2) 一旦事務成功提交且數據持久化落盤之後,此時Redo log中的對應事務數據記錄就失去了意義,所 以Redo log的寫入是日誌文件循環寫入的
    (3) 指定Redo log日誌文件組中的數量 innodb_log_files_in_group 默認爲2
    (4) 指定Redo log每一個日誌文件最大存儲量innodb_log_file_size 默認48M
    (5) 指定Redo log在cache/buffer中的buffer池大小innodb_log_buffer_size 默認16M
    (6) Redo buffer 持久化Redo log的策略Innodb_flush_log_at_trx_commit

    • (a) 取值 0 每秒提交 Redo buffer --> Redo log OS cache -->flush cache to disk[可能丟失一秒內的事務數據]
    • (b) 取值 1 默認值,每次事務提交執行Redo buffer --> Redo log OS cache -->flush cache to disk [最安全,性能最差的方式]
    • © 取值 2 每次事務提交執行Redo buffer --> Redo log OS cache 再每一秒執行 ->flush cache to disk操作

    建議取值2,MySQL掛了,損失一次事務數據,操作系統掛了,損失1秒事務數據。

  • 總結
    undo log是對舊數據(原始數據)的備份,redo log是對新數據(事物所要提交的數據)的備份。

mysql性能優化

https://blog.csdn.net/madongyu1259892936/article/details/99650495

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章