本文主要总结的是五个核心后台进程(PMON、SMON、CKPT、DBWn、LGWR),理解这些进程的概念是Oracle学习的内功,是TroubleShooting和优化的基础,以下内容参考了Oracle编程艺术、官方文档Concept、OCP考试指南及行业大牛的总结。不到位的地方,请务必指出。
查询所有后台进程:
select paddr,name from v$bgprocess where paddr<>'00'
而下面语句是查看所有进程(后台进程+服务器进程):
select addr,program from v$process
vprocess与vbgprocess关联查询:
select a.paddr,a.name,a.description from v$bgprocess a, v$process b where a.paddr=b.addr
pmon(Process Monitor process)用于监控其他后台进程。负责在连接出现异常中止后进行清理工作。例如,一个专用服务器进程崩溃或者出于某种原因被结束掉,就要由PMON进程负责善后(恢复或者撤销工作),并释放资源。PMON会回滚未提交的工作,释放锁,并释放之前为失败进程分配的SGA资源。
PMON还负责监视其他Oracle后台进程,并在必要时重启这些后台进程。
主要作用:
Smon(System Monitor Process)负责各种系统级清理职责。上面说的PMON进程所对应的是各个进程,而SMON则是从系统级的视角出发,成为了数据库上的垃圾回收器。
主要作用:
所做的工作:
Smon进程功能远不止以上几项,用到再补充。
DBWn(Database Writer Process)是数据库块写入进程。负责将buffer cache中的脏块写入磁盘,为buffer cache腾出更多空间(释放缓冲区来读入其他数据),再就是为了推进检查点(将在线重做日志文件中的位置前移,如果出现数据库崩溃,Oracle会从这个位置开始读取来恢复实例)。
DBWn进程可以配置多个,11g最多36个,12c最多100个。使用下面语句可查看:
Select name,description from v$bgprocess where description like ‘db writer process%’;
查看当前数据库DBWn进程数量,查询db_writer_processes参数
修改DBWn进程数量:
alter system set db_writer_processes=4 scope=spfile;
注意DBWn进程设置越多占用CPU资源就越多,所以不是越多越好,得根据情况来。
Oracle默认的DBWn进程数量是cpu_count参数的1/8,它的数量影响写入磁盘的速度,如果写入速度不够快,不能很快的释放buffer cache,就出出现Free Buffer Waits 和 Write Complete Waits这两个等待事件的数量和等待时间开始增加。
另外,DBWn使用异步(ASYNC)I/O将块写到磁盘。采用异步I/O,DBWn会收集一批要写的块,并把他们交给操作系统。DBWn并不等待操作系统真正将块写出;而是立即返回,并收集下一批要写的块。当操作系统完成写操作时,它会异步地通知DBWn写操作已经完成。这样,与把所有工作都串行起来执行相比,DBWn可以更快地工作。
另外注意DBWn进程写入磁盘是离散写(scattered write),会把块分散地写到磁盘的各个位置。
LGWR是顺序写(sequential write)。
DBWn 进程在下列条件下会将脏缓冲区写入到磁盘:
至于DBWn进程怎么判断哪些脏块应该写,是怎么写的,相关到检查点队列(checkpoint queue),LRU算法(Least Recently Used)等知识。
Lgwr进程负责将SGA中重做日志缓冲区(redo log buffer)的内容刷新输出到磁盘。LGWR是顺序写(sequential write),比离散写效率高。
触发条件:
在 DBWn 可以将脏缓冲区写到磁盘之前,与该缓冲区更改相关联的重做记录必须先被写入磁盘 (预写协议)。如果 DBWn 发现一些重做记录尚未写入, 则它通知 LGWR 将记录写入磁盘,并等待 LGWR 完成此工作,然后DBWn 才将数据缓冲区写入磁盘。
lgwr和commit Oracle使用快速提交机制来提高已提交事务的性能。当用户发出commit语句时,事务分配到一个scn。lgwr将一个提交记录记入redo log buffer,连同提交scn和事务的重做条目,并立即写入到磁盘。
重做日志缓冲区是循环的。当 LGWR 将重做条目从重做日志缓冲区写入到联机重做日志文件时,服务器进程可以复制新条目并覆盖已写入到磁盘的重做日志缓冲区中的条目。通常 LGWR 的写入速度足够快, 以确保在缓冲区中总会有可用空间供新条目使用, 即使对联机重做日志的访问很繁重时也是如此。
包含事务提交记录的重做条目的原子写入, 是确定该事务已提交的唯一事件。Oracle 数据库向已提交事务返回一个成功代码,虽然数据缓冲区尚未写入到磁盘。对数据块的相应更改被延迟,直到 DBWn 在某个有利的时机将它们写到数据文件。
注意: LGWR 可能会在提交事务之前, 将重做日志条目写入到磁盘。只有之后提交了事务,这些重做条目才会成为永久性的。当事务活动很高时, LGWR 可能会使用组提交。例如, 某个用户提交其事务, 导致 LGWR 将事务的重做条目写入到磁盘。在此写操作的过程中,其他用户也试图提交。但 LGWR 无法写入磁盘以提交这些事务,直到前面的写入完成为止。完成后, LGWR 可以将(尚未提交的)等待事务中的重做条目列表在一个操作中全部写入。通过这种方式, 数据库最小化了磁盘 I/O, 而最大化了性能。如果提交请求继续维持在一个高的水平,则每个 LGWR 写入操作都可能包含多个提交记录。
检查点(checkpoint)是一种机制。它的作用是通知dbwn进程将数据库缓冲区缓存(buffer cache)中的已修改的数据脏块写入到disk中,ckpt进程负责通知 dbwn进程。
要修改数据库中的数据,首先需要将数据从数据文件中取出到SGA的buffer cache中,这里是要修改数据的一个副本,在这里进行修改的同时,会将变更向量写入到SGA中的redo log buffer内存区域,然后通过lgwr进程实际写入到磁盘上的redo log中。到这一步,修改的数据还没有实际写入磁盘,但是redo log中已经有记录。
假设这时候数据库崩溃了,那么内存中修改过的、尚未写入数据文件的数据会丢失。在下一次数据库启动之后,Oracle会通过redo log进行事务重演,也就是进行前滚操作,将数据库恢复到崩溃前的状态(这里我的理解是将redo log中的记录应用到数据文件,这样就保持了一致性),然后数据库可以打开使用,在之后Oracle会将没有提交的数据进行回滚。
崩溃后打开数据库,需要先读取redo log完成前滚,需要前滚的数据越多,那么打开时间越长。检查点的存在就是为了缩短这个恢复时间。
检查点位置是由buffer cache中最旧的脏缓冲区来确定的。 检查点位置作为一个指向重做流的指针,并存储在控制文件中,和在每个数据文件头中。
目标: 使用检查点,能实现以下目标:
检查点结构:
检查点类型:
其他类型的检查点包括实例和介质恢复检查点, 和删除或截断模式对象时的检查点。
完全检查点只会在执行 alter system checkpoint 语句或 consistent shutdown 关闭数据库时出现。
学习后台进程知识,还是需要先对内存结构(SGA、PGA)有些基础,其他强制性进程, 包括 MMAN、 DIAG、VKTM、 DBRM、 和 PSP0 等,另外还有可选进程ARCn等等。 还需要对一些进程的内部原理再深入学习下,比如检查点队列(checkpoint queue)、DBWn进程判断哪些脏块写或者不写相关的LRU算法(Least Recently Used)。