redo log和undo log、事務
redo log
如果系統突然崩潰,一些在緩存中的修改還沒來的及同步到磁盤中,用redo log就可以恢復這些修改,Redo log就是記錄這些修改的日志。這些對頁面的修改有一些是原子操作,比如有些插入伴隨着頁面分裂和頁的新建(悲觀插入),此時這些分裂和修改必須一氣呵成,這樣的操作叫mini-transition,一條語句可能包含多個mini-transition,而一個又包含多個redo日志,這種原子性用一個特殊位來標記,在恢復時讀到標志位才恢復之前的內容,否則放棄之前的日志。每次的redo日志也是存到buffer pool中,選擇合適的時機刷新到磁盤,可以選擇事務提交時同步到磁盤或寫入緩存。
(LSN:記錄的一個字段,一個redo日志對應的編號,一個頁的LSN越大說明剛剛修改過)
undo log
為了事務回滾而記錄的日志信息,undo日志有幾種類型,插入數據、刪除數據、更新數據都會產生不同的undo log,記錄有一個roll_pointer的指針指向它的undo log,所有關於這條記錄的undo log都連成一條鏈表,稱為版本鏈,根據undo log的事務ID來判斷是哪個事務中修改了該記錄,事務回滾時找到對應事務ID的undo log恢復數據除此之外,undo log還可以用來維護MVCC(多版本並發控制)。
(mysql刪除時實際上分兩步,第一步是標記刪除,如果事務提交再將其放入垃圾鏈表中)
事務
事務的隱式提交:一些DDL語言(create、drop、alter)、使用表的語句(帶table的)、開啟另一個事務等。。。
創建保存點:savepoint 保存點名
回滾到保存點:rollback to 保存點名
事務的使用:start transaction、commit、rollback
隔離級別的實現
Read uncommitted的實現:每次讀時都讀最新的那個版本,並發問題最嚴重
Read committed的實現:避免臟寫,在每次讀取數據時都生成一個readview,readview其中存有創建當前結構的事務ID,活躍事務ID,然后從記錄開始讀每個undo log,如果某個undo log剛好是事務的創建ID或不在readview的活躍事務列表中就可以讀,這樣就避免了臟讀。
Repeatable read的實現:在事務第一次讀的時候生成readview,然后讀記錄,這樣就能保證讀到的數據不可能不一樣。
Serializable的實現:依賴mysql的鎖