【Oracle专栏】跨服务器调用ORA-02064: 不支持分布式操作

发布时间:2026/8/25 2:30:23
【Oracle专栏】跨服务器调用ORA-02064: 不支持分布式操作 Oracle OceanBase 相关文档希望互相学习共同进步风123456789-CSDN博客1.背景前几天反馈跨服务器调存储过程包报错ORA-02064: 不支持分布式操作。本文就该问题进行实验及解决。2. 实验2.1 实验准备准备两台服务器A服务器即调用服务器ip 192.168.3.14 、B服务器即被调用服务器ip 192.168.3.122.1.1 A服务器14 准备- 表、存储过程、包创建测试表ew_dayend_log创建存储过程GET_LOGGER 插入表逻辑创建包day_end_test 函数中调用存储过程--表 create table EW_DAYEND_LOG ( logid VARCHAR2(45), function_name VARCHAR2(200), table_name VARCHAR2(200), data_issue VARCHAR2(7), log_time DATE, log_type VARCHAR2(5), message VARCHAR2(500) );--过程 CREATE OR REPLACE PROCEDURE GET_LOGGER(pDataIssue IN varchar2, --期次 pFunctionName IN varchar2, --方法名称 pTableName IN varchar2, --处理表名称 pType IN varchar2, --0成功 1失败 3异常 vMsg IN varchar2) is --处理信息 --插入日志 BEGIN INSERT INTO EW_DAYEND_LOG (LOGID, FUNCTION_NAME, TABLE_NAME, DATA_ISSUE, LOG_TIME, LOG_TYPE, MESSAGE) VALUES (SYS_GUID(), pFunctionName , pTableName , pDataIssue , SYSDATE, pType , vMsg ); COMMIT; END GET_LOGGER;--包 create or replace package day_end_test is function day_end(pDataIssue in varchar2) return varchar2; end day_end_test; / CREATE OR REPLACE PACKAGE BODY day_end_test is function day_end (pDataIssue in varchar2) return varchar2 is vResult varchar2(10); vMsg varchar2(1000); begin vResult : 0; BEGIN GET_LOGGER(pDataIssue, day_end_test, log, 0, 调用测试); /* INSERT INTO EW_DAYEND_LOG (LOGID, FUNCTION_NAME, TABLE_NAME, DATA_ISSUE, LOG_TIME, LOG_TYPE, MESSAGE) VALUES (SYS_GUID(), day_end_test , log , pDataIssue, SYSDATE, 0, 调用测试1); COMMIT;*/ EXCEPTION WHEN OTHERS THEN vMsg : 报错位置 || dbms_utility.format_error_backtrace || 报错信息 || substr(SQLERRM, 1, 200); GET_LOGGER(pDataIssue, day_end_test, log, 3, vMsg); vResult : 1; END; return vResult; end; end day_end_test; /2.1.2 B服务器12 准备- dblink、包创建dblinkew_14创建包day_end_test2--创建dblink create public database link ew_14 connect to xxx identified by xxx using 192.168.3.14/orcl;--包 create or replace package day_end_test2 is function day_end_run(pDataIssue in varchar2) return varchar2; end day_end_test2; / CREATE OR REPLACE PACKAGE BODY day_end_test2 is function day_end_run(pDataIssue in varchar2) return varchar2 is vResult varchar2(10); vMsg varchar2(1000); begin vResult : 0; BEGIN GET_LOGGERew_14(pDataIssue, day_end_test2.day_end_run12, log, 0, 12调用测试); EXCEPTION WHEN OTHERS THEN vMsg : 报错位置 || dbms_utility.format_error_backtrace || 报错信息 || substr(SQLERRM, 1, 200); GET_LOGGEREw_14(pDataIssue, day_end_test2.day_end_run12, log, 3, vMsg); vResult : 1; END; return vResult; end; end day_end_test2; /2.2 实验测试2.2.1 在B服务器14 测试本地的存储过程、包test包发现没有问题保证本地是正确的。执行结果ok2.2.2 在A服务器12 测试调用 B服务器查询dblink 14ok--查询14 select * from EW_DAYEND_LOGEW_14 ;结果查询ok表直接插入14ok--插入 INSERT INTO EW_DAYEND_LOGEw_14 (LOGID, FUNCTION_NAME, TABLE_NAME, DATA_ISSUE, LOG_TIME, LOG_TYPE, MESSAGE) VALUES (SYS_GUID(), day_end_test , log ,2026-08, SYSDATE,0,调用测试1); COMMIT; select * from EW_DAYEND_LOGEw_14;结果插入ok包调用 远端存储过程 ok测试结果查看结果ok包调用 远端包 ORA-02064--修改包体改为调用远程包 CREATE OR REPLACE PACKAGE BODY day_end_test2 is function day_end_run(pDataIssue in varchar2) return varchar2 is vResult varchar2(10); vMsg varchar2(1000); begin vResult : 0; BEGIN --GET_LOGGERew_14(pDataIssue, day_end_test2.day_end_run12, log, 0, 12调用测试); vResult : day_end_test.day_endew_14(pDataIssue); EXCEPTION WHEN OTHERS THEN vMsg : 报错位置 || dbms_utility.format_error_backtrace || 报错信息 || substr(SQLERRM, 1, 200); GET_LOGGEREw_14(pDataIssue, day_end_test2.day_end_run12, log, 3, vMsg); vResult : 1; END; return vResult; end; end day_end_test2;再次测试返回1 报错报错ORA-02064: 不支持分布式操作19行就是插入commit 的时候。至此问题复现。2.3 实验解决2.3.1 修改A服务器14的包 测试no修改A服务器14的包将包中的存储过程注释调 改为直接插入表再测试CREATE OR REPLACE PACKAGE BODY day_end_test is function day_end (pDataIssue in varchar2) return varchar2 is vResult varchar2(10); vMsg varchar2(1000); begin vResult : 0; BEGIN --GET_LOGGER(pDataIssue, day_end_test, log, 0, 调用测试); INSERT INTO EW_DAYEND_LOG (LOGID, FUNCTION_NAME, TABLE_NAME, DATA_ISSUE, LOG_TIME, LOG_TYPE, MESSAGE) VALUES (SYS_GUID(),day_end_test ,log , pDataIssue,SYSDATE, 0,调用测试33); COMMIT; EXCEPTION WHEN OTHERS THEN vMsg : 报错位置 || dbms_utility.format_error_backtrace || 报错信息 || substr(SQLERRM, 1, 200); GET_LOGGER(pDataIssue, day_end_test, log, 3, vMsg); vResult : 1; END; return vResult; end; end day_end_test;在B服务器调用A的包测试结果依然报错 ORA-02064: 不支持分布式操作说明 调用远端包不可以调用远端存储过程可以。2.3.2 增加A服务器含包的存储过程 测试 no--增加存储过程 CREATE OR REPLACE PROCEDURE PRO_TEST(pDataIssue IN varchar2, vResult OUT varchar2) is BEGIN vResult : day_end_test.day_end(pDataIssue); END PRO_TEST;本地测试ok远端调用b依然报错--修改远端调用包改为调用存储过程 CREATE OR REPLACE PACKAGE BODY day_end_test2 is function day_end_run(pDataIssue in varchar2) return varchar2 is vResult varchar2(10); vMsg varchar2(1000); begin vResult : 0; BEGIN --GET_LOGGERew_14(pDataIssue, day_end_test2.day_end_run12, log, 0, 12调用测试); --vResult : day_end_test.day_endew_14(pDataIssue); PRO_TESTew_14(pDataIssue,vResult); EXCEPTION WHEN OTHERS THEN vMsg : 报错位置 || dbms_utility.format_error_backtrace || 报错信息 || substr(SQLERRM, 1, 200); GET_LOGGEREw_14(pDataIssue, day_end_test2.day_end_run12, log, 3, vMsg); vResult : 1; END; return vResult; end; end day_end_test2;测试结果报错 ORA-02064: 不支持分布式操作2.3.3 解决思路1被调用的不要commit解决思路被调用的不要commitrollback等数据库事务操作统一在服务端执行。服务器A 14 被调用端代码注释commit。服务器B 12 调用端增加commit;代码修改如下--服务器A 被调用端去掉commit CREATE OR REPLACE PACKAGE BODY day_end_test is function day_end (pDataIssue in varchar2) return varchar2 is vResult varchar2(10); vMsg varchar2(1000); begin vResult : 0; BEGIN --GET_LOGGER(pDataIssue, day_end_test, log, 0, 调用测试); INSERT INTO EW_DAYEND_LOG (LOGID, FUNCTION_NAME, TABLE_NAME, DATA_ISSUE, LOG_TIME, LOG_TYPE, MESSAGE) VALUES (SYS_GUID(),day_end_test ,log , pDataIssue,SYSDATE, 0,调用测试33); --COMMIT; EXCEPTION WHEN OTHERS THEN vMsg : 报错位置 || dbms_utility.format_error_backtrace || 报错信息 || substr(SQLERRM, 1, 200); GET_LOGGER(pDataIssue, day_end_test, log, 3, vMsg); vResult : 1; END; return vResult; end; end day_end_test;--服务器b 12上增加commit CREATE OR REPLACE PACKAGE BODY day_end_test2 is function day_end_run(pDataIssue in varchar2) return varchar2 is vResult varchar2(10); vMsg varchar2(1000); begin vResult : 0; BEGIN --GET_LOGGERew_14(pDataIssue, day_end_test2.day_end_run12, log, 0, 12调用测试); vResult : day_end_test.day_endew_14(pDataIssue); --PRO_TESTew_14(pDataIssue,vResult); commit; EXCEPTION WHEN OTHERS THEN vMsg : 报错位置 || dbms_utility.format_error_backtrace || 报错信息 || substr(SQLERRM, 1, 200); GET_LOGGEREw_14(pDataIssue, day_end_test2.day_end_run12, log, 3, vMsg); vResult : 1; END; return vResult; end; end day_end_test2;执行结果ok但是被调用的包中不可能只有一个commit而且里面还调用的子过程所以还是采用另外一种方式解决自治事务。2.3.4 解决思路2被被调用的采用自治事务解决思路用Oracle自治事务来解决。在调用端中的procedure中添加oralce自治事务的声明方法为PRAGMA AUTONOMOUS_TRANSACTIO即在服务器B侧增加语句即将分布式调用设置成为自主提交. 修改代码如下--服务器A 14 被调用端增加自治事务申明 CREATE OR REPLACE PACKAGE BODY day_end_test is function day_end (pDataIssue in varchar2) return varchar2 is PRAGMA AUTONOMOUS_TRANSACTION; vResult varchar2(10); vMsg varchar2(1000); begin vResult : 0; BEGIN --GET_LOGGER(pDataIssue, day_end_test, log, 0, 调用测试); INSERT INTO EW_DAYEND_LOG (LOGID, FUNCTION_NAME, TABLE_NAME, DATA_ISSUE, LOG_TIME, LOG_TYPE, MESSAGE) VALUES (SYS_GUID(),day_end_test ,log , pDataIssue,SYSDATE, 0,调用测试33); COMMIT; EXCEPTION WHEN OTHERS THEN vMsg : 报错位置 || dbms_utility.format_error_backtrace || 报错信息 || substr(SQLERRM, 1, 200); GET_LOGGER(pDataIssue, day_end_test, log, 3, vMsg); vResult : 1; END; return vResult; end; end day_end_test;--服务器B 12 调用端去掉commit,改回正常调用 CREATE OR REPLACE PACKAGE BODY day_end_test2 is function day_end_run(pDataIssue in varchar2) return varchar2 is vResult varchar2(10); vMsg varchar2(1000); begin vResult : 0; BEGIN --GET_LOGGERew_14(pDataIssue, day_end_test2.day_end_run12, log, 0, 12调用测试); vResult : day_end_test.day_endew_14(pDataIssue); --PRO_TESTew_14(pDataIssue,vResult); --commit; EXCEPTION WHEN OTHERS THEN vMsg : 报错位置 || dbms_utility.format_error_backtrace || 报错信息 || substr(SQLERRM, 1, 200); GET_LOGGEREw_14(pDataIssue, day_end_test2.day_end_run12, log, 3, vMsg); vResult : 1; END; return vResult; end; end day_end_test2;测试结果ok将被调用端 改回最初的包包里调用的子过程再次测试测试结果ok自此问题彻底解决3.总结1报错场景Oracle不支持分布式操作ORA-02064: 不支持分布式操作一、使用DBLink 调用远程的存储过程远程存储过程存在Commit语句会导致此异常。二、 使用DBLink 调用远程的存储过程时远程存储过程通过引用游标返回结果集也会导致此异常。例如 数据库A ,B 通过DBlink互相访问, 数据库A调用数据库B的存储过程pro_b , pro_b里面有DML语句,且有commit ,或rollback. 这时数据库A通过DBlink 的调用pro_bB就会产生这个错误。2分布式事务原理当需要在多个Oracle数据库之间进行数据一致性操作时就会用到分布式事务。分布在本地和远程两个db的事务同时操作就构成了一个分布式事务。分布式事务采用Two-Phase Commit提交机制保证分布在各个节点的子事务能够全部提交或全部回滚的原子性。在这种机制下事务处理过程分为三个阶段PREPARE发起分布式事务的节点通知各个关联节点准备提交或回滚。COMMIT写入commited SCN释放锁资源FORGET悬疑事务表和关联的数据库视图信息清理各关联节点此时会做三个事情刷新redo信息到redo log中将持有的锁转换为悬疑事务锁取各节点中最大的SCN号进行同步。SQL Server依赖分布式事务协调器Distributed Transaction CoordinatorMSDTC来使用分布式事务Oracle Client使用Oracle Services for Microsoft Transaction Server服务来支持分布式事务。3Oracle 自治事务oracle一个存储过程中调用了另外一个存储过程为了使两个存储过程之间的事务不会相互影响就需要自治事务处理PRAGMA AUTONOMOUS_TRANSACTION; -- 用于标记子程序为自主事务处理到此ok项目管理--相关知识项目管理-项目绩效域1/2-CSDN博客项目管理-项目绩效域1/2_八大绩效域和十大管理有什么联系-CSDN博客项目管理-项目绩效域2/2_绩效域 团不策划-CSDN博客高项-案例分析万能答案作业分享-CSDN博客项目管理-计算题公式【复习】_项目管理进度计算题公式:乐观-CSDN博客项目管理-配置管理与变更-CSDN博客项目管理-项目管理科学基础-CSDN博客项目管理-高级项目管理-CSDN博客项目管理-相关知识组织通用治理、组织通用管理、法律法规与标准规范-CSDN博客Oracle其他文档希望互相学习共同进步Oracle-找回误删的表数据(LogMiner 挖掘日志)_oracle日志挖掘恢复数据-CSDN博客oracle 跟踪文件--审计日志_oracle审计日志-CSDN博客ORA-12899报错遇到数据表某字段长度奇怪现象“Oracle字符型长度50”但length查却没有50_varchar(50) oracle 超出截断-CSDN博客EXP-00091: Exporting questionable statistics.解决方案-CSDN博客Oracle 更换监听端口-CSDN博客