使用pymqi调用IBM MQ事务时遇MQRC_ENVIRONMENT_ERROR(2012)求助
IBM MQ事务功能启用报错(MQRC_ENVIRONMENT_ERROR)解决方案
问题详情
使用Python pymqi库连接IBM MQ,添加qmgr.begin()启用事务后触发错误:
MQI Error. Comp: 2, Reason 2012: FAILED: MQRC_ENVIRONMENT_ERROR
无事务逻辑的代码可正常运行。
原代码
import logging from datetime import datetime import pymqi logging.basicConfig(level=logging.INFO) queue_manager = 'QM1' channel = b'DEV.APP.SVRCONN' host = '127.0.0.1' port = '1414' queue_name = 'DEV.QUEUE.1' conn_info = f'{host}({port})' conn_info = conn_info.encode('utf-8') user = 'app' password = 'xxxxxx' # Setting up CD() parameters cd = pymqi.CD() cd.ChannelName = channel cd.ConnectionName = conn_info cd.ChannelType = pymqi.CMQC.MQCHT_CLNTCONN cd.TransportType = pymqi.CMQC.MQXPT_TCP # Message to be sent message = f'Message sent to {queue_name} at: {datetime.now()}' kwargs = { 'user': user, 'password': password, 'cd': cd } try: # Connect to the queue manager qmgr = pymqi.QueueManager(None) qmgr.connect_with_options(queue_manager, **kwargs) # Start a transaction qmgr.begin() try: # Open the queue within the transaction queue = pymqi.Queue(qmgr, queue_name) # Put a message to the queue within the transaction queue.put(message) logging.info(message) # Close the queue within the transaction queue.close() # Commit the transaction qmgr.commit() except pymqi.MQMIError as e: # Rollback the transaction in case of an error logging.error(f"MQI error: {e}") qmgr.backout() raise finally: # End the transaction qmgr.disconnect() except pymqi.MQMIError as e: logging.error(f"MQI error: {e}")
原因分析及修复方案
核心问题
客户端模式下(通过SVRCONN通道连接),事务操作需要满足两个关键条件:
- 连接时需确保事务环境初始化正确;
- 发送消息时必须指定
MQPMO_SYNCPOINT选项,将消息绑定到当前事务。
修复后的代码
import logging from datetime import datetime import pymqi logging.basicConfig(level=logging.INFO) queue_manager = 'QM1' channel = b'DEV.APP.SVRCONN' host = '127.0.0.1' port = '1414' queue_name = 'DEV.QUEUE.1' conn_info = f'{host}({port})'.encode('utf-8') user = 'app' password = 'xxxxxx' # 设置CD参数 cd = pymqi.CD() cd.ChannelName = channel cd.ConnectionName = conn_info cd.ChannelType = pymqi.CMQC.MQCHT_CLNTCONN cd.TransportType = pymqi.CMQC.MQXPT_TCP message = f'Message sent to {queue_name} at: {datetime.now()}' kwargs = { 'user': user, 'password': password, 'cd': cd } try: qmgr = pymqi.QueueManager(None) # 连接时指定句柄共享选项,确保事务环境可用 qmgr.connect_with_options(queue_manager, pymqi.CMQC.MQCNO_HANDLE_SHARE_NO_BLOCK, **kwargs) qmgr.begin() try: # 打开队列时指定输出模式,适配事务场景 queue = pymqi.Queue(qmgr, queue_name, pymqi.CMQC.MQOO_OUTPUT + pymqi.CMQC.MQOO_INPUT_AS_Q_DEF) # 发送消息时添加SYNCPOINT选项,绑定到当前事务 queue.put(message, pymqi.CMQC.MQPMO_SYNCPOINT) logging.info(message) queue.close() qmgr.commit() except pymqi.MQMIError as e: logging.error(f"MQI错误: {e}") # 仅在已连接状态下执行回滚 if qmgr.is_connected(): qmgr.backout() raise finally: # 确保断开连接前检查连接状态 if qmgr.is_connected(): qmgr.disconnect() except pymqi.MQMIError as e: logging.error(f"MQI错误: {e}")
额外排查点
- 检查队列管理器是否启用事务支持,目标队列的
DEFPSIST属性建议设为YES(事务消息通常需要持久化); - 确认客户端MQ库版本与队列管理器版本兼容,版本不匹配可能导致环境类错误;
- 验证SVRCONN通道的
MCAUSER是否拥有执行事务操作的权限(例如PUT、COMMIT等)。
内容的提问来源于stack exchange,提问作者K Ashish
相关产品推荐
相关产品推荐

