Oracle的nologging属性是非常容易被滥用的。在我们之前的文章中,探讨过append+nologging对于Redo Log的影响。从文章的结论看:如果我们使用append配合nologging,的确是可以减少Redo Log的生成的。
但是,这样做真的有好处吗?
希望减少Redo Log生成的思路无非是:Redo Log生成量少了,这样在LGWR写入的量就少了,从而带来的物理IO和日志切换动作就少了。但是,随着带来的问题是:日志少了真的没有问题吗?
Oracle Redo Log是数据库的重要对象,原始提出Redo Log的目的在于“日志在先,数据恢复”。从宏观上看,Redo Log是保证数据库事务一致性的手段。但更重要的是,Redo Log是数据库内部一致性、数据库完全恢复和高可用性组件(DG、OGG)的重要技术基础。
Redo Log是描述数据块变化的记录信息,其中包括逻辑变化和物理变化。本篇就通过实验来确定Append+Nologging给备份还原带来的问题。
1、环境准备和备份
我们选择Oracle 11gR2进行测试。为了保证一致性,我们首先进行一次热备份动作。
RMAN> backup database plus archivelog delete all input;
Starting backup at 10-DEC-13
current log archived
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=38 device type=DISK
(篇幅原因,有省略……)
Starting Control File and SPFILE Autobackup at 10-DEC-13
piece handle=/u01/flash_recovery_area/WILSON/autobackup/2013_12_10/o1_mf_s_833787521_9bdo43ol_.bkp comment=NONE
Finished Control File and SPFILE Autobackup at 10-DEC-13
此时,配合归档模式,我们是可以实现完全恢复的。
RMAN> list backup;
List of Backup Sets
===================
BS Key Type LV Size Device Type Elapsed Time Completion Time
------- ---- -- ---------- ----------- ------------ ---------------
130 Full 1.31G DISK 00:01:55 10-DEC-13
BP Key: 130 Status: AVAILABLE Compressed: NO Tag: TAG20131210T073642
Piece Name: /u01/flash_recovery_area/WILSON/backupset/2013_12_10/o1_mf_nnndf_TAG20131210T073642_9bdo0djj_.bkp
List of Datafiles in backup set 130
(篇幅原因,有省略……)
SPFILE Included: Modification time: 10-DEC-13
SPFILE db_unique_name: WILSON
Control File Included: Ckp SCN: 5260073 Ckp time: 10-DEC-13
2、一次append+nologging动作
我们创建一张数据表T,将其nologging属性设置为Y。
SQL> create table t as select * from dba_objects where 1=0;
Table created
SQL> alter table t nologging;
Table altered
使用insert append插入数据。
SQL> insert /*+append*/ into t select * from dba_objects;
72768 rows inserted
SQL> commit;
Commit complete
3、启动恢复过程
如果此时发生系统故障,数据丢失,需要进行数据恢复动作。试图使用RMAN来进行完全恢复。
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
SQL> conn / as sysdba
Connected to an idle instance.
SQL> startup mount;
ORACLE instance started.
Total System Global Area 849530880 bytes
Fixed Size 1339824 bytes
Variable Size 511708752 bytes
Database Buffers 331350016 bytes
Redo Buffers 5132288 bytes
Database mounted.
启用RMAN恢复过程。
--Restore过程
RMAN> restore database;
Starting restore at 10-DEC-13
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=18 device type=DISK
channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00001 to
(篇幅原因,有省略……)
channel ORA_DISK_1: piece handle=/u01/flash_recovery_area/WILSON/backupset/2013_12_10/o1_mf_nnndf_TAG20131210T073642_9bdo0djj_.bkp tag=TAG20131210T073642
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:07:05
Finished restore at 10-DEC-13
--Recover应用Redo Log
RMAN> recover database;
Starting recover at 10-DEC-13
using channel ORA_DISK_1
starting media recovery
media recovery complete, elapsed time: 00:00:12
Finished recover at 10-DEC-13
RMAN>
恢复过程没有明显的错误标志,恢复似乎是成功了。之后打开数据库。
RMAN> alter database open;
database opened
4、坏块出现
回到sqlplus环境,检查数据表。
SQL> conn scott/tiger@wilson;
Connected to Oracle Database 11g Enterprise Edition Release 11.2.0.1.0
Connected as scott
SQL> select count(*) from t;
select count(*) from t
ORA-01578: ORACLE 数据块损坏 (文件号 4, 块号 3611)
ORA-01110: 数据文件 4: '/u01/oradata/WILSON/datafile/o1_mf_users_805nxydh_.dbf'
ORA-26040: 数据块是使用 NOLOGGING 选项加载的
报错坏块!
这个过程也是可以理解的。Redo Log是描述数据变化全过程的过程化数据。完全恢复是建立在重演Redo Log过程,以达到最终数据一致的目的。Nologging通过额外的手段减少了redo log的生成,必然有一部分重要的变化数据是缺失的。那么,nologging部分还原出来之后,就难以保证数据一致性。
至此,我们可以看出nologging的问题,就是影响数据的恢复过程连续性。让我们设想一种场景:如果在生产环境中使用nologging append方法之后,没有发现后续的问题,也没有进行全备份动作。一旦发生故障,需要进行数据恢复时就遇到麻烦。不仅仅是该数据表可能有问题,其他数据表引用的该数据表关系也会受到影响。
更进一步,如果我们配置了Data Guard、OGG这种严重依赖Redo Log Apply的技术组件,我们更可能会导致源数据库正确、但是备份端出现坏块。
5、处理方法
Nologging是一个综合性的过程。在Oracle数据库中,数据库层面、表空间和数据表三个层次均有nologging配置属性。三者之前的配置关系和作用是相互的。
下面我们通过数据库层面的nologging,开启强制日志(force logging)功能,一定程度上可以避免由于nologging带来的数据恢复问题。注意:由于条件的限制,笔者使用了另外的数据库,但是不影响结果。
SQL> archive log list;
Database log mode Archive Mode
Automatic archival Enabled
Archive destination USE_DB_RECOVERY_FILE_DEST
Oldest online log sequence 110
Next log sequence to archive 112
Current log sequence 112
SQL> alter database open;
Database altered.
SQL> alter database force logging;
Database altered.
SQL> select log_mode, force_logging from v$database;
LOG_MODE FORCE_LOGGING
------------ -------------
ARCHIVELOG YES
备份数据过程省略,建立一个全新的全备份。之后创建数据表。
SQL> create table t nologging as select * from dba_objects where 1=0;
Table created
SQL> alter table t move tablespace users;
Table altered
SQL> select logging from dba_tables where owner='SYS' and table_name='T';
LOGGING
-------
NO
SQL> insert /*+append*/ into t select * from dba_objects;
75607 rows inserted
SQL> commit;
Commit complete
SQL> select count(*) from t;
COUNT(*)
----------
75607
启动还原过程,从全备份开始,前推Redo Log进行完全恢复。
--start到mount状态省略
RMAN> restore database;
Starting restore at 11-DEC-13
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile backup set restore
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
channel ORA_DISK_1: restoring datafile 00001 to /u01/app/oradata/ORA11G/datafile/o1_mf_system_92t6zl2m_.dbf
channel ORA_DISK_1: restoring datafile 00002 to /u01/app/oradata/ORA11G/datafile/o1_mf_sysaux_92t6zl5k_.dbf
channel ORA_DISK_1: restoring datafile 00003 to /u01/app/oradata/ORA11G/datafile/o1_mf_undotbs1_92t6zl6d_.dbf
channel ORA_DISK_1: restoring datafile 00004 to /u01/app/oradata/ORA11G/datafile/o1_mf_users_92t6zl83_.dbf
channel ORA_DISK_1: restoring datafile 00005 to /u01/app/oradata/ORA11G/datafile/o1_mf_example_92t74b1f_.dbf
channel ORA_DISK_1: restoring datafile 00006 to /u01/app/oradata/ORA11G/datafile/o1_mf_trcatbl_96mlzz0j_.dbf
channel ORA_DISK_1: restoring datafile 00007 to /u01/app/oradata/ORA11G/datafile/o1_mf_test1_971dp6kb_.dbf
channel ORA_DISK_1: restoring datafile 00008 to /u01/app/oradata/ORA11G/datafile/o1_mf_test2_971dqkh0_.dbf
channel ORA_DISK_1: reading from backup piece /u01/app/fast_recovery_area/ORA11G/backupset/2013_12_11/o1_mf_nnndf_TAG20131211T091503_9bhh4qdp_.bkp
channel ORA_DISK_1: piece handle=/u01/app/fast_recovery_area/ORA11G/backupset/2013_12_11/o1_mf_nnndf_TAG20131211T091503_9bhh4qdp_.bkp tag=TAG20131211T091503
channel ORA_DISK_1: restored backup piece 1
channel ORA_DISK_1: restore complete, elapsed time: 00:01:15
Finished restore at 11-DEC-13
RMAN> recover database;
Starting recover at 11-DEC-13
using channel ORA_DISK_1
starting media recovery
media recovery complete, elapsed time: 00:00:05
Finished recover at 11-DEC-13
RMAN> alter database open;
database opened
启动数据库之后,检查数据表状态。
SQL> select count(*) from t;
COUNT(*)
----------
75607
SQL> select logging from dba_tables where owner='SYS' and table_name='T';
LOGGING
-------
NO
从实验结果可知,利用force logging,可以一定程度上避免由于数据表nologging引起的坏块问题。
6、结论与反思
在这个案例中,我们看到了日常工作中常用nologging的潜在问题。在实际工作中,特别是大数据、数据仓库系统应用,很多运维人员甚至开发人员都喜欢使用nologging来处理数据。这样的现象是由于对Oracle Redo Log重要性没有明确认识。一旦进行恢复,就容易大祸临头。
笔者认为:nologging的使用是有条件和场合的。如果我们是在准备数据阶段,关闭归档、使用nologging都是允许的手段。一旦上线,切记要主要避免使用这样的操作方式。也许在性能上有一些优势,但是带来的风险不是我们可以承担的。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/17203031/viewspace-1063011/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/17203031/viewspace-1063011/