一、重做日志概述
重做日志对于Oracle数据库的恢复来说是十分关键的,redo log包含两个或更多的被预先分配的文件,在文件当中记录着数据库内发生的所有改变。每一个数据库的实例都与其redo log相关联,目的是保证在实例失败时以保护数据库中数据的安全。(维护数据的一致性,完整性)
1、重做线程
在多实例环境中,每个实例的重做日志也被称为重做线程(redo thread)。在传统的单实例环境中,仅有一个实例访问数据库,所以只有一个重做线程,在Oracle的RAC集群环境中,两个或更多的实例同时访问一个数据库,每个实例都有它自己的重做线程,其目的为,每个实例分别使用自己的重做线程以避免对一个单一的重做日志文件的争用,从而得以排除在这方面的潜在的性能瓶颈。
2、重做日志文件的内容
重做日志文件中包含的是重做记录(redo record),也被称为重做条目,重做记录是由一组改变向量(change vector)构成,每一个改变向量描述了数据库中每一个数据块(oracle data block)的变化,通过使用重做记录,能够恢复数据库产生的所有变化,包括回滚段,因此,重做日志也需要保护回滚数据。当使用重做日志文件恢复数据库时,数据库读取重做日志中的改变向量并应用到与之相关的数据块上。例如:修改雇员表中的薪水字段,在redo log中将会产生一条重做记录,该重做记录描述了表段中数据块的变化。其包含如下change vector:undo redo --> undo --> redo --> do.
重做记录被缓存在SGA的redo log buffer缓冲区中,这个缓冲区是可循环写入的,缓冲区中的内容通过LGWR进程写入重做日志文件中。每当一个事务提交时,LGWR将该事物产生的redo records从redo log buffer写入重做日志文件,并且分配SCN(system change number)用以标识每次提交的redo records,仅当该事务的所有redo records都被安全的写入了磁盘文件中后,才会出现事务已被提交的提示信息;重做记录也可以在事务提交之前写入重做日志文件,如果重做日志缓冲区已满或者由于其他的事务提交,LGWR将重做日志缓冲区中的重做记录写入重做日志文件,尽管其中一些重做记录没有被提交,在必要的时候,数据库会回滚这些变化。
3、重做记录如何被写入重做日志文件
在一个Oracle数据库中最少需要两个重做日志文件,以保证在其中一个日志归档时(archivelog mode),另一个日志是可以被写入的。LGWR以一种循环的方式交替的使用重做日志文件。当前的重做日志文件被写满时,LGWR开始写另一个可用的重做日志文件,当最后一个重做日志文件被写满时,LGWR又会反过来写第一个重做日志文件。重做日志文件是否可被LGWR立即重用取决于数据库是否启用了归档模式:
a、在非归档模式中,在日志切换之前,日志中记录的数据变化被同步到数据文件之后,LGWR将可以重用该重做日志文件。
b、在归档模式中,在日志切换之前,必须保证数据的变化被同步到数据文件且该日志已经完成归档之后,LGWR才可以重用该重做日志文件。
4、ACTIVE和INACTIVE状态的区别
ACTIVE:以ACTIVE标识的重做日志文件对于实例恢复来说是必须的
INACTIVE:以INACTIVE标识的重做日志文件对于实例恢复来说不是必须的
5、日志切换和日志序列号
日志切换是指LGWR停止对一个日志文件的写入操作并开始对另一个日志文件执行写入操作。日志切换通常发生在当前日志已被写满的情况下。但是,并不是只有在当前日志被写满时才会发生日志切换,可以配置日志切换发生的频率,而不管日志文件是否被写满,另外还可以手动执行强制的日志切换操作。
在发生日志切换时,Oracle为每一个重做日志文件分配日志序列号,在归档模式下,归档日志也使用该序列号。每一个在线或归档重做日志文件都通过这个序列号来唯一标识。在崩溃、实例、介质修复期间,数据库将正确的,以日志序列号(log sequence)的递增顺序应用这些在线重做日志或归档重做日志。
二、规划重做日志
1、多路复用重做日志文件
为了防止故障波及重做日志本身,Oracle允许使用多路复用重做日志,这意味着两个或两个以上相同的重做日志的副本可以保存在单独的位置,即使重做日志的副本都在同一磁盘上,冗也余可以帮助防止I/O错误,文件损坏等等情况的出现。当重做日志文件被设置为多路复用时,LGWR同时写入相同的信息到多个重做日志文件的副本,从而消除由于单点失败引起的故障。
重做日志的多路复用是通过创建日志文件组的方式来实现的,一个日志文件组包含一个日志文件盒它的多个副本,日志组中的每一个日志成员都是完全相同的,日志文件组被一个数字标识,例如group 1,group 2,group 3,等等。在日志切换之后,当前日志组中的成员同时成为active状态,也就是说,它们将被LGWR进程同时写入,并被分配了一个相同的日志序列号
2、重做日志发生故障时数据库的反应
场景 | LGWR进程行为 |
LGWR成功的写入了日志组中的一个成员 | LGWR将重做记录信息写入可用的日志成员,将忽略不可用的日志成员 |
LGWR无法访问以一个日志组,因为该日志组必须完成归档 | 数据库操作将展示停止,知道该日志组可用或该日志组中的日志完成归档 |
由于介质损坏,下一个日志组的中所有成员均无法访问 | 数据库将返回一个错误,数据库实例将被关闭,这时可能需要执行介质恢复,如果数据库检查点已经超过该日志文件,则不需要执行介质恢复,只需要删除损坏日志文件组即可 |
当前日志文件组中的所有成员突然都不可用 | 数据库将返回一个错误,数据库实例将立即被关闭,这时可能需要执行介质恢复。如果介质上包含的文件并没有丢失,而只是因为其他原因以外被关闭,那么可能不需要介质恢复,在其恢复后进行实例修复即可。 |
3、合法的和非法的配置重做日志
在大多是情况下,多路复用的重做日志文件都是对称的:所有的日志文件组拥有相同的成员数量,然后Oracle并没有硬性的规定所有日志文件组的成员数量必须一致。例如:group 1有两个成员,group 2仅仅只有一个成员,这样是合法的,实例对重做日志文件的唯一要求就是必须至少保证其有两个组。
4、日志成员应被置于不同的磁盘上
这和控制文件有些类似,好处也不用多说,就不进行过多说明了。
5、规划重做日志文件的大小
同意组中的成员必须拥有相同的文件大小,不同组中的重做日志文件大小不必一致。但是不推荐这样做,这样做导致的问题我们都可以估计到,那就是日志切换的时间不统一。总体来说,规划重做日志文件的尺寸应兼顾性能与效率,同时还要结合数据库的繁忙程度来考虑。重做日志文件的尺寸最少为4MB。
6、控制归档延迟
使用初始化参数archive_lag_target控制归档延迟。
三、管理重做日志组及其成员
1、创建日志文件组
方法一:
SQL> alter database add logfile ('/u01/app/oracle/oradata/redo04.log') size 51200k;
Database altered.
SQL> select group#,member from v$logfile;
GROUP# MEMBER
---------- --------------------------------------------------
3 /u01/app/oracle/oradata/prac/redo03.log
2 /u01/app/oracle/oradata/prac/redo02.log
1 /u01/app/oracle/oradata/prac/redo01.log
4 /u01/app/oracle/oradata/redo04.log
方法二:
SQL> alter database add logfile group 5 ('/u01/app/oracle/oradata/redo05a.log') size 51200k;
Database altered.
SQL> select group#,member from v$logfile;
GROUP# MEMBER
---------- --------------------------------------------------
3 /u01/app/oracle/oradata/prac/redo03.log
2 /u01/app/oracle/oradata/prac/redo02.log
1 /u01/app/oracle/oradata/prac/redo01.log
4 /u01/app/oracle/oradata/redo04.log
4 /u01/app/oracle/oradata/redo04-b.log
4 /u01/app/oracle/oradata/redo04-c.log
5 /u01/app/oracle/oradata/redo05a.log
7 rows selected.
2、为日志文件组添加成员
方法一:
SQL> alter database add logfile member '/u01/app/oracle/oradata/redo04-b.log' to group 4; //这里就不用指定成员的大小了,因为组内成员大小必须一致。
Database altered.
SQL> select group#,member from v$logfile;
GROUP# MEMBER
---------- --------------------------------------------------
3 /u01/app/oracle/oradata/prac/redo03.log
2 /u01/app/oracle/oradata/prac/redo02.log
1 /u01/app/oracle/oradata/prac/redo01.log
4 /u01/app/oracle/oradata/redo04.log
4 /u01/app/oracle/oradata/redo04-b.log
方法二:
Database altered.
SQL> select group#,member from v$logfile;
GROUP# MEMBER
---------- --------------------------------------------------
3 /u01/app/oracle/oradata/prac/redo03.log
2 /u01/app/oracle/oradata/prac/redo02.log
1 /u01/app/oracle/oradata/prac/redo01.log
4 /u01/app/oracle/oradata/redo04.log
4 /u01/app/oracle/oradata/redo04-b.log
4 /u01/app/oracle/oradata/redo04-c.log
3、改变存储位置和重命名
step 1、关闭数据库,shutdown immediate
step 2、拷贝文件到新的存储位置,cp、mv等命令
step 3、启动数据库到mount状态,执行 alter database rename file '成员1源路径','成员2源路径' to '成员1新路径','成员2新路径';
step 4、打开数据库,alter database open;
4、删除日志文件组及其成员
删除日志文件组时要考虑如下限制条件:
a、Oracle实例要求一个数据库中必须至少保留两组日志文件。
b、只能删除inactive状态的日志文件组,如果必须删除active状态的组,那么需要先执行日志切换。
SQL> select group#,status from v$log;
GROUP# STATUS
---------- ----------------
1 CURRENT
2 UNUSED
3 UNUSED
4 UNUSED
SQL> alter database drop logfile group 1;
alter database drop logfile group 1
*
ERROR at line 1:
ORA-01623: log 1 is current log for instance prac (thread 1) - cannot drop
ORA-00312: online log 1 thread 1: '/u01/app/oracle/oradata/prac/redo01.log'
c、确保日志文件组被删除前已经完成了归档。
SQL> alter database drop logfile group 5;
Database altered.
SQL> select group#,member from v$logfile;
GROUP# MEMBER
---------- --------------------------------------------------
3 /u01/app/oracle/oradata/prac/redo03.log
2 /u01/app/oracle/oradata/prac/redo02.log
1 /u01/app/oracle/oradata/prac/redo01.log
4 /u01/app/oracle/oradata/redo04.log
4 /u01/app/oracle/oradata/redo04-b.log
4 /u01/app/oracle/oradata/redo04-c.log
6 rows selected.
5、删除日志成员
在删除日志成员时应考虑如下限制条件:
a、无法删除当前组的成员。
SQL> alter database drop logfile '/u01/app/oracle/oradata/prac/redo01.log';
alter database drop logfile '/u01/app/oracle/oradata/prac/redo01.log'
*
ERROR at line 1:
ORA-01623: log 1 is current log for instance prac (thread 1) - cannot drop
ORA-00312: online log 1 thread 1: '/u01/app/oracle/oradata/prac/redo01.log'
b、当组中仅剩唯一成员时,无法删除该成员,如确实需删除,可以直接删除组。
SQL> alter database drop logfile member '/u01/app/oracle/oradata/redo05a.log';
alter database drop logfile member '/u01/app/oracle/oradata/redo05a.log'
*
ERROR at line 1:
ORA-00361: cannot remove last log member /u01/app/oracle/oradata/redo05a.log for group 5
c、从一个重做日志组中删除日志成员后,操作系统并不会删除磁盘文件,在确保重做日志文件删除成功后,然后使用操作系统命令来删除掉重做日志文件。
6、重做日志切换与检查点:
通常写满一个日志组后开始写下一个重做日志文件组时,称发生一次日志切换。
可以通过设置初始化参数ARCHIVE_LAG_TARGET使日志切换按一定的时间间隔进行,在必要的时候也可以执行alter system switch logfile 来强制切换。
7、清除重做日志文件组:
alter database clear logfile group5;
下列两种情况无法清除日志文件组:
**数据库只有两组日志文件组;
**需要清除的日志文件组时当前正在重做日志文件组
如果要清除的重做日志文件组尚未归档,必须使用unarchive子句,一面对这个重做日志文件组进行归档,如:
alter database clear unarchive logfile group 5;
四、查看日志文件信息:
v$log 包含从控制文件中获取的所有重做日志文件组的基本信息
v$logfile 包含重做日志文件及其成员的文件信息
v$log_history 包含重做日志文件的历史信息