必须先查v$database确认database_role,主库查v$archive_dest_status,备库查v$managed_standby和v$dataguard_stats;统一从v$dataguard_stats提取apply lag数值(秒),避免解析字符串误差。

查 v$archive_dest_status 前先确认当前是主库还是备库
直接连上就查 v$archive_dest_status 很容易翻车——这个视图在备库上默认不可见(尤其物理备库启用 STANDBY_FILE_MANAGEMENT=AUTO 时),且主备角色切换后查询逻辑必须动态适配。脚本第一件事不是查数据,而是跑 SELECT database_role FROM v$database 确认角色。
实操建议:
- 用
cx_Oracle连接后立刻执行该语句,把结果存为role变量 - 主库查
v$archive_dest_status关注STATUS、ERROR、APPLIED_SCN;备库则查v$managed_standby和v$dataguard_stats - 别硬写死连接串指向“主库”,生产环境可能随时 switchover,脚本得自己识别
用 v$dataguard_stats 算实时延迟比查 APPLY_LAG 字符串更可靠
v$dataguard_stats 里的 VALUE 列返回的是秒数(如 3620 表示 1 小时延迟),而 v$archive_dest_status.APPLY_LAG 返回的是格式化字符串(如 +00 01:00:20),解析易出错且 Oracle 版本间行为不一致(12c 后部分场景返回 NULL)。
实操建议:
- 统一从
v$dataguard_stats WHERE NAME = 'apply lag'提取数值,转成整型再判断 - 注意单位:该值是“备库已接收但未应用的 redo 时间差”,不是网络传输延迟
- 若查不到
apply lag,降级查transport lag+apply lag是否都为 0,再结合v$managed_standby.PROCESS = 'MRP0'是否在运行
捕获 ORA-16810 错误要区分是配置问题还是瞬时故障
调用 dbms_dataguard.is_standby 或查 v$archive_dest 时遇到 ORA-16810: multiple errors or warnings detected for the database 是典型信号,但不能一概判为宕机。它可能是归档目标路径满、密码文件不一致、监听没起来等可恢复问题。
实操建议:
- 捕获异常后,立刻查
v$dataguard_status WHERE severity IN ('Error', 'Warning') ORDER BY timestamp DESC拿最近 5 条明细 - 重点过滤
ERROR级别的ORA-错误码,比如ORA-16057(DG 配置缺失)、ORA-12514(TNS 服务名错) - 对
ORA-16810本身不做告警,只作为触发深度检查的开关——真正要告警的是底层具体错误
Python 脚本里别用 time.sleep() 做轮询,改用数据库端 DBMS_ALERT
常见写法是 while 循环里反复 connect → query → sleep(30),这既占连接数又难控制精度。Oracle 自带 DBMS_ALERT 可让备库在日志应用完成时主动通知,Python 只需监听信号。
实操建议:
- 在备库执行
BEGIN DBMS_ALERT.REGISTER('dg_apply_done'); END; - Python 用
cx_Oracle的connection.subscribe(..., callback=...)注册回调函数 - 主库每次 commit 后调用
DBMS_ALERT.SIGNAL('dg_apply_done', ...)(需提前授权) - 此方案省连接、低延迟,但要求 Oracle 11gR2+ 且用户有
EXECUTE ON DBMS_ALERT权限
真正的难点不在查哪些视图,而在于把“主备角色动态感知”“错误分级收敛”“延迟单位统一转换”这三件事稳稳焊进同一段逻辑里。漏掉任一环节,脚本上线后就会在半夜发一堆无效告警。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











