DATAGUARD之四:DATAGUARD的一些常见问题

一,常见问题

1,重命名文件

一般我们在配置DG的时候,会配置STANDBY_FILE_MANAGEMENT为AUTO。

这种情况下,人为的操作时不允许的,所以rename,add,drop,create需要先把该参数设置为manual

--以下操作都时不允许的
ALTER DATABASE RENAME
ALTER DATABASE ADD/DROP LOGFILE
ALTER DATABASE ADD/DROP STANDBY LOGFILE MEMBER
ALTER DATABASE CREATE DATAFILE AS

--报错信息
ORA-01511: error in renaming log/datafiles 
ORA-01270: RENAME operation is not allowed if STANDBY_FILE_MANAGEMENT is auto

2,备库不会从主库接收日志

--在备库查询,一般情况下能看到足够的信息
SELECT DEST_ID "ID", STATUS "DB_status", DESTINATION "Archive_dest", ERROR "Error" FROM V$ARCHIVE_DEST WHERE DEST_ID <=5;

如果归档路径没有显示足够的信息,那么检查以下的项目是否有任何问题,原理都是检查两边的连接性:

a)主库tnsnames.ora中的service配置是否正确,tnsping一下

b)LOG_ARCHIVE_DEST_n里面,指向备库的那一个路径中的service name跟tnsnames.ora中配置的是否一致

c)LOG_ARCHIVE_DEST_STATE_n指向备库的那一个必须设置为ENABLE

d)备库的listener.ora没有正确配置,比如说静态服务

e)备库监听没有启动

f)备库实例没有启动

g)添加参数的时候,你指定的是scope=spfile,而不是both,所以当前没有生效

h)日志传输认证没有配置正确,通常我们配的是密码文件,两边同步一下,远程sqlplus @测试

i)创建备库时所使用的备份不是当前主库的,或者创建控制文件时,没有指定为standby使用

3,无法mount物理备库

如果你创建控制文件的时候,没有以ALTER DATABASE CREATE [LOGICAL] STANDBY CONTROLFILE方式创建的话,你是无法mount起来的

另外一种情况就是,不能直接系统层面备份,比如说cp,mv

二,日志文件路径错误

如果你在一个MANDATORY路径指定了REOPEN,那么当主库无法成功传输日志的时候,日志传输服务就会停止。

这是因为REOPEN必须和MAX_FAILURE参数配合使用,一个指定间隔多久进行重试,一个则指定最多失败几次。

举个例子:

--每个5秒进行尝试,最多失败三次就不再尝试
LOG_ARCHIVE_DEST_1='LOCATION=/arc_dest REOPEN=5 MAX_FAILURE=3'

可以使用ALTERNATE参数来配置备选的LOG_ARCHIVE_DEST_n路径,备选也就是说当归档路径失败的时候,才会使用这个。

使用NOALTERNATE参数,则能防止原始归档路径当失败的时候自动切换到下一个归档路径,见仁见智。

使用方式:

--在路径1的配置里面指定了ALTERNATE是哪一个路径
LOG_ARCHIVE_DEST_1='LOCATION=/disk1 MANDATORY ALTERNATE=LOG_ARCHIVE_DEST_2'
LOG_ARCHIVE_DEST_STATE_1=ENABLE
LOG_ARCHIVE_DEST_2='LOCATION=/disk2 MANDATORY'
LOG_ARCHIVE_DEST_STATE_2=ALTERNATE

三,逻辑备库的错误

对于逻辑备库的错误来说,数据库有一个很关键的工具:DBMS_LOGSTDBY.SKIP_ERROR,具体使用例子可以看一下官档

https://docs.oracle.com/en/database/oracle/oracle-database/18/arpls/DBMS_LOGSTDBY.html#GUID-267A7172-05AD-443A-9AC6-B4D0CF8208A5

处理错误的方式依托于出现错误的表的重要性:

a)你可以选择忽略表的错误或者特定的DDL语句

