上一篇 / 下一篇 2009-10-12 10:59:41 / 个人分类:实践
一、 问题现象:
在一个test 表上创建触发器如下:
ALTER TRIGGER [TR_test_I]
ON [dbo]. [ test ]
AFTERINSERT , UPDATE
AS
BEGIN
IF EXISTS( SELECT *FROM myTest. test. DBO. testWHERE MM_SNUMB= RTRIM ( @MM_SNUMB))
BEGIN
DELETE FROM myTest. test. DBO. testWHERE MM_SNUMB= RTRIM ( @MM_SNUMB)
END
INSERT INTO myTest. test. DBO. test SELECT *FROM INSERTED
END
当对表test 进行UPDATE 操作时出现如下错误:
[OLE/DB provider returned message: 新事务不能登记到指定的事务处理器中。 ]
OLE DB error trace [OLE/DB Provider 'SQLOLEDB' ITransactionJoin::JoinTransaction returned 0x8004d00a].
消息 7391 ,级别 16 ,状态 1 ,过程 TR_test_I ,第 26 行
The operation could not be performed because the OLE DB provider 'SQLOLEDB' was unable to begin a distributed transaction.
二、 解决方案
根据网上查的资料进行了如下操作:
1. 双方启动MSDTC 服务
MSDTC 服务提供分布式事务服务,如果要在数据库 中使用分布式事务,必须在参与的双方服务器启动MSDTC (Distributed Transaction Coordinator )服务。
2. 在事务开始前加入set XACT_ABORT ON 语句
对于大多数OLE DB 提供程序(包括SQL Server ),必须将隐式或显示事务中的数据修改语句中的XACT_ABORT 设置为ON 。唯一不需要该选项的情况是在提供程序支持嵌套事务时。
3. MSDTC 设置
打开“ 管理 工具―― 组件服务” ,以此打开“ 组件服务―― 计算机” ,在“ 我的电脑” 上点击右键。在MSDTC 选项卡中,点击“ 安全配置” 按钮。在安全配置窗口中做如下设置:
1) 选中“ 网络DTC 访问”
2) 在事务管理通讯中设置时,事务发起服务器选“ 允许出站“,
事务处理服务器选” 允许入站” ,都选择” 不要求进行验证”
3) 选中启用XA 事务
4) 保证DTC 登陆账户为:NT Authority/NetworkService
4. 确定后自动重启MSDTC 服务
5. 重新执行对test 表的UPDATE 操作,执行成功。
三、 进一步实验
上面的方法是通过“SQLOLEDB “,创建链接服务器来进行的。
之后,我有尝试使用ODBC 创建链接服务器进行测试 时也是经过了一番波折。
1. 创建链接服务器:
EXEC sp_addlinkedserver 'mytest' , '' , 'MSDASQL' , 'test'
GO
EXEC sp_addlinkedsrvlogin ' myte' , false, 'sa' , 'sa'
GO
2. 建立用户 DSN
3. 执行 对test 表的UPDATE 操作时,产生如下错误:
[OLE/DB provider returned message: [Microsoft][ODBC 驱动程序管理器 ] 未发现数据源名称并且未指定默认驱动程序 ]
OLE DB error trace [OLE/DB Provider 'MSDASQL' IDBInitialize::Initialize returned 0x80004005: ].
消息 7399 ,级别 16 ,状态 1 ,过程 TR_MOLD_MASTER_I ,第 26 行
OLE DB provider 'MSDASQL' reported an error.
4. 经过多次调整链接参数后仍无法解决,无奈之下只好删除该 DSN, 创建了一个与之同样设置的系统 DSN ,进行测试时,经过一个较为漫长的等待后竟然成功了 ( 真是太让人惊讶了 )
注: 与用户 DSN 不同的是系统 DSN 允许所有登录服务器的用户使用 。
四、 总结:
经过一番折腾,触发器终于如愿正常使用了。通过比较网上针对此类问题的其它说明,我个人认为其中的部分内容并非引起该问题的原因,在设置时是可有可无的。
1. 开始时填写的 BEGIN DISTRIBUTED TRANSACTION 、 COMMIT TRANS
2. MSDTC 设置时的客户端和远程访问,事务管理通讯中的允许入站或出站 ( 虽然自己没有尝试了解进一步的原因,但个人认为不了解的东西使用的越少越好 )
3. 链接服务器远侧域名解析, 135 端口等,在 MSDTC 服务启用的情况下,此类问题都可以不去考虑
但是,其中的有些细节是必须注意的,如 :
SET ON 改为 OFF 时,会产生如下错误:
[OLE/DB provider returned message: 无法在此会话中启动更多的事务。 ]
OLE DB error trace [OLE/DB Provider 'SQLOLEDB' ITransactionLocal::StartTransaction returned 0x8004d013: ISOLEVEL=4096].
消息 7395 ,级别 16 ,状态 2 ,过程 TR_MOLD_MASTER_I ,第 28 行
Unable to start a nested transaction for OLE DB provider 'SQLOLEDB'. A nested transaction was required because the XACT_ABORT option was set to OFF.
缺少该语句时,也会产生同样的错误。
不管如何,上面的内容只是自己在现有的环境下测试得出的结果,并不保证其它的环境同样适用。希望能给大家帮助。
最后添加一个微软 的DTC测试工具http://space.itpub.net/?uid-672726-action-viewspace-itemid-616306