注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

饥民2011

一直在搬砖

 
 
 

日志

 
 
 
 

Oracle 日志的核心意义(快速提交,写缓存,回滚)  

2013-02-09 12:59:42|  分类: Oracle |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

这篇文章是参考甲骨论老相老师的教学视频
http://v.youku.com/v_show/id_XMzk1MDA3NjA4.html
所做的学习笔记


1.Oracle有1个重要的原则.

        这个原则就是已提交的事务,Oracle保证不会丢失. 除非服务器存储设备出问题了.

        也就是说,如果用户在数据库执行一些DML sql语句, 但是并没有提交的话, 这时服务器突然崩溃, 或者断电了. 重启后, 用户的这些修改有可能找不回来了.  但是用户,一但执行commit动作, 即使服务器崩溃, 重启后用户的修改还能找回来.

2. 后台进程DBWR 不断将LRUW链(脏buffer) 的冷端写入到dbf文件中.

         前面章节已经提过很多次,  当server process修改完数据后(可能若干个buffer), 就直接返回给用户, 告诉用户修改完成了, 但是并不负责将这些buffer写入到dbf文件, 而是将这些buffer挂到LRUW chain,写入dbf文件的动作交由后进程DBWR执行.

         如下图:
    
Oracle 日志的核心意义(快速提交,写缓存,回滚,构造CR块) - 饥民 - 饥民2011


       这样的好处时,提高了用户的速度感受, 因为写入buffer到dbf文件是1个很耗时间的物理IO动作, 如果让server process执行这个动作才返回信息给用户的话, 用户就会觉得数据库性能很差了.

3. 用户提交commit时, 脏buffer并没有写入dbf文件.
       这个很明显了, 用户commmit后,一般马上就可以执行下1个动作了, 但是这时脏buffer并没有写放入到dbf文件. 只不过被挂在LRUW chain让后台DBWR来写入.   

       但如果这时服务器崩溃, 是否这些脏buffer就会丢失? 是否违反了Oracle上述的那个原则?  其实不是, Oracle有另1个机制保证commit即使脏buffer还未写入dbf文件, 也能把脏buffer重现出来.
 
       如果没有这个机制, 用户commit后, 为了保证oracle的那个原则, server process就必须等待脏buffer写入dbf文件后才能返回完成信息给用户.  这样的话commit的速度就十分缓慢了.

        这个机制就是日志系统了.
      
4.所以说日志系统的第1个核心意义就是提高commit速度.
        下面讲解下这个机制的实现原理.

        
Oracle 日志的核心意义(快速提交,写缓存,回滚,构造CR块) - 饥民 - 饥民2011

    如上图:

    4.1 内存中的redo log buffer 相对于buffer cache来一般很小, 只有几MB空间.

    4.2 server process 一旦修改了buffer, 无论commit与否,都会产生redo 写入到redo log buffer.

    4.3 server process 不commit的话, DBWR是不会将该buffer是不会写入到dbf文件中的, 而LGWR 是不断地将redo log buffer里的日志数据写如到logfile里面.

  
因为redo log buffer的大小很小,例如9g以前大概只有3g, 所以有几个条件会触发LGWR将redo log buffer里的数据写入到日志文件.
    例如: a.  每隔3秒写一次.
              b.  redo log buffer的占用到1MB(留下2BM作缓冲应急)
             
    所以, 很多时候, server process修改了若干数据, 在commit之前, 对应的日志就已经写入到日志文件里了. 所以commit时就能马上提示用户完成, 然后这时DBWR才按需将对应脏buffer写入到dbf文件.

     即使这时服务器崩溃,  但是由于日志文件里已经有其修改的记录, 所以能根据这些日志数据, 把脏buffer重现出来, 就能保证commit后的数据不丢失了.

  

    4.4 如果commit的时候, 对应日志还在redo Log buffer 中, 那么commit动作也会触发LGWR将日志数据写入到日志文件. 才会提示用户commit完成.

   
有时後,用户的sql语句修改完马上就commit,  对应的日志还在redo log buffer, 还没写入日志文件, 这时 commit动作就会触发LGWR把日志数据写入logfiles啦.

      当很多个session修改数据库时,就会产生大量的日志数据, LGWR就比较繁忙了.

      可能有人会问, 写入日志文件同样是1个物理IO动作, 为什么commits 写入脏buffer 就慢,  写入日志就快呢.

       是因为1个事务中, 可能有多条DML语句, 修改的数据block可能遍布dbf文件中各个位置.  而日志数据是严格按照修改时间产生的, 写入日志文件时,在磁盘中也是一段物理上连续的数据.
      
     所以写入脏buffer 会耗费大量是时间在磁盘寻道上(磁头知道到对应block的物理地址), 而物理IO 90%的时间都是寻道时间, 所以同为物理IO,  写入日志数据到日志文件时几乎不用寻道, 只要按照顺序一直写就是了. 比写入脏buffer快很多.

     所以说, 日志系统能大大加快commit速度!




5.所以说日志系统的第2个核心意义是令到Buffer cache发挥写缓存的作用.

   
当若干server process想从数据文件中读出数据时, Buffer cache能作为1个读缓存发挥作用, 因为第1次读取数据文件中的1个block时, 就会把这个block放入buffer cache中, 下一次读取这个block时就避免多余的物理IO了.

       但是当DBWR把脏buffer从buffer cache写入到dbf文件这个1个过程中, 是没有写缓存的, 因为DBWR写入1个脏buffer就发生1次物理IO,  下次写入同样1个脏buffer时也要发挥物理IO.

       但是因为有日志系统的存在, 令到server process 在commit 时不必DBWR不必马上将对应脏buffer 写入到数据文件中, 而是将其放到LURW chain中,  如果server process在接下来一段时间多次修改这个buffer, 那么这个脏buffer就会移到LRUW chain的热端. 写入到数据文件的优先级就更低了.  所以实际上server process发生了对1个block的多次改动, 发生了多次commit动作, 但是DBWR把最后一次的改动结果写入到dbf文件中的就行了,  因为日志系统的存在, 不怕服务器崩溃后丢失了数据改动.

        所以说日志令buffer cache发挥写缓存的作用, 如果没有日志, oracle为了保证commit后数据不丢失的原则, 务必commit 1次 写入脏buffer1次...

       而实际上, DBWR 会绕过操作系统的缓存, 直接将数据写入到磁盘上的缓存中.  至于磁盘本身有没有将磁盘缓存的数据写入到磁盘扇区对应地址上, DBWR是不知道的.   因为有电池的存在, 正常来将磁盘就算断电也会保证将磁盘缓存中的数据写入扇区. 但是若过磁盘的缓存出现故障, Oracle实际上还是有可能丢失数据的.


6.所以说日志系统的第3个意义是回滚数据.
      这个很简单, 没什么可说的,  就是1个事务中发生了回滚动作, server process 就会提取日志数据, 根据日志把改动还原回去.

       同样, 因为数据改动可以rollback这个特性, 日志系统就可以协助用于构造CR块了,

       至于什么是CR块, 之前已经提过很两次了, 这里就不重复了哈哈.

 

     


  
  







  评论这张
 
阅读(358)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017