b)把存储过程和一个过滤器关联起来,以便在运行时能够判断是跳过该语句,执行该语句或者执行一条替代的语句

以上的两种方式可以让你先跳过错误,继续进行SQL APPLY,然后再这之后,你再去查询DBA_LOGSTDBY_EVENTS来处理之前出现的问题。

四,切换成物理备库时发生错误

1,重做日志没有传输成功

正常情况下,切换之前,最后一个日志必须成功传输并且应用。

因此如果切换没有成功,请查询下V$ARCHIVED_LOG表的SEQUENCE#列,看一下原主库的最后一个日志是否已经传输到备库应用了。

如果没有的话,这种情况下,你可以手动从主库拷贝最后一个日志到备库,然后手动注册,接着再打开日志应用,最后一个归档会自动被应用。

ALTER DATABASE REGISTER LOGFILE '/oradata/fra/archivelog/test1.arc';
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;

这个时候再查询switchover_status,看到的结果可能,只是可能会变成了TO PRIMARY或者SESSIONS ACTIVE

SELECT SWITCHOVER_STATUS FROM V$DATABASE;

这个时候就可以重新进行switchover了。

2,ORA-01102

设置DB_UNIQUE_NAME=unique_database_name。

这个错误之所以会发生,是因为主库和备库在同一端,然后刚好没有设置DB_UNIQUE_NAME,那么在启动到mount状态的时候,主库备库因为使用同一个mount lock照成冲突,后者将无法挂载到mount状态

3,SWITCHOVER之后日志没有开始应用

如果切换后备库没有开始应用日志,可能是一些环境或者初始化参数没有设置正确

所以检查吧:

  • 主库是否能tnsping通备库的服务
  • 检查归档路径有没有问题,要注意检查LOG_ARCHIVE_DEST_STATE_n
  • LOG_ARCHIVE_FORMAT必须包含%s (sequence), %t (thread), and %r (resetlogs ID)来确定归档的唯一性
  • 在备库检查下DB_FILE_NAME_CONVERT和LOG_FILE_NAME_CONVERT,以及STANDBY_FILE_MANAGEMENT

4,SWITCHOVER失败后的回切

有时候可能因为某些原因SWITCHOVER没法继续下去,在11.2.0.2之后,Oracle提供了把新备库切换回主库的可能性。

a)把新备库启动到mount状态

b)启动日志应用

c)启动日志应用后,再重新验证下数据库的SWITCHOVER_STATUS,如果是TO PRIMARY或者SESSIONS ACTIVE,那么则表示它可以被切换回主库了。有时候可能需要点时间,所以多查询几次,直到返回这两个值,当然前提是你的配置没有问题

d)运行以下语句来转换DB,如果成功则万事大吉,不成功就看下一步

ALTER DATABASE SWITCHOVER TO target_db_name [FORCE];

e)当触发了SWITCHOVER的时候,在log路径下会生成一个trace文件,你可以看以下主库的alert,里面的记录内容类似于

Backup controlfile written to trace file /u01/app/oracle/diag/rdbms/ryanstd/ryan/trace/ryan_ora_29487.trc

把SQL语句拷贝到一个临时文件执行,这些语句会把新的备库重新转换成主库角色

f)关闭原本的备库

g)在主库创建新的备库控制文件,然后拷贝到旧备库端

h)启动备库,如果启用了归档缺口管理,那么FAL进程会自动开始重新归档任何缺失的重做日志到备库。

  监控两边的alert日志,然后在主库手动切换一次日志以确保归档正常

i)等应用完成,状态恢复正常,再重新尝试switchover

五,切换逻辑备库时的问题

 逻辑备库的切换操作通常由两部分组成:准备和提交。

滚动升级或者说使用DG BROKER在此之外,如果你刚好遇见的是跟着两种相关的错误,看下面第3小节。

注意:下面的内容都是假设启用了flashback database的,一般情况下,你在网上找的教程99%都有这么一步。

