SQL 服务器和 Oracle 之间的分布式事务

Distributed transaction between SQL Server and Oracle

我在开始事务并尝试提交在 SQL 服务器上启动的事务时遇到问题。

DECLARE @return_value int,
        @ERROR_MESSAGE nvarchar(2000)

BEGIN TRANSACTION
    EXEC @return_value = [dbo].[SEND_EMAIL]
            @SUBJECT = N'subject',
            @BODY = N'body',
            @RECEIVERS = N'user@email.com',
            @ERROR_MESSAGE = @ERROR_MESSAGE OUTPUT

    SELECT @ERROR_MESSAGE AS N'@ERROR_MESSAGE'

    COMMIT TRANSACTION

    SELECT 'Return Value' = @return_value
GO

和return这个:

OLE DB provider "OraOLEDB.Oracle" for linked server "linked_server" returned message "Unable to enlist in the transaction.".

(1 row(s) affected)

Msg 3930, Level 16, State 1, Line 16
The current transaction cannot be committed and cannot support operations that write to the log file. Roll back the transaction.

(1 row(s) affected)
Msg 3998, Level 16, State 1, Line 3
Uncommittable transaction is detected at the end of the batch. The transaction is rolled back.

我在 SQL 服务器中的存储过程是这样的:

BEGIN TRY
    EXECUTE('Call Schema.Package.StoredProcedure(?,?,?,?,?)', @subject, @body, @receivers, @vcSendBy, @ERROR_MESSAGE OUT) AT [linked_server]

END TRY
BEGIN CATCH

    SET @ERROR_MESSAGE = error_meessage();

END CATCH

这项工作没有 BEGIN TRANSACTION AND COMMIT 但我不知道为什么。

提前致谢。

您需要使用分布式事务协调器。如果您的代码必须包含在事务中,那么对于您的问题没有简单的固定答案。

在此处查看文档:MSDN Distributed Transactions

这是另一个关于这个主题的好文章 link:DTC

由于您的事务跨越多个数据库,因此您需要确保您使用的是分布式事务。请参阅 here 了解如何配置您的服务器。

服务器配置完成后,您可以使用以下语法启动分布式事务:

BEGIN DISTRIBUTED TRAN
    --INSERT, UPDATE, DELETE Data on SQL Server Table
    --INSERT, UPDATE, DELETE Data on Oracle Server Table
COMMIT TRAN 

我解决了我在 Oracle 中执行存储过程时遇到的问题,我在 SQL 服务器中的存储过程中调用了函数

 FUNCTION FUNCTION_CALL_SP (
           SUBJECT IN VARCHAR2,
           BODY IN CLOB,
           RECEIVERADDRESS IN varchar2,
           send_by IN varchar2
 ) RETURN varchar2 IS 

ERROR_MESSAGE   VARCHAR2(400);

BEGIN

SP_SEND_EMAIL(
    SUBJECT           =>   SUBJECT,
    BODY     =>   BODY,
    RECEIVERADDRESS  =>   RECEIVERADDRESS,
    send_by          =>   send_by,
    ERROR_MESSAGE   =>   ERROR_MESSAGE
);
return ERROR_MESSAGE;
END FUNCTION_CALL_SP ;

现在在 SQL 服务器的存储过程中,我有这个:

   SET @vQuery = 'SELECT @vfResult = A.ERRORMESSAGE FROM OPENQUERY(BCIE,''SELECT SCHEMA.PACKAGE.FUNCTION_SEND_EMAIL('''''+@SUBJECT+''''', '''''+@BODY+''''', '''''+@RECEIVERS+''''', '''''+@SEND_BY+''''') ERRORMESSAGE FROM DUAL'') A';

    BEGIN TRANSACTION
    EXEC SP_EXECUTESQL 
              @Query  = @vQuery
            , @Params = N'@vfResult NVARCHAR(MAX) OUTPUT'
            , @vfResult = @vfResul OUTPUT

    SET @ERROR_MESSAGE = @vfResult;
    COMMIT TRANSACTION

并且工作正常。