ITPub博客

首页 > 数据库 > Oracle > redo的内部过程与lgwr

redo的内部过程与lgwr

Oracle 作者:leon3389 时间:2014-02-21 10:14:00 0 删除 编辑

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


参考资料
http://www.itpub.net/thread-1807437-1-1.html
DSI 405

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/26453519/viewspace-1085027/,如需转载,请注明出处,否则将追究法律责任。

上一篇: 没有了~
下一篇: 没有了~
请登录后发表评论 登录
全部评论

注册时间:2013-02-26

  • 博文量
    1
  • 访问量
    5366