前几天,某应用说他们备库上报了ORA-1578和ORA-26040错误,报错的信息是使用nologging导致数据块损坏。查了官网资料,也让应用把主库信息反馈回来,发现主库没有开启force logging。在搭建DG时,是需要开启这一属性。
应用碰到的这个问题,是由于主库未开启force logging,而之前他们手工维护索引时,为了加快维护速度,采用了parallel + nologging,最终导致备库出现数据块损坏。
若主库启用了force logging,则不存在该问题。
以下是在搭建DG时,force logging官方说明。

问题的影响面:
1)在备库上进行数据备份,数据的可用性存在问题
2)备库提供查询操作,访问到损坏的数据块,会直接报错
3)无论是定期主备切换演练,或是主库宕机需要切换,在切换新主后,访问损坏的数据块,将会报错,影响业务的连续性
问题修复方法,一般有以下方法:
1)若损坏的是小表的索引,则可以直接在主库上drop掉,重建即可
2)若损坏的是大表的索引,可以找个业务低峰期,在主库上drop掉,重建。或是通过rman工具命令进行修复(针对12c以上版本数据库),修复步骤如下:
开启主库问题对象的logging属性
停掉备库同步
通过recover命令进行修复
检查v$nonlogged_block表,是否还有未修复数据块
若已全部修复,再次打开备库数据同步
3)若损坏的是表,建议重建表。
下面用两个测试用例来重现问题及修复碰到的问题。
>>>测试用例一:主库未开启force logging,维护索引时,在语句级别上使用nologging
1)检查主库force logging属性No

2)DG配置信息

3)在主库上,切换到ora_mon用户,创建一张测试表,在ID列上创建一个普通索引,并插入10万行记录

4)在主库上对idx_test_ind_nologgin索引进行rebuild,并行度为4,并且开启nologging属性。索引维护结束后,只将并行度改为1

5)查看备库信息及日志同步情况

6)在备库上,切换到ora_mon用户,统计test_ind_nologgin表的总记录数,由于是全表扫描,所以没有报错。若where条件加上ID列查询,语句走了idx_test_ind_nologgin索引,则直接报错,如下图所示:

7)从备库的alert log日志,也可以看到相关的报错信息

8)在备库上,查看v$nonlogged_block表,可以看到出问题的数据块信息

9)在备库上,停止数据同步。然后通过rman工具的recover命令进行修复

10)在主库上,开启idx_test_ind_nologgin索引的logging属性,并插入10万条记录

11)在备库上开启数据同步,并进行全表查询或是使用ID列进行查询,没有出现前面报错信息,说明了数据块已经修复了

>>>测试用例二:主库开启force logging,维护索引时,在语句级别上使用nologging
1)重启主库到mount状态,开启force logging,打开主库,并切换一下日志

2)在主库上,切换到ora_mon用户,创建一张测试表,在ID列上创建一个普通索引,并插入10万行记录。然后对idx_test_ind_nologging索引进行rebuild,并行度为4,并且开启nologging属性。索引维护结束后,只将并行度改为1

3)启动备库,并开启数据同步

4)在备库上,切换到ora_mon用户,统计test_ind_nologging表的总记录数,由于是全表扫描,所以没有报错。若where条件加上ID列查询,语句走了idx_test_ind_nologging索引,也没有任何报错





