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,具体使用例子可以看一下官档
处理错误的方式依托于出现错误的表的重要性:
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
暂且记录下官档直通车:
浙公网安备 33010602011771号