众所周知我们的Data Guard数据同步是基于日志流的。所以在主库执行nologging操作是不被允许的。这也就是为什么我们需要在配置Data Guard阶段需要使用Force Logging。但是这也会带来很多问题(SQL执行效率),例如:当我们使用数据泵进行迁移时我们希望最少停机时间完成,这时候我们就可能会考虑到以最小日志导入的方式以加快导入速度,然后重新同步备库。
在一些场景中,我们会去使用nologging操作去节省大量数据插入的时间,而这种操作所带来的问题就是,如果该库在有备库的情况下,因为主库的nologging插入操作不会生成redo,所以不会在备库上传输和应用,这会导致备库的数据出现问题。
在Oracle 11g,如果遇到这样的问题,可以通过在备库恢复有问题的数据文件来解决问题,示例如下:
在一个具有主备关系的主库上将force_logging设置为nologging模式,随后创建一张表,设置为nologging模式
-
SQL> alter database no force logging;
-
SQL> create table DEMO tablespace users pctfree 99 as select rownum n from xmltable('1 to 1000');
-
SQL> alter table DEMO nologging;
之后使用/* +append*/插入数据并提交
-
SQL> insert /*+ append */ into DEMO select rownum n from xmltable('1 to 100000');
-
SQL> commit
这时候在备库对该表进行查询会看到如下报错信息
-
SQL>select count(1) from demo;
-
select count(1) from demo
-
*
-
ERROR at line 1:
-
ORA-01578: ORACLE data block corrupted (file # 4, block # 819)
-
ORA-01110: data file 4: '/data/data1/ORCL2/datafile/o1_mf_users_3ft1e9qb_.dbf'
-
ORA-26040: Data block was loaded using the NOLOGGING option
而要修复这个问题,需要将包含缺少的数据的数据文件从主库复制到物理备库。
步骤一
1、查询主库
-
SQL> SELECT NAME, UNRECOVERABLE_CHANGE# FROM V$DATAFILE;
-
NAME UNRECOVERABLE_CHANGE#
-
--------------------------------------------------------------------------- ---------------------
-
+DATADG/orcl/datafile/system.270.972381717 0
-
+DATADG/orcl/datafile/sysaux.265.972381717 0
-
+DATADG/orcl/datafile/undotbs1.261.972381717 0
-
+DATADG/orcl/datafile/users.259.972381717 6252054
-
+DATADG/orcl/datafile/example.264.972381807 0
-
+DATADG/orcl/datafile/undotbs2.258.972381927 0
-
+DATADG/orcl/datafile/example.266.972400297 0
-
+DATADG/orcl/datafile/ax.268.973612569 0
2、查询备库
-
sys@ORCL>SELECT NAME, UNRECOVERABLE_CHANGE# FROM V$DATAFILE;
-
NAME UNRECOVERABLE_CHANGE#
-
--------------------------------------------------------------------------- ---------------------
-
/data/data1/ORCL2/datafile/o1_mf_system_3dt1e9op_.dbf 0
-
/data/data1/ORCL2/datafile/o1_mf_sysaux_3ct1e9nb_.dbf 0
-
/data/data1/ORCL2/datafile/o1_mf_undotbs1_3gt1e9qq_.dbf 0
-
/data/data1/ORCL2/datafile/o1_mf_users_3ft1e9qb_.dbf 5383754
-
/data/data1/ORCL2/datafile/o1_mf_example_3et1e9ps_.dbf 0
-
/data/data1/ORCL2/datafile/o1_mf_undotbs2_3ht1e9r1_.dbf 0
-
/data/data1/ORCL2/datafile/o1_mf_example_3at1e9nb_.dbf 0
-
/data/data1/ORCL2/datafile/o1_mf_ax_3bt1e9nb_.dbf 0
3、比较主数据库和备用数据库的查询结果
在两个查询结果中比较UNRECOVERABLE_CHANGE#列的值。如果主库中UNRECOVERABLE_CHANGE#列的值大于备库中的同一列,则需要将这些数据文件在备库恢复。
步骤二
将主库对应的数据文件拷贝至备库
-
SQL> alter tablespace users begin backup
-
SQL> exit
-
ASMCMD>cp +DATADG/orcl/datafile/users.259.972381717 /tmp
-
$ scp /tmp/users.259.972381717 10.10.60.123:/data/data1/ORCL2/datafile/
-
SQL> alter tablespace users end backup
步骤三
备库将旧的数据文件rename至新的数据文件
-
SQL> alter database recover managed standby database cancel;
-
SQL> alter system set standby_file_management=manual; #在备库执行rename操作时,需要此参数为manual
-
SQL> alter database rename file '/data/data1/ORCL2/datafile/o1_mf_users_3ft1e9qb_.dbf' to '/data/data1/ORCL2/datafile/users.259.972381717';
-
SQL> alter system set standby_file_management=auto;
-
SQL> alter database recover managed standby database using current logfile disconnect from session;
之后就可以在备库查询到实例表DEMO
-
SQL> select count(1) from demo;
-
COUNT(1)
-
----------
-
101000
对于这种情况,在12.1版本中,RMAN提供了一种便捷的方式让我们不需要在主库上进行数据文件的备份传输而可以在备库使用 restore database (or datafile ) from service去从主库进行恢复。
当然,Oracle的RMAN是足够聪明的:如果数据文件是正常的状态,RMAN可以根据它们的数据文件头进行跳跃恢复。如果,由于nologging操作导致某些块被标记为损坏的,那么这部分数据文件就是需要恢复的,然后怎么办?在恢复命令中有FORCE选项。但我们可能并不需要它。因为有些时候数据文件是同步的,实时日志应用进程还是在运行的。这个时候,为了恢复,我们需要停止应用。
一旦我们停止了应用,那么我们就不需要执行RESOTORE DATABASE FORCE操作,因为现在数据文件的状态是过旧的,就算你不加FORCE选项RMAN也是不会跳过这些数据文件的。
步骤一
备库关掉实时日志应用,并开启至mount状态。
-
SQL> alter database recover managed standby database cancel;
-
SQL> shutdown immediate
-
Database closed.
-
Database dismounted.
-
ORACLE instance shut down.
-
SQL> startup mount
-
ORACLE instance started
步骤二
备库登陆RMAN,使用restore database (or datafile ) from service进行恢复
-
RMAN> restore database from service 'primary_db'; #这里的primary_db,为备库至主库的tns连接串的别名
-
Starting restore at 2018-05-03 17:00:35
-
using target database control file instead of recovery catalog
-
allocated channel: ORA_DISK_1
-
channel ORA_DISK_1: SID=29 device type=DISK
-
channel ORA_DISK_1: starting datafile backup set restore
-
channel ORA_DISK_1: using network backup set from service primary_db
-
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
-
channel ORA_DISK_1: restoring datafile 00001 to /data/data1/ORCL2/datafile/o1_mf_system_02t1t9ck_.dbf
-
channel ORA_DISK_1: restore complete, elapsed time: 00:00:25
-
channel ORA_DISK_1: starting datafile backup set restore
-
channel ORA_DISK_1: using network backup set from service primary_db
-
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
-
channel ORA_DISK_1: restoring datafile 00003 to /data/data1/ORCL2/datafile/o1_mf_sysaux_03t1t9d3_.dbf
-
channel ORA_DISK_1: restore complete, elapsed time: 00:00:15
-
channel ORA_DISK_1: starting datafile backup set restore
-
channel ORA_DISK_1: using network backup set from service primary_db
-
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
-
channel ORA_DISK_1: restoring datafile 00004 to /data/data1/ORCL2/datafile/o1_mf_undotbs1_04t1t9di_.dbf
-
channel ORA_DISK_1: restore complete, elapsed time: 00:00:02
-
channel ORA_DISK_1: starting datafile backup set restore
-
channel ORA_DISK_1: using network backup set from service primary_db
-
channel ORA_DISK_1: specifying datafile(s) to restore from backup set
-
channel ORA_DISK_1: restoring datafile 00006 to /data/data1/ORCL2/datafile/o1_mf_users_05t1t9dm_.dbf
-
channel ORA_DISK_1: restore complete, elapsed time: 00:00:15
-
Finished restore at 2018-05-03 17:01:34
当然要记得去起库并开启实时日志应用进程!
而在12.2中,Oracle提供了一种更方便的方式去进行恢复主库会将未记录的块的列表发送至备库,并记录在备库控制文件中,我们可以从备库的v$nonlogged_block这个视图查看到相关信息。不需要发送主库的整个数据文件,而是在RMAN执行一个简单的命令来恢复它们:
RECOVER DATABASE NONLOGGED BLOCK
步骤一
停止备库实时日志应用
-
SQL> alter database recover managed standby database cancel;
步骤二
备库登陆RMAN执行
RECOVER DATABASE NONLOGGED BLOCK
注意:执行此步骤前请确认主备库的log_archive_config参数已经设置
-
RMAN> recover database nonlogged block;
-
Starting recover at 2018-05-03 14:54:22
-
using target database control file instead of recovery catalog
-
allocated channel: ORA_DISK_1
-
channel ORA_DISK_1: SID=56 device type=DISK
-
starting recovery of nonlogged blocks
-
List of Datafiles
-
=================
-
File Status Nonlogged Blocks Blocks Examined Blocks Skipped
-
---- ------ ---------------- --------------- --------------
-
1 OK 0 0 107519
-
3 OK 0 0 262399
-
4 OK 0 0 149759
-
5 OK 0 0 31999
-
6 OK 0 0 42239
-
7 OK 0 16707 21532
-
8 OK 0 0 12799
-
9 OK 0 0 76799
-
18 OK 0 0 33279
-
19 OK 0 0 57599
-
20 OK 0 0 24959
-
21 OK 0 0 33279
-
22 OK 0 0 51199
-
23 OK 0 0 12799
-
29 OK 0 0 1310719
-
30 OK 0 0 12799
-
31 OK 0 0 33279
-
32 OK 0 0 52479
-
33 OK 0 0 923519
-
34 OK 0 16822 8777
-
35 OK 0 0 12799
-
37 OK 0 0 24959
-
Details of nonlogged blocks can be queried from v$nonlogged_block view
-
recovery of nonlogged blocks complete, elapsed time: 00:00:08
-
Finished recover at 2018-05-03 14:54:32
最后别忘了开启实时日志应用进程。
综上来看,12.2中这个特性在数据仓库等一些场景是可以尝试的。以往我们开启force logging造成大量的redo日志并且影响一部分dml语句的执行效率。在12.2我们可以尝试使用nonlogging操作去节省大量数据插入的时间,然后在系统空闲时间进行备库恢复操作。但是注意这种操作也存在弊端,这样你的备库的可用性就大大降低了。凡事总有取舍!
| 作者简介
陈康,沃趣科技数据库技术专家
主要参与公司产品实施、测试、维护以及优化。