DBMS_LOGSTDBY.COMPARE 返回 NULL 或 0 行仅表示“未查到差异记录”,不等于数据一致;原因包括校验范围小、表未启用LOGGING或无主键、被SKIP规则跳过、备库未处于APPLYING_LOG状态、或存在LOB等不支持类型。
LOGSTDBY.COMPARE 返回 NULL 或 0 行代表什么
它不代表“一致”,只代表「没查到差异记录」——可能是校验范围太小、对象没被纳入、或根本没触发比对逻辑。oracle 的 dbms_logstdby.compare 默认只检查当前 scn 下已应用的表,且要求表必须启用日志记录(logging)、有主键或唯一约束,否则直接跳过不报错。
常见错误现象:DBMS_LOGSTDBY.COMPARE 执行完返回空结果集,但实际数据已错位;或者只返回几行,却漏掉大量未校验的表。
- 必须提前执行
EXEC DBMS_LOGSTDBY.SKIP('SCHEMA','TABLE_NAME')取消跳过规则,否则被跳过的表不会参与比对 - 校验前需确认备库处于
APPLYING_LOG状态,且已应用到主库当前 SCN:用SELECT APPLIED_SCN FROM V$LOGSTDBY_PROGRESS对比主库SELECT CURRENT_SCN FROM V$DATABASE -
COMPARE不校验 LOB、XMLType、嵌套表等复杂类型字段,遇到这些列会静默忽略整行
如何让 DBMS_LOGSTDBY.COMPARE 覆盖全部业务表
它默认只比对在 DBA_LOGSTDBY_LOG 和 DBA_LOGSTDBY_SKIP 中显式注册的表,不是“所有用户表”。想全量覆盖,得手动构造校验任务列表,并逐个调用 COMPARE。
使用场景:上线前批量验证、灾备切换前兜底检查。
- 先查出待校验表:用
SELECT OWNER, TABLE_NAME FROM DBA_TABLES WHERE OWNER NOT IN ('SYS','SYSTEM') AND TEMPORARY='N' AND DROPPED='NO'过滤掉系统表和临时对象 - 过滤掉无主键表:
SELECT t.OWNER, t.TABLE_NAME FROM DBA_TABLES t WHERE NOT EXISTS (SELECT 1 FROM DBA_CONSTRAINTS c WHERE c.OWNER = t.OWNER AND c.TABLE_NAME = t.TABLE_NAME AND c.CONSTRAINT_TYPE = 'P') - 对每张表调用:
DBMS_LOGSTDBY.COMPARE('SCHEMA_NAME','TABLE_NAME', commit_scn => NULL);注意commit_scn设为NULL才能用当前应用 SCN,设成具体值可能因 SCN 未到达导致无结果
ORA-16224 / ORA-16191 错误出现时还能不能跑 COMPARE
不能。这两个错误分别代表逻辑备库应用进程已停止(ORA-16224)和主备连接中断(ORA-16191),此时 DBMS_LOGSTDBY.COMPARE 会直接报 ORA-31693 或超时失败,不是数据不一致,而是根本没法读取备库当前状态。
性能影响:强行重试会持续占用 LOGSTDBY_APPLIER 进程资源,拖慢恢复进度。
- 先用
SELECT STATUS, ERROR FROM V$LOGSTDBY确认应用状态,STATUS 必须是APPLYING_LOG - 检查
V$LOGSTDBY_EVENTS最近 5 条错误事件,重点看网络、归档缺失、DDL 冲突类报错 - 修复后必须执行
ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE重启应用,再等至少 30 秒让进程稳定,才能调用COMPARE
对比结果里出现 DIFFERENT_ROW_COUNT > 0 之后怎么办
这个数值只表示「检测到哈希不匹配的行数」,不等于真实差异行数——因为哈希碰撞、LOB 截断、字符集转换都可能导致假阳性。它只是第一道筛选信号,不是最终结论。
容易踩的坑:直接根据这个数字判定同步失败,甚至触发回切,结果发现是误报。
- 先查具体差异:
SELECT * FROM DBA_LOGSTDBY_COMPARE WHERE SCHEMA_NAME = 'XXX' AND TABLE_NAME = 'YYY',重点关注HASH_VALUE和COMMIT_SCN - 手工比对几条:用
SELECT DBMS_CRYPTO.HASH(CAST(t AS RAW),2) FROM (SELECT * FROM SCHEMA.TABLE WHERE ROWID = 'xxx') t在主备两端分别算哈希,确认是否真不同 - 如果确认是真差异,优先查
V$LOGSTDBY_STATS中apply_lag和latest_scn是否滞后,再查DBA_LOGSTDBY_SKIP是否漏配了某类 DML 操作
最常被忽略的一点:COMPARE 的哈希算法依赖 NLS_COMP 和 NLS_SORT 参数,主备库若设置不一致(比如一个用 BINARY,一个用 GENERIC_M),哪怕数据完全一样,哈希值也会不同。










