使用.NET C#调用IBM MQ 9.1.5分布式事务遇2035错误的咨询
解决IBM MQ分布式事务2035权限错误及相关疑问
你遇到的2035错误(MQRC_NOT_AUTHORIZED)是典型的权限问题,和启用XA分布式事务后涉及的恢复队列、DTC配置直接相关,下面逐个解答你的疑问:
关于SYSTEM.DOTNET.XARECOVERY.QUEUE的疑问
- 队列是否存在于队列管理器?
默认情况下,IBM MQ 9.1.5不会自动创建这个队列。它是.NET客户端处理XA事务恢复的专用队列,必须你手动在队列管理器上创建它,才能让分布式事务的恢复机制正常工作。 - 是否需要启用权限?
必须要!你的应用程序使用的MQ用户ID需要拥有这个队列的至少PUT、GET和INQ权限——分别用于写入恢复消息、读取恢复信息和查询队列状态。
你可以用MQSC命令配置权限,示例如下:SET AUTHREC PROFILE(SYSTEM.DOTNET.XARECOVERY.QUEUE) OBJTYPE(QUEUE) PRINCIPAL('你的应用MQ用户ID') AUTHADD(PUT,GET,INQ)
关于Microsoft Distributed Transaction Manager(MS DTC)的疑问
没错,MS DTC必须在你的应用所在的本地主机上运行,而且要正确配置才能和IBM MQ协同完成分布式事务。因为DTC是跨资源事务的协调者,负责保证MQ和其他事务性资源(比如数据库)的事务一致性。
额外提几个关键配置点:
- 确保
Distributed Transaction Coordinator服务已经启动(可以在Windows服务列表里找到它) - 如果MQ队列管理器在远程服务器,需要在DTC配置里启用网络访问,允许入站/出站事务,同时配置防火墙开放DTC的通信端口
- 确认你的MQ客户端安装了XA事务支持组件(9.1.5版本的客户端默认包含,但可以检查是否正确注册了XA驱动)
给你代码的小优化建议
你代码里重复初始化了getMessageOptions,可以删掉那行重复的代码;另外,使用CommittableTransaction时,最好显式将MQ操作纳入当前事务范围,避免和环境事务冲突,调整后的代码片段如下:
var getMessageOptions = new MQGetMessageOptions(); getMessageOptions.Options += MQC.MQGMO_WAIT + MQC.MQGMO_SYNCPOINT; getMessageOptions.WaitInterval = 20000; // 20 seconds wait Transaction oldAmbient = Transaction.Current; using (var tx = new CommittableTransaction()) { Transaction.Current = tx; // 显式绑定当前事务 try { int i = queue.CurrentDepth; Log.Information($"Current queue depth is {i} message(s)"); var message = new MQMessage(); queue.Get(message, getMessageOptions); string messageStr = message.ReadString(message.DataLength); Log.Information(messageStr); tx.Commit(); } catch (MQException e) when (e.Reason == 2033) { Log.Information("No messages in the queue"); tx.Rollback(); } catch (Exception ex) { Log.Error($"Exception when trying to capture a message from the queue: {ex.Message}"); tx.Rollback(); throw; } finally { Transaction.Current = oldAmbient; // 恢复原环境事务 } }
内容的提问来源于stack exchange,提问作者jumpercake
相关产品推荐
相关产品推荐

