【internal】redo生成机制

来源:互联网 发布:张无忌武力 知乎 编辑:程序博客网 时间:2024/06/15 19:35

redo生成流程

oracle10g之后引入的IMU(in memory undo)机制,这个机制改变了部分redo的生成机制,所以,redo生成流程必须分两部分介绍:

传统流程

IMU机制下的流程。

 

先说下如何区分系统是否使用了IMU。

10g以后,默认是启用了IMU的,但有些条件下IMU被关闭。

这些条件有

1、RAC环境中

2、数据库级别启用了supplement log(任何级别)。

3、系统隐含参数_in_memory_undo参数设置成False的情形下。

4、redo文件过小,小于50M的情形下。

5、(部分不使用IMU)当系统并发很高,当前所有的IMU Latch都被使用,新的IMU Latch请求都失败,则会话不会等待IMULatch的释放,而是直接使用传统流程,绕过IMU。因此IMU层面不会造成等待。

6、(部分不使用IMU)当一个事务很大,产生的redo或回滚数据超过了共享池中IMU区、privateRedo Strand Area中任何一个的大小,则这个事务将不再使用IMU方式,原本写的IMU区数据和redo数据将全部刷出。这个时间叫做IMUFlashes。每发生一次这种事件,v$sysstat中的IMU Flushes值将加1。

 

以上的检查条件略多,所以,基本上通过

   select * from v$sysstat a where a.NAME like '%IMU%'

 

    查看IMUcommits行的值,若这个值为0,则基本是没启用IMU了。

 

   再说下IMU下的redo生成流程

 

l

 

流程解析:

    1、server进程从共享池的sql中把目标值拿到PGA中。

   2、申请IMULatch和redo allocation Latch。这里IMU Latch和redo allocation Latch会有多个,对应privateredo area也会被分成多个strands。申请成功后,则分配IMU和private redo区间,分配完释放两个Latch。此区间就成进程私有的了,后续进行DML操作可以直接往里面写数据。

    3、从PGA中生成数据块的更改信息(数据块的redochange vector)。

   4、从bufferpool中的对应块里找到修改前的值,放入到shared pool中的私有IMU区。并将新值写入到buffer pool中的数据块。该块变成脏块。

   (4.5)SMON会定期醒来,检查IMU中的数据,生成undo对应的redo信息写入私有redo区,并把数据刷入bufferpool中的undo block,该undo块成为脏块。

   5、当事务commit。申请logbuffer区的redo allocation Latch(public area)。申请成功后,为该事务在redo buffer中分配一段空间,释放Latch。

   6、申请redocopy Latch。申请成功后,把IMU中剩余数据生成redo,刷到undo block.并在copy Latch保护下把私有redo区中的数据拷贝到bufferpool。拷贝完成后释放redo copy Latch。

   7、LGWR开始把bufferpool中的数据往磁盘写。

   8、写完成后commit完成。


传统方式下的redo生成流程


流程解析:

    1、server进程从共享池的sql中把目标值拿到PGA中。

   1.5 从bufferpool中把old值拿到PGA中。

   1.6 生成undo块的redochange vector,生成data块的redo change vector.

   2、申请redoallocation Latch。申请成功后,则在buffer pool里分配一段空间,释放redo allocation Latch。

   3、申请redocopy Latch。

   4、申请成功后将undo的CV和data的CV拷贝到logbuffer。

   5、修改bufferpool中的undo block(转为dirty block)。

   6、修改bufferpool中data block(转为dirty block)。

    (此时一个update语句即算结束)

   7、若发生commit,将触发LGWR把logbuffer中内容写入到log file。

     (commit完成)

redo文件格式

 

 

redo过程事件分析

log buffer space

事件原因:

    申请logbuffer中的空间不得。

 

log file sync

事件原因:

    用户commit之后,等待把相关redo信息从logbuffer刷入log file的过程。

    造成这个事件的原因主要有:

      1、commit过于频繁

     2、LGWR工作过慢,一般伴随着logfile parallel write,则表示IO过慢。

 

log file parallel write

事件原因:

    LGWR在执行从logbuffer刷入log file过程中,开始物理IO的过程。(开始物理IO之前需要进行一些Latch的申请,以及进程间message的传递,这些部分加上物理IO就是logfile sync的过程。)

 

log file switch(checkpoint incomplete) 

事件原因:

    日志切换时发生完全检查点,但这个完全检查点优先级并不高,不会立即触发DBWn进程写入dirtyblock,因此日志切换主要等待在关闭当前日志,打开新日志的过程(即log file switch completion),但若日志组切换了一轮,又切换到当前日志组,可当前日志中对应的脏块还没有写完,即日志仍为active状态,这时session需要等待DBw0把改日志对应的脏块全部写出,把检查点scn登记到controlfile和data file header这些内容,这个等待过程就是 log file switch(checkpointincomplete) 。

     所以,造成这个事件的原因主要有

     1、日志产生的太快大,导致切换过于频繁。

     2、当前日志组设置的过少,或过小,导致切换过于频繁。

     3、DBWn进程写的太慢,导致一轮日志切换的时间仍然写不完。

 

  log fileswitch completion

      事件原因:

          这个过程主要就是关闭当前日志,打开新日志。

 

 log fileswitch(private strand flush incomplete)  

      事件原因:

 

 log fileswitch (archiving needed) 

      事件原因:

 

 

 

遗留问题:

    1、dumpshared pool查看IMU等相关内存。

    2、pbsa和pvsa数目初始化值及如何设置

    3、redobuffer大小的初始化值和设置

    4、相关latch的初始化大小和设置,redoallocation latch、redo copy latch、