数据库可以有两种LOG模式,ARCHIVELOG模式和NOARCHIVELOG模式。
NOARCHIVELOG模式在线重做日志写满以后不会被归档,因此出现故障后无法恢复。
可以使用select log_mode from v$database语句来查询,或者在sysdba权限下使用archive log list语句来查询当前的LOG模式。
例如:
sys@ORA11GR2> archive log list
Database log mode Archive Mode
Automatic archival Enabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 18
Next log sequence to archive 20
Current log sequence 20

如需更改LOG模式,需要关闭数据库,然后startup mount,然后调用下面的语句修改:
alter database noarchivelog/archivelog
之后alter database open来打开数据库。

更改log_archive_dest_1参数可更改归档日志目录(pfile/spfile中参数db_recovery_file_dest指定的目录将无效),此外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';
如需恢复到db_recovery_file_dest指定的目录,可以把上述log_archive_dest_n参数设为空('')。

可以通过alter system archive log current;语句强制归档日志;
可以通过select name from v$archived_log;查看归档日志文件路径。

此外,在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 可以查看是否强制为日志模式。

NOARCHIVELOG模式和ARCHIVELOG模式下REDO日志生成量对比

NOARCHIVELOG ARCHIVELOG ARCHIVELOG+NOLOGGING ----------------------------------------------------------------- CREATE TABLE AS 107964 6773704 142592 INSERT 6630644 6628728 6627988 INSERT /*+ APPEND*/ 60312 6722784 60088

在一个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.