《Oracle编程艺术》学习笔记(19)-数据库日志模式

数据库可以有两种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


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.


 

 

 

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值