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定义了两个临界点async和sync,当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博客 ” ,链接:https://blog.itpub.net/15480802/viewspace-1317139/
,如需转载,请注明出处,否则将追究法律责任。