Online log
在线日志是分组的,一个库至少需要两组,默认是三组。多个组以循环方式使用。
每个组内可以有多个日志文件成员,互为镜像。默认情况下每个组只有一个成员。
要提高可靠性,应该为每个组至少配置两个成员,将这两个成员分配到不同的磁盘上。
可以通过alter system switch logfile;语句强制切换online日志文件组;
这时会建立一个检查点(也可以alter sytem checkpoint)强制建立一个检查点。
通过select * from v$log;语句可以查看在线日志组的详细信息。
status列显示了当前活动的日志组。
通过 select * from v$logfile;语句可以查看日志文件成员的详细信息。
创建新的日志组:
alter database add logfile group 4 ('/u01/oradata/REDO04_01.LOG','/u02/oradata/REDO04_02.log') size 50M;
alter database drop logfile group 4;
添加/删除日志组成员:
alter database add logfile member '/u02/oradata/REDO01_02.log' to group 1;
alter database drop logfile member '/u02/oradata/REDO01_02.log';
Archive log存放路径
相关参数有三个,log_archive_dest,log_archive_dest_n和db_recovery_file_dest.
如果log_archive_dest_n则使用log_archive_dest,如果log_archive_dest也没有设置,则使用db_recovery_file_dest.
*USE_DB_RECOVERY_FILE_DEST表示archive log存放位置是db_recovery_file_dest指定的目录。
更改log_archive_dest_n参数可更改归档日志目录,此外10g之后,可以生成多份日志的拷贝到不同位置,因此可以指定多个目录,例如:
alter system set log_archive_dest_1='location=/data/oracle/log1/archive_log';
alter system set log_archive_dest_2='location=/data/oracle/log2/archive_log';
通过设置关键词location或service设置本地归档或归档到STANDBY数据库。
这时log_archive_dest的指定无效且无法修改。
如需恢复到db_recovery_file_dest指定的目录,可以把上述log_archive_dest_n参数设为'location=USE_DB_RECOVERY_FILE_DEST'。
*如果只是把log_archive_dest_n参数设置为'',Archive destination会变成standby_archive_dest参数指定的位置。
需要重起数据库之后,才会恢复到db_recovery_file_dest指定的目录。
使用log_archive_dest参数最多可设置2个归档路径,
通过log_archive_dest设置一个主归档路径,通过log_archive_duplex_dest参数设置一个从归档路径。
所有的路径必须是本地的。这种方式主要在8i以前使用。
可以通过alter system archive log current;语句强制归档日志;
可以通过select name from v$archived_log;查看归档日志文件路径。
更改日志模式
如需更改LOG模式,需要关闭数据库,然后startup mount,然后调用下面的语句修改:
alter database noarchivelog/archivelog
之后alter database open来打开数据库。
此外,在NOARCHIVELOG模式下,一些操作,例如CREATE TABLE,除了数据字典的修改外,不会生成REDO日志。
使用INSERT /*+ APPEND*/语法的直接路径插入也不生成REDO日志,但是普通的INSERT操作还是会生成REDO日志。
在ARCHIVELOG模式运行下的数据库,无论是直接路径插入还是普通的插入,都会生成REDO日志,但是可以用NOLOGGING的方式进行一些操作。
1)在SQL语句中设置NOLOGGING
例如在CREATE TABLE语句中使用NOLOGGING,
create table t nologging as select * from all_objects;
除了数据字典的修改外,不会生成REDO日志,相对于不使用NOLOGGING,生成日志大大减少。(在我的测试环境上,从6.56M减少到143K)
需要注意,NOLOGGING不能避免所有后续操作生成redo。在上面创建的表T上进行的后续的“正常“操作(如INSERT、UPDATE 和DELETE)还是会生成日志。其他特殊的操作(如使用SQL*Loader的直接路径加载,或使用INSERT /*+ APPEND*/语法的直接路径插入)不生成日志(除非通过alter table t logging;语句,再次启用完全的日志模式)。
2)在段(表格或者索引)上设置NOLOGGING属性
例如alter index xxx nologging/logging;
这样重建这个索引的时候就不会生成重做日志。
在一个ARCHIVELOG模式的数据库,如果使用NOLOGGING得当,可以加快很多操作的速度。但是需要谨慎,操作后,必须尽快为受影响的数据文件建立一个新的基准备份。
Oracle9i Release 2之后,DBA可能把数据库置于FORCE LOGGING模式。在这种情况下,所有操作都会计入日志。
查询SELECT FORCE_LOGGING FROM V$DATABASE 可以查看是否强制为日志模式。
通过下面的操作来修改(不需要重起数据库)
ALTER DATABASE FORCE LOGGING;
ALTER TABLESPACE tablespace_name FORCE LOGGING;
取消FORCE LOGGING模式
ALTER DATABASE NO FORCE LOGGING;
ALTER TABLESPACE tablespace_name NO FORCE LOGGING;
NOARCHIVELOG模式和ARCHIVELOG模式下REDO日志生成量对比
NOARCHIVELOG ARCHIVELOG ARCHIVELOG+NOLOGGING ----------------------------------------------------------------- CREATE TABLE AS 107964 6773704 142592 INSERT 6630644 6628728 6627988 INSERT /*+ APPEND*/ 60312 6722784 60088
*如果FORCE_LOGGING=YES,得到的结果同ARCHIVELOG模式下的结果。
在一个NOARCHIVELOG模式数据库下进行试验的结果:
tony@MYTEST2> select log_mode from v$database; LOG_MODE ------------ NOARCHIVELOG tony@MYTEST2> create or replace function get_stat_val( p_name in varchar2 ) return number 2 as 3 l_val number; 4 begin 5 select b.value into l_val 6 from v$statname a, v$mystat b 7 where a.statistic# = b.statistic# 8 and a.name = p_name; 9 return l_val; 10 end; 11 / Function created. tony@MYTEST2> variable redo number tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> create table t as select * from all_objects; Table created. tony@MYTEST2> exec dbms_output.put_line((get_stat_val('redo size')-:redo) - > || ' bytes of redo generated...'); 107964 bytes of redo generated... PL/SQL procedure successfully completed. tony@MYTEST2> truncate table t; Table truncated. tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> insert into t select * from all_objects; 53878 rows created. tony@MYTEST2> exec dbms_output.put_line((get_stat_val('redo size')-:redo) - > || ' bytes of redo generated...'); 6630644 bytes of redo generated... PL/SQL procedure successfully completed. tony@MYTEST2> truncate table t; Table truncated. tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> insert /*+ APPEND */ into t select * from all_objects; 53878 rows created. tony@MYTEST2> exec dbms_output.put_line((get_stat_val('redo size')-:redo) - > || ' bytes of redo generated...'); 60312 bytes of redo generated... PL/SQL procedure successfully completed.
将数据库改为ARCHIVELOG模式下进行试验的结果:
tony@MYTEST2> select log_mode from v$database LOG_MODE ------------ ARCHIVELOG tony@MYTEST2> variable redo number tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> create table t as select * from all_objects; Table created. tony@MYTEST2> exec dbms_output.put_line((get_stat_val('redo size')-:redo) - > || ' bytes of redo generated...'); 6773704 bytes of redo generated... PL/SQL procedure successfully completed. tony@MYTEST2> truncate table t; Table truncated. tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> insert into t select * from all_objects; 53878 rows created. tony@MYTEST2> exec dbms_output.put_line((get_stat_val('redo size')-:redo) - > || ' bytes of redo generated...'); 6628728 bytes of redo generated... PL/SQL procedure successfully completed. tony@MYTEST2> truncate table t; Table truncated. tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> insert /*+ APPEND */ into t select * from all_objects; 53878 rows created. tony@MYTEST2> exec dbms_output.put_line((get_stat_val('redo size')-:redo) - > || ' bytes of redo generated...'); 6722784 bytes of redo generated... PL/SQL procedure successfully completed. tony@MYTEST2> drop table t; Table dropped. tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> create table t nologging as select * from all_objects; Table created. tony@MYTEST2> exec dbms_output.put_line((get_stat_val('redo size')-:redo) - > || ' bytes of redo generated...'); 142592 bytes of redo generated... PL/SQL procedure successfully completed. tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> truncate table t; Table truncated. tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> insert into t select * from all_objects; 53878 rows created. tony@MYTEST2> exec dbms_output.put_line((get_stat_val('redo size')-:redo) - > || ' bytes of redo generated...'); 6627988 bytes of redo generated... PL/SQL procedure successfully completed. tony@MYTEST2> truncate table t; Table truncated. tony@MYTEST2> exec :redo := get_stat_val( 'redo size' ); PL/SQL procedure successfully completed. tony@MYTEST2> insert /*+ APPEND */ into t select * from all_objects; 53878 rows created. tony@MYTEST2> exec dbms_output.put_line((get_stat_val('redo size')-:redo) - > || ' bytes of redo generated...'); 60088 bytes of redo generated... PL/SQL procedure successfully completed.