SQL Server链接服务器存储过程SSMS正常,Delphi ADO调用报错
链接服务器调用Oracle时的事务启动错误(Delphi ADO调用vs SSMS直接执行)
我们有一个运行在SQL Server上的存储过程,通过链接服务器与Oracle表交互,核心逻辑是动态获取链接服务器名称,通过EXEC动态SQL完成三个步骤:
- 向Oracle写入初始数据
- 从Oracle读取处理结果到临时表
- 更新Oracle表标记已处理数据
存储过程核心代码片段:
写入Oracle数据
DECLARE @lksrv VARCHAR(300); SELECT @lksrv = Value FROM cfg; EXEC(' INSERT INTO ' + @lksrv + 'EXTERNALTABLE(TSTATUS, MSGGER, FIELD1, FIELD2, ...) SELECT 0 AS TSTATUS, NULL AS MESSAGE, FValue1, FValue2, ... FROM InternalTable ');
读取Oracle处理结果
EXEC(' INSERT INTO ##TemporaryValues (FiedlRet1, FiedlRet2...) SELECT E.RETVALUE1, E.RETVALUE2... FROM ' + @lksrv + 'EXTERNALTABLE e WHERE e.TSTATUS IN (2, 3, 25, 29) ');
标记Oracle已处理数据
EXEC(' UPDATE e SET TSTATUS = t.FinalResult FROM ' + @lksrv + 'EXTERNALTABLE e INNER JOIN ##TemporaryValues t ON t.KEY = e.KEY ');
注释掉所有链接服务器访问逻辑后,两种调用场景(SSMS/Delphi ADO)均正常运行。
环境版本信息
SQL Server版本
Microsoft SQL Server 2016 (SP2-CU15) (KB4577775) - 13.0.5850.14 (X64) Sep 17 2020 22:12:45 Copyright (c) Microsoft Corporation Standard Edition (64-bit) on Windows Server 2019 Standard 10.0 <X64> ( Build 17763: ) (Hypervisor)
Oracle环境信息
- ODA版本:Product Name: ODA X8-2L
- 数据库版本:Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production Version 19.14.0.0.0
- 已安装补丁:
- 32327201;R
- DBMS - DSTV36 UPDATE - TZDATA2020E
- 31324507;INSTANCE CRASHED AFTER SEVERAL PROCESS HANG DUE TO LATCH CACHE BUFFERS CHAINS
- 32374616;ALLOW UNDERSCORE AND HYPHEN FOR ORACLE_SID
- 30870248;UNEXPECTED W000...FAILED TO ATTACH... SCREEN MESSAGES DURING BROKER SWITCHOVER
- 33710568;19.14 DBVM PROVISION DCS-10001 FAILED TO CREATE THE DATABASE PRCZ-4001 PRCZ-2103 [FATAL] ERROR IN PROCESS ?/BIN/ORAPWD
- 33657803;MERGE ON DATABASE RU 19.14.0.0.0 OF 33314523 33548869
- 32984625;RANDOM AFD DISK MISSING AFTER A NODE REBOOT IN SIHA.
- 33531364;LNX64-1913-CMT ASMCMD SHOULD SHOW ERROR MESSAGE ON FAILURES
- 33312823;LNX64-1912-CMT LOTS OF KJOER_OS_GETNEXT FAILED MESSAGES FLOODING IN GEN0 TRACE AND UNPUBLISH FENCED ORPHAN MSG IN ASM ALERT LOG
- 33695048;LOG4J 2.17 CPU FIX FOR CVE-2021-45105 FOR SPATIAL CLIENT SIDE JARS
- 31335037; RDBMS - DSTV35 UPDATE - TZDATA2020A
- 30432118;MERGE REQUEST ON TOP OF 19.0.0.0.0 FOR BUGS 28852325 29997937
- 33561310;OJVM RELEASE UPDATE: 19.14.0.0.220118 (33561310)
- 31732095;UPDATE PERL IN 19C DATABASE ORACLE HOME TO V5.32
- 33497160;JDK BUNDLE PATCH 19.0.0.0.220118
- 33837519;OCW Interim patch for 33837519
- 33515361;Database Release Update : 19.14.0.0.220118 (33515361)
- 部署模式:多租户(包含一个PDB)
问题现象
- a) 在SQL Server Management Studio中直接执行该存储过程,运行完全正常;
- b) 在Delphi 2010应用中通过ADO连接(
TADOQuery或TADOStoredProcedure)调用时,抛出错误:
Cannot start a transaction for OLE DB provider "OraOLEDB.Oracle" for linked server "XX"
排查与解决线索
检查ADO连接的事务属性
Delphi的ADO组件默认可能隐式开启事务,比如TADOConnection的Attributes包含xaCommitRetaining/xaAbortRetaining,或IsolationLevel设置过高。尝试显式控制事务:ADOConnection1.BeginTrans; try ADOStoredProc1.ExecProc; ADOConnection1.CommitTrans; except ADOConnection1.RollbackTrans; raise; end;或者将
ADOConnection的Attributes设为[],禁用隐式事务保留。修改链接服务器的事务设置
在SQL Server中调整链接服务器的OLE DB提供程序配置:- 进入服务器对象 -> 链接服务器 -> 提供程序 -> OraOLEDB.Oracle,取消勾选启用分布式事务处理
- 或通过T-SQL关闭远程事务提升:
EXEC sp_serveroption @server=N'XX', @optname=N'remote proc transaction promotion', @optvalue=N'false';
调整存储过程的事务边界
在存储过程中显式控制事务,避免隐式事务干扰链接服务器操作:BEGIN TRANSACTION; BEGIN TRY -- 写入Oracle数据的EXEC语句 -- 读取结果的EXEC语句 -- 标记已处理的EXEC语句 COMMIT TRANSACTION; END TRY BEGIN CATCH ROLLBACK TRANSACTION; THROW; END CATCH更新OraOLEDB.Oracle驱动版本
确保SQL Server服务器上的OraOLEDB.Oracle驱动与Oracle 19c兼容,尝试升级到对应版本的Oracle客户端驱动,旧版本可能存在分布式事务兼容性问题。验证MSDTC配置(若需分布式事务)
若必须使用分布式事务,检查SQL Server所在服务器的MSDTC配置:- 确保MSDTC服务已启动
- 在组件服务中,开启MSDTC的网络访问、远程客户端支持
- 确认Oracle服务器端事务管理器允许与MSDTC交互
内容的提问来源于stack exchange,提问作者Agostinho
相关产品推荐
相关产品推荐

