4.3.2 LGWR进程
LGWR进程的功能是将重做日志缓冲区中的重做日志写入重做日志文件,这是Oracle保证数据库一致性的一种重要手段。
当用户执行DML或DDL命令时,服务器进程首先在重做日志缓冲区中生成重做日志,然后才修改数据库高速缓存中相应的缓冲区。在一定的条件下,LGWR进程将重做日志缓冲区中的重做日志写入重做日志文件,而DBWR进程也将在一定的条件下,把数据库高速缓存中的脏缓冲区写入数据文件,这两个进程并不是同步的。
LGWR进程被启动执行的时机有以下几种情况:
·固定的时间间隔(如每隔3秒)。
·用户执行了COMMIT操作。
·重做日志缓冲区已经有1/3的空间被写满。
·DBWR将脏缓冲区写入数据文件之前。
由此可见,如果脏缓冲区中的数据被写入了数据文件,那么重做日志一定被写入了重做日志文件。而用户数据还没有被写入数据文件时,重做日志也可能被写入了重做日志文件,也可能没有。
SGA中的重做日志缓冲区是一段可循环使用的存储区域。一方面,服务器进程将生成的重做日志写入重做日志缓冲区,占用一部分空间。另一方面,LGWR进程将重做日志写入重做日志文件,释放一部分空间。由于LGWR进程将重做日志写入重做日志文件的速度高于服务器生成重做日志的速度,所以在任何情况下重做日志缓冲区中始终都有足够的空闲空间。重做日志缓冲区的使用情况如图4.4所示。
图 4.4 重做日志缓冲区的使用
当用户执行事务时,服务器进程一方面在重做日志缓冲区中产生重做日志;另一方面,在数据高速缓存中修改数据。对重做日志缓冲区和重做日志文件是按顺序写的,效率很高,而对数据高速缓存和数据文件都是随机写的,因为数据的分布并没有什么规律,所以效率较低。如果写日志和写数据是同步进行的,那么整个数据库的性能就不可能很高。
为了提高处理事务的效率,Oracle采取了“快速提交”的机制。当用户执行一个事务时,这个事务将获得一个SCN,同时产生重做日志,重做日志被写入重做日志缓冲区。在此之后,服务器进程才在数据高速缓存中修改数据。如果用户提交了事务,SCN也将被写入重做日志缓冲区,然后LGWR进程立即开始工作,将这个事务的重做日志和SCN一起写入重做日志文件,这个事务就算成功地执行结束了。而与这个事务有关的脏缓冲区这时并没有写入数据文件,而是由DBWR进程在适当的时候写入。
在这里向大家介绍一个概念,即SCN(系统改变号,System Change Number)。SCN是用于记录数据库变化的一个数字,它是一个正整数。当一个事务执行之后,便获得一个新的SCN,每个SCN在整个数据库中都是唯一的,而且所有SCN的值是递增的,随着数据库的运行,SCN不断增大,并且永远不会重复,也没有消耗完的时候。SCN被同时记录在数据文件、控制文件和重做日志文件中,如果这三个文件的SCN完全一致,数据库就达到了一个完全一致的状态。
现在我们考虑一个非常复杂的问题,Oracle如何利用重做日志保证数据库的一致性?如果发生了系统断电,用户执行的事务是否有效?Oracle如何利用重做日志进行数据库的恢复?
假设用户执行了一条DML命令,如UPDATE。假设在执行这条命令之前数据库的SCN值为2000,在执行这条DML命令之后,这个事务获得的SCN是2010。现在我们来分析两种常见的情况。
首先我们考虑用户没有提交事务的情况。根据DBWR进程LGWR进程的工作时机可知,这次事务带来的变化可能已经被写入了数据文件和重做日志文件,也可能没有。但是无论是否写入,这次事务都是无效的,因为新的SCN没有被写入数据文件、控制文件和重做日志文件,这三种文件中记录的还是原来的SCN值,即2000。如果此刻系统突然断电,那么数据库服务器在重新启动时,将检查这三种文件中记录的SCN,并且回退最后一个SCN之后的所有事务。也就是说,用户执行了一条DML命令,但是因为没有提交该事务,系统发生断电等故障时,数据将丢失,无法恢复。
现在再考虑事务被提交的情况。当用户执行COMMIT命令提交事务时,重做日志缓冲区中的重做日志和新的SCN将被写入重做日志文件。尽管这个事务所产生的脏缓冲区可能还没有被DBWR进程写入数据文件,但这个事务已经有效。考虑上面提到的UPDATE命令,这时重做日志文件记录的是新的SCN值,即2010,但是这个SCN值还没有被写入数据文件和控制文件。如果这三个文件的SCN不一致,那么重做日志文件中记录的SCN一定大于数据文件和控制文件中的SCN。如果此刻系统突然断电,那么数据库服务器在重新启动时,将检查这三种文件中记录的SCN,并且重新执行两个SCN之间的所有事务,然后将其中未提交的事务回滚,这样三种文件中的SCN将达到一致,然后才打开数据库,这时数据库达到了一致的状态。数据库的这种操作称为“实例恢复”,实例恢复是根据重做日志文件的内容进行的,这个过程由后台进程SMON完成。SMON进程将重做日志文件中记录的事务重新执行一次,从而保证了数据不会因为系统故障而丢失。
那么在系统运行过程中,三种文件中的SCN能不能达到一致呢?答案是肯定的,这要依赖于后台进程CKPT。当CKPT进程开始工作时,SCN将被写入数据文件和控制文件,使三种文件的SCN完全一致。同时CKPT进程通知DBWR进程开始工作,把脏缓冲区中的数据写入数据文件。这时数据库将达到完全一致的状态,系统断电时数据库将不受任何影响,也不需要进行实例恢复。
由此可见,只有当事务被提交后,才有可能进行实例恢复,用户的数据才不至于丢失。如果事务没有提交,数据是无法进行恢复的。