消息 7391:链接服务器无法开始分布式事务(两个 svrs 在本地运行)

Posted

技术标签:

【中文标题】消息 7391:链接服务器无法开始分布式事务(两个 svrs 在本地运行)【英文标题】:Msg 7391: linked server unable to begin a distributed transaction (both svrs running locally) 【发布时间】:2017-01-18 14:42:13 【问题描述】:

我将 LinkedServer 从 SqlServer 2014 设置为在我的 Win 10 PC 上运行的 mysql 5.7.3。选择和插入查询都可以通过 openquery 单独工作,但插入查询不会在触发器中起作用。请不要将此标记为重复,除非您找到下面未列出的“治疗”!

链接服务器“MYSQL”的 OLE DB 提供程序“MSDASQL”返回消息“[MySQL][ODBC 5.3(w) Driver]Optional feature not supported”。

*消息 7391,级别 16,状态 2,过程 TRG_AfterEventInsert,第 14 行

无法执行操作,因为链接服务器“MYSQL”的 OLE DB 提供程序“MSDASQL”无法开始分布式事务。

关于这方面的帖子有很多,但我已经做了我能找到的所有事情,但它仍然无法正常工作。我发现了一个名为 dtcping 的 MS 实用程序,它起初失败,直到我翻转了注册表设置,但现在它成功了。

在 DTC 属性屏幕上,我启用了网络 DTC 管理员、允许远程、允许输入/出站而无需身份验证和启用 XA 事务。在我的链接服务器上,我有 rpc & rpc out = true 并且“启用 DT 提升”为 false。我将 msdtc 应用添加到防火墙排除项中。

我还尝试为我的 LinkedServer 禁用 DTC,但没有奏效。我仍然得到错误。

任何人都可以在这里提出调试措施吗?我花了几乎一整天的时间在这上面没有成功。 MySQL驱动是5.3(32位)。

更新: dtcPing 运行没有错误,但是当我尝试触发插入时,我在 dtctrace.log 中看到以下内容

TRANSACTION_BEGUN RM_ENLISTED_IN_TRANSACTION "资源管理器 #1001 作为事务登记 #1 登记。RM guid = '57c2b4b4-f37a-4017-a1fc-2d95bd64693d'"

RECEIVED_ABORT_REQUEST_FROM_BEGINNER "收到初学者中止交易的请求"

TRANSACTION_ABORTING "事务正在中止"

【问题讨论】:

【参考方案1】:

你的意思是 MySQL 5.3 吗?当前手册显示版本低至 5.7,并指出分布式事务仅支持 InnoDB 存储引擎14.3.7 XA Transactions。

如果您已经检查了 MySQL 部分的所有内容,您是否检查过 SQL Server 端的不同类型的触发器?您是否使用了不受支持的数据类型?

【讨论】:

抱歉...在 5.7 版本中出现错字,是的,我肯定在使用 InnoDB 存储。触发器是“插入后”,我只是运行在我的正常 SQL 会话中运行良好的相同插入查询。【参考方案2】:

"包裹在触发器中的分布式查询,即使没有 明确指定的事务,也被视为分布式 交易。”

support.microsoft.com/en-us/kb/274348

所以您需要使用 DTC 或使用来自 Calling linked server from trigger 的 (2)

【讨论】:

我正在尝试使用 DTC。链接中的替代方法不好。我无法从 SQLSVR 复制到 MYSQL,调度任务会导致延迟。 @DeannaD,在我提到的cmets中,不需要等到任务被调度触发,你可以从触发器开始一个工作,所以延迟最小并且记录将被处理几乎立即。或者,您可以连续运行作业,每 X 毫秒检查一次表格。 @DeannaD,至于复制,有各种客户(非本地)解决方案可以从 MSSQL 复制到 MySQL,例如symmetricds.org【参考方案3】:

创建触发器时,请使用以下构造来避免事务:


create trigger ti on t for insert, update as
begin

    COMMIT -- Commit FIRST to avoid DTC...
    insert into  [mysql]...[mysql.customers] (a,b) -- Do you work
    select  i, 'Test'
    from    inserted
    BEGIN TRAN -- Start tran again otherwise it will crash!!
end
go

注意,“[mysql]...[mysql.customers]”语法,请求提供者 MSDASQL 启用仅级别 0 设置(转到链接服务器并在提供者上设置)。

但正如其他人所建议的那样,你最好还是直接从触发器中踢出一份工作。

完整的测试代码:

---------------
-- Run on MYSQL...
---------------
CREATE TABLE customers (a INT, b CHAR (20), INDEX (a)) ENGINE=InnoDB;

---------------
-- Run on SQL Server
---------------
create table t (i int)

go

create trigger ti on t for insert, update as
begin

    COMMIT -- Commit tran to avoid DTC...
    insert into  [mysql]...[mysql.customers] (a,b)
    select  i, 'Test'
    from    inserted
    begin tran -- Start tran again otherwise it will crash!
end
go

insert into t (i) select 1

-- Verify results
select *
from [mysql]...[mysql.customers]

【讨论】:

以上是关于消息 7391:链接服务器无法开始分布式事务(两个 svrs 在本地运行)的主要内容,如果未能解决你的问题,请参考以下文章

链接服务器问题解救未验证

链接服务器无法开始分布式事务 - SQL Server

在没有分布式事务的链接服务器上调用过程

无法执行操作,因为链接服务器的 OLE DB 提供程序“SQLNCLI11”无法开始分布式事务

无法执行该操作,因为链接服务器 "XXX" 的 OLE DB 访问接口 "SQLNCLI10" 无法启动分布式事务。

链接服务器的 OLE DB 访问接口 "SQLNCLI" 无法启动分布式事务 外加SQL事务死锁问题