共计 2888 个字符,预计需要花费 8 分钟才能阅读完成。
如何理解 redo 的内部过程与 lgwr,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面丸趣 TV 小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
Oracle 采用混合日志记录模式,以数据块为单位,即 dba + sql,即避免记录整个块,又可快速恢复
the granularity is at the block level (like physical logging), so one operation is stored for each individual block change
一个大事务可由多个 mini-transaction 即 redo record 组成,而每个 record 又可由多个 change vector 组成;commit/rollback 单独对应 1 个 redo record;
每个 redo record 包含 1 个原子操作,1 个 change vector 仅对应 1 个数据块,change vector 在实际修改块之前生成;
事务提交时,将生成的 redo+undo 和 commit record 写入重做日志文件,同时更新 rollback segment header 的事务表;
注:临时表只记录 undo
Redo 有 3 种 latch
1 Copy,可通过_LOG_SIMULTANEOUS_COPIES 设置多个
2 Allocation 只有 1 个
3 Write 只有 1 个
REDO 的生成
Redo 先在 PGA 中生成,依次获取 copy latch–allocation latch,将 redo 写入 log buffer 后再修改块,Lgwr 在刷新 redo buffer 时获取 write latch,避免同时多次刷新;
具体步骤如下
1 以排他模式 pin 住 buffer block
2 在 PGA 中构建 change vector 并组合成 redo record,由 kconew()/kcoadd() 完成
3 调用 kcrfwr() 将 record 写入 log buffer:
计算 record 占用的空间大小;
分配 SCN;
获取 copy latch,验证 SCN;
获取 allocation latch,检验 log buffer/file 是否有足够空间,有则释放 allocation latch 将 redo 写入 log buffer,否则同时释放 allocation/copy latch 并通知 LGWR 进行 log flush/switch;
注:为防止多个进程同时通知 LGWR 刷新 redo 或切换日志文件,引入 write latch(只有 1 个),只有获取此 latch 后才能进行下一步操作;
4 将 redo record 写至 log buffer 而后释放 copy latch, 检查是否达到触发 LGWR 阈值;
5 更改 buffer block
nologging
此模式下仍记录 redo record,其下的 change vector 类型均为 INVALID;每个 record 可对应多个数据块,应用该 redo 时相应数据块将被标识为 soft-corrupt;
LGWR 触发阈值
1 由前台进程触发:log buffer 空间不足;事务提交
2 log buffer 满 1 /3
3 redo 超过 1M
4 3 秒超时
5 日志切换
6 redo 线程关闭
LGWR 触发过程
1 获取 write/allocation latch,前者防止 LGWR 被多次请求,后者防止为前台进程继续分配 redo 空间
2 确定待写的 log buffer 范围(从起始处至待刷新的 buffer),分配新 SCN(避免两次 flush 使用同一个 SCN)
3 释放 allocation latch
4 计算所需 redo write 次数,因为 log buffer 为环形,故至多写两次(分布于头尾)
5 计算 target RBA,依据 log_checkpoint_interval 增进增量检查点
6 释放 write latch
7 确保待写的 log buffer 都复制完毕,即等待所有 copy latch 释放
8 LGWR 更新 redo block header 的 SCN 和 checksum(可选)
9 执行磁盘写,可修改_lgwr_async_io 启用异步 IO
组提交
Lgwr 在 c1 处接到请求,开始刷新 log buffer 时新增了 c2/g1/c3,此时需等待 c3 写完(释放 redo copy latch) 后,连同 c3 一起刷新,
常见的 redo 等待事件
log file parallel write- 由 lgwr 触发,将 redo record 写入当前 log 文件,其并行度由物理磁盘数决定
log file sync- 由前台进程等待,从 commit/rollback 直到 lgwr 将日志写入磁盘并通知请求进程为止
log buffer space- log buffer 中没有足够空间存放新生成的 redo,说明 lgwr 写出速度较 redo 生成慢
log file switch- 分为 checkpoint incomplete 和 archiving needed
Log file sync 流程
lgwr 会 post 哪些前台进程?
当 lgwr 刷新完日志后,会 post 相应的前台进程 (wakeup)继续工作,那么 lgwr 怎么判断应该 wakeup 哪些前台进程呢?
log file sync 等待的 p1 参数的含义为:P1 = buffer# in log buffer that needs to be flushed
当 lgwr 刷新完 buffer 后,会扫描活跃会话列表,查看哪些会话在等待 log file sync,而且会话的 buffer# 小于等于它所刷新的 log buffer 的最大值,这些会话会被 wakeup。
Lgwr file sync 与 buffer busy wait
事务 commit 的 stack call 如下
为 ktcCommitTxn= ktucmt = kcbchg = kcbchg1_main = kcrfw_redo_gen = kcrf_commit_force
kcbchg== block change,为什么要发生 block change 呢?因为 commit 需要对在 Buffer Cache 里的 block 做 immediate block cleanout,期间需要排他模式 pin;
若此时其他会话访问该块则会等待 buffer busy wait
http://www.askmaclean.com/archives/why-slow-redo-write-cause-buffer-busy-wait.html
归档日志流程
1 ARCH 读取控制文件以决定待归档的日志文件
2 分配归档内存_LOG_ARCHIVE_BUFFERS * _LOG_ARCHIVE_BUFFER_SIZE;
3 以只读方式打开待归档日志组的所有成员(以轮循方式依次读取 log buffer),并验证 log file header;如果 db_block_checksum=true 每个 log block 还将验证 checksum
4 创建并打开归档日志文件
5 以循环方式将日志从 online log 复制到 archive log,对每个 buffer 都执行 sanity check
执行完毕后关闭 online log 和 archive log
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注丸趣 TV 行业资讯频道,感谢您对丸趣 TV 的支持。