1,在准备阶段遇上了错误

  1.1在PRIMARY DATABASE的准备阶段失败了

当你执行ALTER DATABASE PREPARE TO SWITCHOVER TO LOGICAL STANDBY的时候就撞上了问题,可以执行以下语句取消:

alter database prepare to switchover to logical standby cancel;

  1.2,在LOGICAL STANDBY的准备阶段失败了

也就是在执行ALTER DATABASE PREPARE TO SWITCHOVER TO PRIMARY语句的时候遇到了错误,那么你需要取消主备两端的准备操作:

--在主库
alter database prepare to switchover to logical standby cancel;

--在备库
alter database prepare to switchover to primary cancel;

2,在COMMIT阶段遇上了错误

虽然对于我们来说commit操作只是一条语句,但实际上后台有多个步骤要进行,所以采取什么操作需要根据commit的状态来决定

  2.1,无法转换旧主库

a)检查旧主库的角色

select database_role from v$database;

--如果输出结果是LOGICAL STANDBY,那么switchover的操作已经完成,只是post switchover的一些操作失败了,Oracle建议这个时候重启数据库

--如果输出结果是primary,那么我们就需要进行第2步

b)

--在旧主库执行以下语句
select count(*) from SYSTEM.LOGSTDBY$PARAMETERS where name='END_PRIMARY';

--如果返回的值等于0,那么表示主库处在COMMIT之前的状态,这个时候你不需要采取其他额外操作,可以像之前一样,COMMIT或者CANCEL操作

--如果返回的值大于1,那么主库处于不一致的状态,需要执行下一步

c)在旧主库上采取纠正措施,保证它还处于被逻辑备库保护的状态下

你可以选择处理切换过程中出现的错误,然后再重新触发一次ALTER DATABASE COMMIT TO SWITCHOVER TO LOGICAL STANDBY;

又或者:

--在你触发了alter database commit to switchover to logical standby的时候,日志里面会有一个SCN,我们需要用它来把原本的主库flashback回去
LOGSTDBY: Preparing the COMMIT TO SWITCHOVER TO LOGICAL STANDBY DDL at scn [flashback_scn].

--将主库的实例启动到mount状态

--闪回
FLASHBACK DATABASE TO BEFORE SCN <flashback_scn>;

STARTUP;
--变更用户权限,允许用户修改自己有权限操作的表 ALTER DATABASE GUARD NONE;

做完这些之后,那么主库将会处在COMMIT之前的状态,这个时候你不需要采取其他额外操作,可以像之前一样,COMMIT或者CANCEL操作

   2.2,无法转换目标逻辑备库

 当你在逻辑备库执行ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY的时候遇见了错误,可以采取以下操作:

--检查备库角色
SELECT DATABASE_ROLE FROM V$DATABASE;

--如果结果显示为PRIMARY,那么切换操作已经完成
--重启数据库
--执行以下命令接触写入限制
ALTER DATABASE GUARD NONE;

--如果结果仍然显示LOGICAL STANDBY,那么执行下一步
SELECT COUNT(*) FROM SYSTEM.LOGSTDBY$PARAMETERS WHERE NAME = 'BEGIN_PRIMARY';

--如果以上结果返回0,证明逻辑备库已经处于COMMIT之前的状态,这个时候只需要正常执行COMMIT操作即可
--如果以上结果返回1,那么逻辑备库处于不一致的状态,执行下一步

--从alert日志中,在你触发了ALTER DATABASE COMMIT TO SWITCHOVER TO PRIMARY语句之后,你能够看到一个SCN,这个SCN是我们之后flashback database的时候要指定的,在alert里面,显示如下:
LOGSTDBY: Preparing the COMMIT TO SWITCHOVER TO PRIMARY DDL at scn [flashback_scn].

--STARTUP到MOUNT状态
shutdown immediate;
startup mount;

--FLASHBACK
flashback database to before SCN n;

--打开数据库
startup open;

