InnoDB多版本
InnoDB是一個多版本的存儲引擎:為了支持事務的一些特性諸如並發和回滾,它保持著被修改行的舊版本信息。這些信息被存儲在一個被叫做“回滾段”的表空間中(跟Oracle中的回滾段類似)。InnoDB在回滾段中用這些信息來執行undo操作,以此支持事務回滾。它也用這些信息來構造行的更早的版本,以此支持一致性讀。
在內部,InnoDB為數據庫中存儲的每一行添加三個字段。一個6字節的DB_TRX_ID字段來表示插入或者修改這一行的最後一個事務的事務標示符。delete在內部被當做update來對待,就是在行的特定位做一個標記,以表明這一行已經被刪除。每一行還包含一個被叫做“roll pointer”的7字節的DB_ROLL_PTR字段。這個roll pointer被指向一個寫在回滾段中的undo log。如果行被修改了,那麽這個undo log記錄包含的信息必須先於行修改被重新修改。一個6字節的DB_ROW_ID字段包含一個當行被插入的時候單調遞增的行ID。如果InnoDB自動生成了一個聚集索引,那麽這個索引包含行ID值,否則DB_ROW_ID列不會出現在任何索引中。
回滾段中的undo logs被劃分為insert undo logs和update undo logs。insert undo logs只有在事務回滾的時候才會用到它,並且在事務提交以後它就被丟棄了。update undo logs用在一致性讀的時候。
定期提交你的事務,包括哪些只有一致性讀的事務。否則,InnoDB不能從update undo logs中丟棄數據,並且回滾段可能會增長得很大,填滿你的表空間。
在InnoDB多版本中,當你用SQL語句刪除的時候,這一行並不是立即從數據庫中被物理刪除。只有當它為了刪除丟棄了update undo logs的時候,InnoDB才會物理刪除這一行和它的索引記錄。這種刪除操作被叫做purge,並且它的速度相當快
Multi-Versioning and Secondary Indexes
InnoDB多版本並發控制(MVVC)對待二級索引和聚集索引時不同的。一條記錄的聚集索引在原地被更新,它們的執行undo log的隱藏系統列會被重新構造。不像聚集索引記錄那樣,二級索引記錄不包含隱藏的系統列,它們也不會在原地被更新。
當一個二級索引記錄被更新的時候,舊的二級索引記錄被標記為刪除,新的索引記錄被插入,並且被標記為刪除的索引記錄最終被purge。當一個二級索引記錄被標記為刪除或者二級索引頁被一個新的事務更新的時候,InnoDB用聚集索引查找數據庫記錄。在聚集索引中,記錄的DB_TRX_ID字段被檢查,並且記錄的正確版本會被從undo log中檢索出來,即使記錄在事務初始讀取以後被修改。
小結:
1、InnoDB在回滾段中維護著被修改行的舊的版本信息
2、回滾段中的undo logs分為insert undo logs和update undo logs。並且undo log 日誌寫入優先。
3、在內部,delete被當做update來對待。它是將舊的行標記為刪除,然後插入新的行.
4、當在SQL語句執行DELETE的時候並不是立即從數據庫中刪除這條記錄。只有當它丟棄update undo logs的時候,該記錄及其索引記錄才會被物理刪除。
5、InnoDB給數據庫中的每一行記錄添加三個字段
- DB_TRX_ID:表明插入或者修改這一行的最後一個事務的事務標識符
- DB_ROLL_PTR:指向回滾段中的一個undo log記錄
- DB_ROW_ID:單調遞增的行ID。(PS:如果沒有明確定義聚集索引,那麽會自動生成一個聚集索引,這個時候自動生成的聚集索引的值就是DB_ROW_ID)
6、MVCC下的二級索引和集聚索引時不同的。二級索引記錄既不包含隱藏的系統列,也不會在原位置被更新。與之相反,聚集索引記錄才會包含隱藏的指向undo log記錄的系統列,而且聚集索引時在原來位置上被更新的。
7、當一個二級索引列被更新的時候,舊的二級索引記錄被標記為刪除,同時插入一個新的二級索引記錄。
8、由此可見,undo logs中不僅包含記錄的undo log還包含索引記錄的undo log。
參考 https://dev.mysql.com/doc/refman/5.7/en/innodb-multi-versioning.html
InnoDB多版本