【问题标题】:Distributed transaction between SQL Server and OracleSQL Server 和 Oracle 之间的分布式事务
【发布时间】:2017-04-06 11:56:14
【问题描述】:

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

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

然后返回:

链接服务器“linked_server”的 OLE DB 提供程序“OraOLEDB.Oracle”返回消息“无法加入事务。”。

(受影响的 1 行)

消息 3930,第 16 级,状态 1,第 16 行
当前事务无法提交,也无法支持写入日志文件的操作。回滚事务。

(1 行受影响)
消息 3998,第 16 层,状态 1,第 3 行
在批处理结束时检测到不可提交的事务。事务被回滚。

我在 SQL Server 中的存储过程是这样的:

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 但我不知道为什么。

提前致谢。

【问题讨论】:

  • 您为什么使用事务发送电子邮件?事务用于使数据保持一致状态。发送电子邮件的操作不应改变数据库状态。
  • 当我尝试获取一些参数时,无法提交的事务与我在 Jdeveloper 12c 中的 callablestament 中遇到的问题相同,上面的代码是一种手动重现问题的方法
  • 我解决了我在函数内部执行 Oracle 存储过程的问题,在我的 SQL Server 存储过程中我调用了函数

标签: sql sql-server oracle stored-procedures linked-server


【解决方案1】:

我解决了我在函数内部执行 Oracle 存储过程的问题,在我的 SQL Server 存储过程中我调用了函数

 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 Server 存储过程中,我有这个:

   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

而且工作正常。

【讨论】:

    【解决方案2】:

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

    服务器配置好后,可以启动分布式事务,语法如下:

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

    【讨论】:

      【解决方案3】:

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

      在此处查看文档:MSDN Distributed Transactions

      这是另一个关于该主题的好链接:DTC

      【讨论】:

        猜你喜欢
        • 2010-09-17
        • 2015-09-03
        • 2015-10-04
        • 2012-08-14
        • 1970-01-01
        • 2011-11-04
        • 1970-01-01
        • 2014-10-07
        • 1970-01-01
        相关资源
        最近更新 更多