You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Oracle 19c双向数据同步实现及ORA-12518错误解决

问题分析

ORA-12518错误的核心原因是触发器双向递归调用导致连接资源耗尽:远程库创建触发器后,本地库的变更会触发远程库操作,而远程库的触发器又会立即触发本地库的反向操作,形成无限循环,导致数据库监听进程无法处理持续激增的连接请求,最终抛出该错误。

解决方案

要解决这个问题,核心是切断触发器的递归同步链路,同时优化同步逻辑的准确性和效率,具体实现如下:

1. 给同步操作添加专属标识

通过USERENV('CLIENT_INFO')和DBMS_APPLICATION_INFO包,为触发器发起的同步操作打上唯一标识,触发器检测到该标识时直接跳过执行,避免递归循环。

2. 优化WHERE匹配条件

原触发器使用所有列作为WHERE条件,存在效率低、匹配不准确的问题,改为仅用主键(如id)作为唯一匹配依据,确保同步操作的精准性。

修改后的触发器代码

本地库(local db)触发器

CREATE OR REPLACE TRIGGER trg_test_order_local
AFTER INSERT OR UPDATE OR DELETE ON test_order_local
FOR EACH ROW
DECLARE
  v_client_info VARCHAR2(64);
  PRAGMA AUTONOMOUS_TRANSACTION; 
BEGIN
  -- 检查是否为远程库同步过来的操作,是则跳过
  SELECT USERENV('CLIENT_INFO') INTO v_client_info FROM DUAL;
  IF v_client_info = 'SYNC_FROM_REMOTE' THEN
    COMMIT;
    RETURN;
  END IF;

  -- 设置同步标识,告知远程库触发器这是同步操作
  DBMS_APPLICATION_INFO.SET_CLIENT_INFO('SYNC_FROM_LOCAL');

  IF INSERTING THEN
    INSERT INTO test_order_remote@test_remote1 (id, desc1, desc2, desc23)
    VALUES (:NEW.id, :NEW.desc1, :NEW.desc2, :NEW.desc23);
  ELSIF UPDATING THEN
    -- 仅用主键id匹配,避免多列匹配的误差
    UPDATE test_order_remote@test_remote1
    SET desc1 = :NEW.desc1, desc2 = :NEW.desc2, desc23 = :NEW.desc23
    WHERE id = :OLD.id;
  ELSIF DELETING THEN
    DELETE FROM test_order_remote@test_remote1
    WHERE id = :OLD.id;
  END IF;

  -- 重置客户端标识
  DBMS_APPLICATION_INFO.SET_CLIENT_INFO('');
  COMMIT;
END;
/

远程库(remote)触发器

CREATE OR REPLACE TRIGGER trg_test_order_remote
AFTER INSERT OR UPDATE OR DELETE ON test_order_remote
FOR EACH ROW
DECLARE
  v_client_info VARCHAR2(64);
  PRAGMA AUTONOMOUS_TRANSACTION; 
BEGIN
  -- 检查是否为本地库同步过来的操作,是则跳过
  SELECT USERENV('CLIENT_INFO') INTO v_client_info FROM DUAL;
  IF v_client_info = 'SYNC_FROM_LOCAL' THEN
    COMMIT;
    RETURN;
  END IF;

  -- 设置同步标识,告知本地库触发器这是同步操作
  DBMS_APPLICATION_INFO.SET_CLIENT_INFO('SYNC_FROM_REMOTE');

  IF INSERTING THEN
    INSERT INTO test_order_local@test_local1 (id, desc1, desc2, desc23)
    VALUES (:NEW.id, :NEW.desc1, :NEW.desc2, :NEW.desc23);
  ELSIF UPDATING THEN
    UPDATE test_order_local@test_local1
    SET desc1 = :NEW.desc1, desc2 = :NEW.desc2, desc23 = :NEW.desc23
    WHERE id = :OLD.id;
  ELSIF DELETING THEN
    DELETE FROM test_order_local@test_local1
    WHERE id = :OLD.id;
  END IF;

  -- 重置客户端标识
  DBMS_APPLICATION_INFO.SET_CLIENT_INFO('');
  COMMIT;
END;
/
额外建议

如果是生产环境的双向同步需求,不建议用触发器实现,推荐使用Oracle官方专业同步工具:

  • Oracle GoldenGate:支持异构数据库、低延迟双向同步,适配复杂业务场景
  • Oracle Data Guard:主备架构下可配置为Active Data Guard,实现读写分离+双向同步

内容的提问来源于stack exchange,提问作者Arulselvam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 15:43:12