众所周知,如果一个库没有设置为force logging,而这个库在归档模式下,对表的插入操作如果采用APPEND模式,并且表设置为nologging则不会为插入的数据产生日志。那么对LOB列的存储也设置为NOLOGGING,会产生什么样的结果?

测试环境:Oracle 9.2.0.1 for Win,非归档模式

create table test1.t1(id int not null, out_row clob)
lob(out_row) store as (disable storage in row nocache nologging);

关闭数据库,备份数据文件users01.dbf

启动数据库,将表中插入数据:

insert into test1.t1 select rownum,rpad('x',5000,'x') from dba_objects where rownum<=100;

select * from test1.t1;

能够正常返回100行数据。

关闭数据库,用备份的文件还原文件users01.dbf,启动数据库时报错:

数据库装载完毕。
ORA-01113: ?? 5 ??????
ORA-01110: ???? 5: 'D:\ORACLE\ORADATA\XJ\USERS01.DBF'

SQL> recover datafile 5;
完成介质恢复。

SQL> alter session set nls_language=american;

Session altered.
SQL> alter database open;

Database altered.

SQL> select count(*) from test1.t1;

  COUNT(*)
----------
       100

SQL> select * from test1.t1;
ERROR:
ORA-01578: ORACLE data block corrupted (file # 5, block # 61)
ORA-26040: Data block was loaded using the NOLOGGING option
ORA-01110: data file 5: 'D:\ORACLE\ORADATA\XJ\USERS01.DBF'

由此可以看出,在此前的插入操作中,没有对LOB数据产生日志。

我们将test1.t1删除,再重新创建,只是将LOB设置为LOGGING。

SQL> drop table test1.t1;

表已丢弃。

SQL> create table test1.t1 (id number not  null,out_row clob)
  2  lob (out_row) store as (disable storage in row nocache logging);

重复上步实验过程,发现LOGGING模式下的LOB能够正常恢复。

将数据库设置为归档模式,重复以上测试过程,发现NOLOGGING模式下的LOB仍然不能恢复。

将数据库设置为FORCE LOGGING模式,重复以上测试过程,发现NOLOGGING模式下的LOB能够正常恢复。

经过进一步测试,对LOB字段进行UPDATE也会产生上述实验结果。

在这个测试中使用了一个比较“笨”的办法。观察LOB列是否产生日志,可以观察redo size和分析日志文件进行。在此不在细述。

经过测试,发现IN ROW的LOB列与表中的其他列数据是一致的LOGGING行为。

注意:LOB列如果设置为CACHE,则只能是LOGGING模式。

由此引出一个问题,由于对LOB列设置为NOLOGGING,虽然能够提高数据插入速度,为数据恢复设置了一道难关。需要此种情况下的备份恢复策略,或者将LOB列设置为LOGGING模式。

Trackback

3 comments untill now

  1. 众所周知,如果一个库没有设置为force logging,而这个库在归档模式下,对表的插入操作如果采用APPEND模式,并且表设置为nologging则不会为插入的数据产生日志!!!

    我这边没有9i环境!

    10g和你上面的结果有出入

    SQL> select * from v$version;

    BANNER
    ——————————————————————————–
    Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 – Prod
    PL/SQL Release 10.2.0.1.0 – Production
    CORE 10.2.0.1.0 Production
    TNS for Linux: Version 10.2.0.1.0 – Production
    NLSRTL Version 10.2.0.1.0 – Production

    SQL> create table t as select * from dba_objects where 1=0;

    Table created.

    SQL> Select FORCE_LOGGING from V$DATABASE;

    FORCE_
    ——
    NO

    SQL> archive log list
    Database log mode Archive Mode
    Automatic archival Enabled
    Archive destination USE_DB_RECOVERY_FILE_DEST
    Oldest online log sequence 213
    Next log sequence to archive 215

    SQL> alter table t nologging;

    Table altered.

    SQL> SELECT VALUE
    2 FROM v$mystat, v$statname
    3 WHERE v$mystat.statistic# = v$statname.statistic#
    4 AND v$statname.NAME = ‘redo size';

    VALUE
    ———-
    2088

    SQL> insert /*+ append */ into t select * from dba_objects;

    49802 rows created.

    SQL> SELECT VALUE
    2 FROM v$mystat, v$statname
    3 WHERE v$mystat.statistic# = v$statname.statistic#
    4 AND v$statname.NAME = ‘redo size';

    VALUE
    ———-
    59260

    [回复]

    老熊 回复:

    @stronghearted, 谢谢你的回复,不过我这里说的是:不会为插入的“数据”产生日志,对于其他一些操作,比如空间管理,数据字典的操作,仍然会产生日志的,你这个测试,只有50多K的日志,显然不会是插入的数据产生的。

    [回复]

  2. 记得以前有eygle有篇文章,去找了一下
    http://www.eygle.com/faq/Nologging&append.htm

    [回复]

Add your comment now