1. 功能概述
Active Data Guard DML 重定向 是 Oracle 19c 引入的一项重要新特性,允许在 物理备库(Physical Standby) 上直接执行 DML 操作(INSERT、UPDATE、DELETE)。当用户在备库上发起 DML 时,操作会被 透明地重定向 到主库执行,产生的 Redo 日志再传回备库应用,最终将结果返回给客户端。
此特性使得备库不再仅限于只读查询,而是可以承载 “偶尔写入” 的混合工作负载,真正实现 Read-Mostly 架构。
适用场景
- 备库上运行的只读应用程序偶尔需要执行少量 DML(如更新状态、插入日志)
- 希望减轻主库上大量只读会话的并发压力
- 应用代码无法修改连接字符串,但需要备库具备有限写入能力
- 报表系统需要在查询中间结果时写入临时标记
2. 工作原理
┌─────────────────────────────────────────────────────────────┐ │ 应用层(客户端) │ │ 连接备库,发出 DML 语句(INSERT/UPDATE/DELETE) │ └──────────────────────┬──────────────────────────────────────┘ │ ▼ ┌─────────────────────────────────────────────────────────────┐ │ Active Data Guard 备库 │ │ │ │ ① 接收 DML 请求 │ │ ② 自动检测是否为 DML 操作 │ │ ③ 将 DML 重定向到主库(透明,应用无感知) │ │ ④ 等待主库执行完毕并传回 Redo │ │ ⑤ Redo 应用后,返回结果给客户端 │ └──────────────────────┬──────────────────────────────────────┘ │ 重定向 (ADG_REDIRECT_DML) ▼ ┌─────────────────────────────────────────────────────────────┐ │ 主库(Primary) │ │ │ │ ① 接收来自备库的重定向 DML │ │ ② 在本地执行 DML 操作 │ │ ③ 生成 Redo 日志 │ │ ④ 按 Data Guard 同步策略传送到备库 │ └─────────────────────────────────────────────────────────────┘
详细流程
| 步骤 | 说明 |
|---|---|
| 1 | 客户端连接到备库,发起 DML 语句(INSERT / UPDATE / DELETE) |
| 2 | 备库检测到 DML 操作,通过 ADG_REDIRECT_DML 机制将其 透明重定向 到主库 |
| 3 | 主库执行该 DML,生成 Redo 日志,提交事务 |
| 4 | 主库将 Redo 传输到备库,MRP(Managed Recovery Process)应用 Redo |
| 5 | 备库应用变更后,返回成功结果给客户端,DML 会话期间保持读一致性 |
关键特性
- 透明性:应用无需修改代码或连接字符串
- 读一致性:DML 会话中的未提交更改,在该会话内可查询到(其他会话需等待提交后)
- 等待语义:备库会话会 同步等待 直到数据变更被传回并应用到备库后才返回
- ACID 保障:事务的原子性、一致性、隔离性、持久性完全保持
3. 核心优势
| 优势 | 说明 |
|---|---|
| 🔄 Read-Mostly 负载分担 | 备库可同时处理只读查询和偶发写入,分担主库压力 |
| ⚡ 减少主库压力 | 大量的 SELECT 查询转移到备库,主库专注处理写入 |
| 🔌 无需修改应用 | 备库 DML 对应用完全透明,连接字符串无需变更 |
| ✅ 完整 ACID 保障 | 事务特性完全保留,数据一致性有保障 |
| 🛡️ 高可用增强 | 备库在容灾之外获得更多实用价值 |
4. 前提条件
在启用 DML 重定向之前,必须满足以下条件:
4.1 环境要求
| 条件 | 要求 |
|---|---|
| Oracle 版本 | 19c 或更高版本(19.0.0.0.0 及以上) |
| Data Guard 配置 | 已配置 Data Guard Broker(建议) |
| 备库状态 | 物理备库,处于 READ ONLY WITH APPLY 模式 |
| 网络连接 | 主库和备库之间网络通畅,连接字符串可用 |
4.2 限制说明
⚠️ 重要限制
- SYS 用户不支持:SYS 用户连接备库时无法使用 DML 重定向
- Oracle XA 事务不支持:分布式 XA 事务中的 DML 无法重定向
- 重定向量建议 < 10%:所有备库 DML 最终在主库执行,过多会冲击主库性能
- 连接方式限制:必须使用 用户名/密码 方式登录(
sqlplus user/pass@standby),不能使用/ as sysdba- DDL 不支持:重定向仅限 DML(INSERT/UPDATE/DELETE/MERGE),DDL(CREATE/ALTER/DROP)需要直接在主库执行
4.3 验证备库状态
-- 在备库执行SELECT OPEN_MODE, DATABASE_ROLE, SWITCHOVER_STATUS, PROTECTION_MODE, FLASHBACK_ON FROM V$DATABASE;
预期输出:
OPEN_MODE=READ ONLY WITH APPLYDATABASE_ROLE=PHYSICAL STANDBY
5. 启用配置
参数
ADG_REDIRECT_DML默认值为FALSE。需要在 主库和备库两端 都设置为TRUE。
5.1 主库配置
SQL> show parameter adg_redirect_dml
NAME TYPE VALUE
———————————— ———– ——————————
adg_redirect_dml boolean FALSE
SQL> alter system set adg_redirect_dml=true scope=both;
System altered.
SQL> show parameter adg_redirect_dml
NAME TYPE VALUE
———————————— ———– ——————————
adg_redirect_dml boolean TRUE
5.2 备库配置
SQL> show parameter adg_redirect_dml
NAME TYPE VALUE
———————————— ———– ——————————
adg_redirect_dml boolean FALSE
SQL> alter system set adg_redirect_dml=true scope=both;
System altered.
SQL> show parameter adg_redirect_dml
NAME TYPE VALUE
———————————— ———– ——————————
adg_redirect_dml boolean TRUE
5.3 会话级别控制(可选)
若仅需单个会话启用,而非全局启用:
-- 在当前会话启用 DML 重定向(会覆盖系统级设置)
ALTER SESSION ENABLE ADG_REDIRECT_DML;
-- 在当前会话禁用 DML 重定向
ALTER SESSION DISABLE ADG_REDIRECT_DML;
优先级:会话级设置 > 系统级设置
6. 功能测试
6.1 在主库创建测试表
-- 连接主库(用户名/密码方式)
sqlplus sys/oracle@primary as sysdba
-- 创建测试表
CREATE TABLE oracle_dml_test (
name VARCHAR2(50),
testdate TIMESTAMP
);
-- 插入测试数据
INSERT INTO oracle_dml_test VALUES ('主库写入测试', SYSDATE);
INSERT INTO oracle_dml_test VALUES ('初始数据', SYSDATE);
COMMIT;
-- 验证
SELECT * FROM oracle_dml_test;
6.2 在备库验证数据已同步
-- 连接备库(必须使用用户名/密码方式,不可用 / as sysdba)
sqlplus sys/oracle@standby as sysdba
-- 查看主库创建的表和数据是否已同步(可能在备库需要完全路径或等待 apply 延迟)
SELECT * FROM oracle_dml_test;
-- 确认备库状态
SELECT DATABASE_ROLE, OPEN_MODE FROM V$DATABASE;
SELECT STATUS, INSTANCE_NAME, DATABASE_ROLE, PROTECTION_MODE
FROM V$DATABASE, V$INSTANCE;
预期输出:
DATABASE_ROLE OPEN_MODE
-------------------- --------------------
PHYSICAL STANDBY READ ONLY WITH APPLY
6.3 在备库执行 DML 重定向测试
-- 连接备库(用户名/密码,非 SYS 用户优先)
sqlplus test_user/test_pass@standby
-- 在备库执行 DELETE 操作(将会被透明重定向到主库)
DELETE FROM oracle_dml_test WHERE name = '初始数据';
-- 显示受影响行数
-- 输出: 1 row deleted.
-- 提交事务
COMMIT;
-- 再次查询,确认读一致性
SELECT * FROM oracle_dml_test;
6.4 在主库验证变更已生效
-- 连接主库
sqlplus sys/oracle@primary as sysdba
-- 验证数据已从备库删除
SELECT * FROM oracle_dml_test;
-- 预期:'初始数据' 行已不存在,DML 重定向成功
7. 高级测试场景
7.1 PL/SQL 块中的 DML 重定向
备库上的 PL/SQL 块中包含的 DML 同样会被重定向:
-- 在备库执行
BEGIN
INSERT INTO oracle_dml_test VALUES ('PL/SQL 插入测试', SYSDATE);
UPDATE oracle_dml_test SET name = 'PL/SQL 已更新' WHERE name = 'PL/SQL 插入测试';
COMMIT;
END;
/
7.2 事务一致性验证
-- 备库:插入后未提交,本会话可看到
INSERT INTO oracle_dml_test VALUES ('未提交数据', SYSDATE);
SELECT * FROM oracle_dml_test; -- 可以看到新行
-- 另开一个备库会话(同一事务未提交前),看不到新行
7.3 多表联合 DML
-- 备库执行多表操作
INSERT INTO oracle_dml_test VALUES ('多表测试A', SYSDATE);
UPDATE oracle_dml_test SET testdate = SYSDATE WHERE name LIKE '多表%';
DELETE FROM oracle_dml_test WHERE name = '多表测试A';
COMMIT;
8. 监控与诊断
8.1 查看 DML 重定向状态
-- 当前会话是否启用 DML 重定向
SELECT SYS_CONTEXT('USERENV', 'ADG_REDIRECT_DML') AS adg_redirect_enabled FROM DUAL;
8.2 查询重定向相关的等待事件
-- 查看 DML 重定向相关等待事件
SELECT event, total_waits, time_waited, average_waitFROM V$SYSTEM_EVENTWHERE event LIKE '%ADG%' OR event LIKE '%redirect%';
8.3 重定向错误诊断
常见错误代码:
| 错误码 | 说明 | 解决方案 |
|---|---|---|
| ORA-16397 | 从备库到主库的语句重定向失败 | 检查主库连通性和 ADG_REDIRECT_DML 参数 |
| ORA-00604 | 递归 SQL 级别 1 发生错误 | 通常因使用 / as sysdba 连接导致,改用用户名/密码 |
| ORA-16000 | 备库上不支持的操作 | 确认操作类型为 DML(非 DDL) |
9. 最佳实践与注意事项
✅ 最佳实践
| 实践 | 说明 |
|---|---|
| 控制重定向占比 < 10% | 备库 DML 最终在主库执行,过多 DML 会冲击主库性能 |
| 使用非 SYS 用户 | 创建专用应用用户执行备库 DML,避免 SYS 限制 |
| 监控主库负载 | 关注主库的 DB TIME 和 Redo 生成速率 |
| 设置合理的网络延迟阈值 | 重定向对网络延迟敏感,建议主备之间延迟 < 5ms |
| 优先使用会话级别启用 | 默认关闭,仅对需要的会话启用,减少意外 DML 风险 |
| 测试环境中充分验证 | 上线前模拟备库 DML 压力,确认主库可承受 |
❌ 注意事项
- DDL 不会重定向 — 表结构变更仍需在主库执行
- 序列(Sequence)不重定向 — 在备库访问序列需在主库预先处理
- 临时表 — 全局临时表在备库行为可能不同,需仔细测试
- 主备延迟影响 — 如果主备之间有较大 Redo 应用延迟,DML 操作等待时间会增加
- Data Guard Broker — 建议使用 Broker 管理,Broker 故障切换后参数会自动同步
- 版本兼容性 — 主备库必须同为 19c,且版本补丁级别一致
10. 故障排除
问题 1:ORA-16397 错误
ORA-16397: statement redirection from Oracle Active Data Guard standby database to primary database failed
排查步骤:
- 检查主库和备库的
ADG_REDIRECT_DML参数是否都为TRUE - 确认备库处于
READ ONLY WITH APPLY模式 - 测试主备之间数据库连接是否正常
- 确认未使用
/ as sysdba连接备库
问题 2:备库 DML 无反应
-- 检查备库是否启用了 DML 重定向
ALTER SESSION ENABLE ADG_REDIRECT_DML;
-- 检查连接方式
SELECT SYS_CONTEXT('USERENV', 'AUTHENTICATION_METHOD') FROM DUAL;
-- 应返回非 SYSDBA 认证方式
问题 3:DML 性能缓慢
- 检查主备之间的 网络延迟 和 带宽
- 检查备库的 Redo Apply 速率
- 使用
V$ADG_STATS视图诊断同步延迟
-- 查看 ADG 同步状态
SELECT NAME, VALUE, TIME_COMPUTED, DATUM_TIME
FROM V$ADG_STATS
WHERE NAME LIKE '%lag%';
最后修改时间:2026-07-18 18:05:16
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。





