MySQL:Innodb crash recovery一些代码
2021-01-13 本文已影响0人
重庆八怪
简单记录可能还理解,做个笔记,不深入:
http://mysql.taobao.org/monthly/2015/06/01/
buf_dblwr_init_or_load_pages
初始化dblwr从double write中,写入到内存
Recovering partial pages from the parallel doublewrite buffer at /opt/my_mysql/data/xb_doublewrite
recv_recovery_from_checkpoint_start 总是进行恢复 we always do a 'recovery' at startup
srv_force_recovery >= SRV_FORCE_NO_LOG_REDO 则直接跳过恢复步骤
信息级别信息 "The user has set SRV_FORCE_NO_LOG_REDO on, skipping log redo"
->recv_find_max_checkpoint
找到最大的chk block 有2个chk block循环写入,
->log_group_header_read
读取chk block到 log_sys(log buffer的chk buffer)
buf = log_sys->checkpoint_buf;
checkpoint_lsn = mach_read_from_8(buf + LOG_CHECKPOINT_LSN); //获取chk lsn
checkpoint_no = mach_read_from_8(buf + LOG_CHECKPOINT_NO);//获取chk的次数
获取chk lsn/chk的次数
->recv_group_scan_log_recs带入形参找到的最大chk lsn和日志组,第一次调用带入的参数last_phase为false,任何log rec存储 开始解析 解析入hash结构 recv_sys->addr_hash
available_mem有效的内存来自innodb buffer
首先向下以512对其chk lsn准备开始读取
每次读取分片64K的日志,这里开启一个循环
->log_group_read_log_seg 读取64K的日志,到redo buffer的buffer中,读取为fil_io,这里为第一层缓存到 redo buffer
->recv_scan_log_recs 输入参数主要带入64k的大小和chk lsn开始解析
开启循环分块(512)进行日志检查。如果大于了?则解析结束,加入到解析buffer(recv_buffer这是第二层),结束条件未知
data_len = log_block_get_data_len(log_block); //获取块中存储的数据,一般都是512 除非最后一个块或者不需要恢复
如果输入的lsn大于上次解析lsn则说明有更多的redo需要进行解析,一般为64K,除非最后一个分片We have found more entries
输出日志scanned_lsn > recv_sys->scanned_lsn,这里就代表不是干净关闭数据库,需要进行 recovery,因为需要扫描的
lsn大于了redo中第一个lsn的位置,后面也会用到这个位置,recv_init_crash_recovery_spaces依赖这个比较看是否需要crash recovery,
下列输出日志只输出一次 recv_init_crash_recovery(5.6这里进行dblr恢复)
info级别"Log scan progressed past the checkpoint lsn recv_sys->scanned_lsn(redo中第一个redo record的lsn);
->recv_sys_add_to_parsing_buf 加入到recv_buffer中,输入参数为 64K的分片和扫描到的lsn 循环结束,加入到解析缓存结束
如果扫描次数为80*64K(5M)次则输出一次日志或者结束,作为信息
"Doing recovery: scanned up to log sequence number "
本次64K加入到recv_buffer结束
->recv_parse_log_recs 解析已经存入到recv_buffer的每条redo日志,根据不同的类型
->recv_parse_log_rec解析单个redo
->recv_parse_or_apply_log_rec_body尝试应用MLOG_FILE_*的日志类型
->recv_add_to_hash 加入到hash结构(三层缓存),根据space id和page no进行hash,等待应用
->如果需要进行crash recovery则进行 recv_needed_recovery进行判断在
recv_init_crash_recovery_spaces 初始化需要用到的tablespace,输出日志,info级别
Database was not shutdown normally!
Starting crash recovery.
->buf_dblwr_process应用dblwr的断页信息
->如果内存不足(innodb buffer不足hash的全部日志存储在innodb buffer中)
调用recv_group_scan_log_recs(,,ture)直接进行应用了。第二次调用recv_group_scan_log_recs
->trx_sys_init_at_db_start 初始化undo的page,用于crash recovery 可以不进行undo page的初始化进行启动 SRV_FORCE_NO_UNDO_LOG_SCAN
->recv_apply_hashed_log_recs进行日志应用
->recv_recovery_rollback_active 回滚事务 SRV_FORCE_NO_TRX_UNDO
单独线程trx_rollback_or_clean_all_recovered SRV_FORCE_NO_TRX_UNDO
->Binlog/InnoDB XA Recover
读取64K日志到redo buffer的buffer->存储64K日志到 recv_buffer->循环解析这64K日志
解析每次80*64K(5M)则输出一次日志,或者为结束了
enum {
SRV_FORCE_IGNORE_CORRUPT = 1, /*!< let the server run even if it
detects a corrupt page */
SRV_FORCE_NO_BACKGROUND = 2, /*!< prevent the main thread from
running: if a crash would occur
in purge, this prevents it */
SRV_FORCE_NO_TRX_UNDO = 3, /*!< do not run trx rollback after
recovery */ trx_rollback_or_clean_all_recovered
SRV_FORCE_NO_IBUF_MERGE = 4, /*!< prevent also ibuf operations:
if they would cause a crash, better
not do them */ ibuf_merge_or_delete_for_page
SRV_FORCE_NO_UNDO_LOG_SCAN = 5, /*!< do not look at undo logs when
starting the database: InnoDB will
treat even incomplete transactions
as committed */ trx_sys_init_at_db_start
SRV_FORCE_NO_LOG_REDO = 6 /*!< do not do the log roll-forward
in connection with recovery */
};