10分钟了解Oracle体系结构( 二 )


select ename,salary from emp where name='东方不败';我们来看这么一条简单的查询语句 , oracle是如何处理的 。首先 , 当用户提交了该条sql语句 , 由对应的用户进程(比如我们常用的sql developer)将其发送给服务器 , 监听程序监听到该条请求 , 会为其建立一个对应的服务器进程 , 然后服务器进程会先扫描缓冲区中有没有包含关键行("东方不败")的数据块 , 如果有 , 这就算一次缓存命中了 , 然后相关行会传输到PGA进行进一步处理 , 最终经过格式化后展示给用户;如果没有命中 , 那么服务器进程会首先将对应行复制到缓冲区内 , 然后再返回给客户端 。
DML(insert , update , delete)操作同理 , 加入用户发送一条update语句 , 服务进程依然先去扫描缓冲区 , 如果缓存命中 , 则直接更新 , 数据变脏;如果没有命中 , 由服务器进程将对应数据块先从磁盘上复制到缓冲区内 , 再进行更新操作 。
脏缓冲区如果缓冲区存储的块和磁盘上的块不一致 , 该缓冲区就叫做“脏缓冲区” , 脏缓冲区最终会由数据库写入器(DBWn)写入到磁盘中去 。
数据库写入器(DBWn)数据库写入器是Oracle的一个后台进程 , 所谓后台进程是相对于前台进程(服务器进程)来讲的 。DBWn的"n"意味着一个实例是可以有多个数据库写入器的 。
作用:简而言之 , DBWn的作用就是将变脏了的缓冲区从数据库缓冲区缓存中写入到磁盘中的数据文件中去 。
数据库缓冲区缓存这块内存区域和数据库写入器这块是比较重要的概念 , 别的数据库产品像mySql也都有对应的实现 , 只不过叫法不一样罢了 。了解这块的时候 , 要时刻意识到会话是不会直接更新磁盘数据的 , 会话的更新 , 插入 , 删除包括查询等都是先作用到缓冲区上 , 随后 , DBWn会将其中的脏缓冲区转储到磁盘上去 。
DBWn什么时候写入?DBWn是个比较懒的进程 , 它会尽可能少的进行写入 , 在以下四种情况它会执行写入:
a.没有任何可用缓冲区(不得不写啊)
b.脏缓冲区过多
c.3秒超时(最晚3秒会执行一次写入)
d.遇到检查点 , 即checkPoint(检查点) , 检查点是个Oracle事件 , 遇到检查点 , DBWn会执行写入 。比如实例有序关闭的时候会有检查点 , DBWn会将所有脏缓冲区写入到磁盘上去的 , 这很容易理解 , 要保持数据文件的一致性 。
注意:
从上述DBWn的几个写入时机 , 我们能意识到 , DBWn的写入不是直接依赖于会话的更新操作的 。不是一有脏缓冲区 , 它就执行写入 。而且 , DBWn执行写入跟commit操作也没有任何关系 , 不要以为commit操作的影响结果会实时流入到磁盘中去 。
DBWn采用极懒算法进行写入 , 原因我们应该要清楚:频繁的磁盘IO对系统的压力很大 , 如果DBWn很积极地去写入磁盘 , 那对系统性能的影响就太大了 , 换个角度想 , 如果DBWn很勤快的写磁盘 , 那么数据库缓冲区存在的意义也就不大了 。
当然 , 讲到这儿 , 我们可能会意识到一个问题 , DBWn如此懒地进行数据转储 , 如果在某一时刻 , 数据库缓冲区缓存内存在着大量的脏缓冲区(生产环境中 , 这是常态) , 也就是有大量的未commit和已commit的数据还在内存中 , 没有持久化到磁盘中 , 然后突然系统断电了 , 这种情况下 , 数据是不是就丢掉了?数据当然不会丢失 , 这就引出了重做日志(redo log)的概念 , 接下来 , 我们就来谈谈对应重做日志的内存结构和后台进程 。
日志缓冲区&日志写入器当我们执行一些DML操作(insert,update,delete) , 数据块发生改变了 , 产生的变更向量则会写入到重做日志文件中去 。有了这些记录 , 当系统由于断电等因素突然宕掉 , 数据库缓冲区缓存内的大量脏数据还没来得及写入到数据文件中去 , 在重新启动的时候 , 会有一个实例恢复的过程 , 在此过程中就应用了重做日志记录来使数据保持一致;或者数据库遭遇了物理损坏 , 比如磁盘损坏了 , 此时可以通过Oracle的备份恢复工具(如RMAN)进行数据恢复 , 原理就是 提取备份集-->应用重做日志文件中的变更记录 。


推荐阅读