--做完以上操作后,逻辑备库会恢复到commit之前的一致状态,你只需要重新触发COMMIT操作即可

六,日志应用中断

如果遇见了无法支持的SQL语句或者package的话,SQL应用就会停止,这种情况下可以采取下列的操作:

场景 解决方案
你怀疑是遇上了不支持的SQL语句或者package

查询DBA_LOGSTDBY_EVENTS,它会显示SQL语句和导致SQL应用失败的原因。

包含了事务信息,会话信息,以及错误信息。事务信息可以使用logminer来挖掘问题产生的原因

数据库管理导致的问题,比如说空间不够之类的 根据错误信息解决相关问题
错误的SQL,SQL本身错误,比如说数据文件名的路径不正确

纠正语句,然后使用DBMS_LOGSTDBY.SKIP_TRANSACTION来确保下一次日志应用忽略该条SQL。

然后重新启用日志应用:ALTER DATABASE START LOGICAL STANDBY APPLY;

没有正确设置SKIP参数,比如说只指定了跳过对于某个表的所有DML操作,

但是没有指明要跳过CREATE,ALTER,以及DROP TABLE的操作

运行DBMS_LOGSTDBY.SKIP('TABLE','schema_name','table_name',null),然后重启日志应用

七,重做日志传输的网络优化

可以在每一个日志传输服务相关的参数里,把SDU参数设置为最大值65535。

例子:

--日志传输路径LOG_ARCHIVE_DEST_3,指定的服务是netserv
LOG_ARCHIVE_DEST_3='SERVICE=netserv'

--tnsnames.ora中的相关设置
netserv=(DESCRIPTION=
    (SDU=32768)
    (ADDRESS=(PROTOCOL=tcp)(HOST=host) (PORT=1521))         
    (CONNECT_DATA=(SERVICE_NAME=srvc))
)

--listener.ora,远端静态服务
LISTENER=(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=tcp)
(HOST=host)(PORT=1521))))

SID_LIST_LISTENER=(SID_LIST=(SID_DESC=(SDU=32768)(SID_NAME=sid)
(GLOBALDBNAME=srvc)(ORACLE_HOME=/oracle)))

--如果你使用一个高延迟或者高带宽的网络链接连接到远端,那么你可以通过设置SQLNET.SEND_BUF_SIZE和SQLNET.RECV_BUF_SIZE来提高网络发送和接收的IO缓存

八,备库的磁盘性能慢

如果备库当前是异步I/O,可以尝试把文件系统挂载成Direct I/O模式。

或者设置FILESYSTEMIO_OPTIONS=SETALL,最大的I/O大小设置是1MB。

九,日志文件必须互相匹配,防止主库关机

如果你在一个或者多个备库配置了STANDBY REDO LOG,你要确保每一个备库的每一组STANDBY REDO LOG和主库的redo log大小完全匹配。

在主库做日志切换的时候,如果备库找不到有效的STANDBY REDO LOG,那么可能会发生以下的情况:

  • 如果主库处于MAXIMUM PROTECTION模式,那么主库会关闭
  • 备库的RFS进程会创建一个归档日志文件,并且在alert里面记录:
No standby log files of size <#> blocks available.

因此,无论任何时候,如果你在主库加了一个日志组,一定要记得在每一个备库添加一个相应的STANDBY REDO LOG组,standby redo log组的数目要比主库多一个。

十,逻辑备库的Troubleshooting

暂且记录下官档直通车:

https://docs.oracle.com/en/database/oracle/oracle-database/18/sbydb/troubleshooting-oracle-data-guard.html#GUID-B1551FC6-1B9F-49A5-A462-124697A449C3

十一,DG相关视图:

https://docs.oracle.com/en/database/oracle/oracle-database/18/sbydb/oracle-data-guard-in-oracle-database-views.html#GUID-FF72163C-78B0-475F-B4CE-135EF288A32A

posted @ 2019-11-23 10:59  Ryan_Wo  阅读(1355)  评论(0)    收藏  举报