innodb redo原理小結

myownstars發表於2014-11-01
1 原理
與oracle一樣,innodb redo採用物理邏輯方式,即phsical-to-page, logical-within-page,每條日誌 結構大致如下
struct value_log {
 int opcode;
 long page_no;
 long offset;
 long length;
 char old_value[length];
 char new_value[length];
}

檢查點:將buffer pool中的髒頁重新整理到磁碟,分為sharp和fuzzy,後者將髒頁按照第一次修改時的LSN排序,依次將oldest page寫入磁碟,使得頁的重新整理和日誌LSN順序一致,保證恢復的正確性;
checkpoint結構體佔用296位元組,包括8位元組的log_checkpoint_lsn;
crash recovery: innodb引擎每次啟動都會進行嘗試恢復,頁(0,0)的FIL_HEADER存放fil_page_file_flush_lsn,記錄資料庫關閉時最後重新整理頁的LSN,每次啟動時將其與重做日誌中的檢查點值比較,如果相等則無需恢復;


2 資料結構 
redo log block:以512位元組為單位,每個塊由塊頭(12位元組),塊尾(4位元組)和塊體組成;
redo log file:每個日誌組的第一個檔案前4個塊依次為file header - checkpoint1 - 空塊 - checkpoint2,其餘檔案前4個塊則保留;兩個checkpoint塊在更新時交替使用,crash recovery時讀取其最大值;
log buffer:由結構體log_sys描述,flushed_to_disk_scn--已寫入logfile的LSN; lsn--當前LSN;
log buffer重新整理條件:1 事務提交 2 寫入檢查點 3 log buffer使用空間超出閾值

LSN,即log sequence number,等同於oracle的SCN,存於redo log/page header/checkpoint;
struct dulint_struct {
 ulint high;
 ulint low;
}--各4個位元組

show engine innodb status列舉資訊 
---
LOG
---
Log sequence number 84 3000620880  -- log_sys->LSN
Log flushed up to   84 3000611265  -- log_sys->flushed_to_disk_lsn
Last checkpoint at  84 2939889199  -- log_checkpoint_lsn
注:log_sys->LSN - log_checkpoint_lsn = checkpoint_age

Innodb定義了兩個臨界點asyncsync,當checkpoint_age到達此臨界值時資料庫會有相應動作;

async_water_mark:只阻塞當前執行緒,儘可能的重新整理髒頁,會嚴重消耗IO資源,pre-5.6呼叫buf_LRU_sacn_and_free_block完成

sync_water_mark:重新整理髒頁同時阻塞所有執行緒,直至checkpoint_age降回async,

具體可參考http://blog.itpub.net/15480802/viewspace-1064153/ 


3 具體實現
前臺執行緒訪問頁面,生成redo並提交到log buffer,最後重新整理到磁碟;此過程由mini-transaction實現;
mini-transaction用於實現innodb redo的寫入,保證併發事務下頁的一致性; 
遵循FIX rule & Write-ahead Log & Force-log-at-commit,其中FIx rule規定讀寫頁時必須先獲取S或X latch,每個頁對應一個buf_block_t,
struct buf_block_t {
  ...
  rw_lock_t lock;
  ulint buf_fix_count; --每個fix操作增1,當頁從緩衝池被替換出時必須為0;非頁節點頁由B+樹索引的latch保護,無須持有類似latch;
  ...
}

mini-transaction過程如下
mtr_t mtr;
mtr_start(&mtr);
...
mtr_commit(&mtr);--1 將mtr中儲存的日誌按FIFO規則寫入log buffer(log_sys->mutex); 2 釋放mtr持有的所有latch; 3 釋放log_sys->mutex; 若事務只讀則mtr_commit時只需執行unfix page;


mini_transaction() {
//page1
 lock the page1 in exclusive mode
 transform the page1
 generate the undo and redo log record

//page2
 lock the page2 in exclusive mode
 transform the page2
 generate the undo and redo log record

 write MLOG_MULTI_REC_END

 unlock the page2
 unlock the page1
}


組提交:redo從buffer寫入磁碟可實現組提交,因為fsync時無須持有log->mutex,期間其他事務可執行write redo log buffer to disk;
lock log->mutex
write redo log buffer to disk
unlock log->mutex
fsync 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/15480802/viewspace-1317139/,如需轉載,請註明出處,否則將追究法律責任。

相關文章