如何在Python中捕获_mysql_exceptions.OperationalError: 2002错误
处理MySQL 2002错误的实现方案
刚好做过类似的场景,给你整理一下具体的实现方案!针对_mysql_exceptions.OperationalError: 2002(MySQL服务未启动/不可达)的场景,我们只需要在现有的异常捕获块里扩展分支逻辑,跳过数据库写入操作,让脚本继续监听MQTT消息即可。
核心思路
2002错误本质是客户端连不上MySQL服务(比如服务没开、端口配置错或者网络不通),此时硬写数据库肯定失败,我们要做的就是:
- 精准捕获这个错误码,打印提示信息
- 不执行任何数据库操作(包括无效的重连尝试,因为服务没启动的情况下重连也是白费)
- 让脚本回到MQTT监听状态,等下一条消息到来时再尝试连接写入
代码修改示例
假设你现有的消息处理函数是这样的,我们直接在原有异常处理里加2002的分支:
import paho.mqtt.client as mqtt import MySQLdb from MySQLdb import _mysql_exceptions # 用logging替代print,更适合生产环境排查问题 import logging logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) # 数据库配置(替换成你的实际配置) DB_HOST = "your_db_host" DB_USER = "your_db_user" DB_PASS = "your_db_pass" DB_NAME = "your_db_name" # 初始化MySQL连接和游标 def init_db(): db = MySQLdb.connect(host=DB_HOST, user=DB_USER, passwd=DB_PASS, db=DB_NAME) cursor = db.cursor() return db, cursor db, cursor = init_db() # MQTT消息回调函数 def on_message(client, userdata, msg): global db, cursor # 解析MQTT消息(替换成你实际的解析逻辑) payload = msg.payload.decode("utf-8") ts = "your_timestamp_value" # 替换成你的时间字段处理逻辑 value = "your_parsed_value" # 替换成你的消息内容解析结果 try: # 写入数据库,已处理重复时间条目(ON DUPLICATE KEY) sql = """INSERT INTO your_table (timestamp, value) VALUES (%s, %s) ON DUPLICATE KEY UPDATE value = %s""" cursor.execute(sql, (ts, value, value)) db.commit() logger.info("Successfully wrote message to database") except _mysql_exceptions.OperationalError as e: error_code, error_msg = e.args if error_code == 2006: # 原有逻辑:MySQL连接断开,重新初始化连接并重试写入 logger.warning(f"MySQL server gone away: {error_msg} - reconnecting...") db, cursor = init_db() # 重试一次写入 cursor.execute(sql, (ts, value, value)) db.commit() logger.info("Reconnected to MySQL and wrote message successfully") elif error_code == 2002: # 新增逻辑:MySQL服务不可达,跳过写入,继续监听 logger.error(f"MySQL server not reachable (Error 2002): {error_msg} - skipping database write") # 不需要额外操作,函数结束后自动回到MQTT监听状态 except Exception as e: # 处理其他未知异常 logger.error(f"Unexpected error when writing to database: {str(e)}") db.rollback() # MQTT客户端初始化和启动逻辑(替换成你现有的代码) mqtt_client = mqtt.Client() mqtt_client.on_message = on_message mqtt_client.connect("your_mosquitto_host", 1883, 60) mqtt_client.subscribe("your_topic") mqtt_client.loop_forever()
关键细节说明
- 错误码精准区分:通过
e.args拆分错误码和消息,避免2002和2006错误的处理逻辑混淆 - 2002错误的处理边界:只打印日志提示,不做无效操作,确保脚本不会因为MySQL未启动而中断
- 兼容原有稳定逻辑:完全保留你已经实现的2006重连、重复时间条目处理,不需要改动原有可靠代码
- 日志化替代打印:用
logging模块代替print,更方便生产环境的日志追溯和问题排查
这样修改后,当MySQL服务未运行时,脚本会自动跳过数据库写入,持续监听MQTT消息;当服务恢复后,下一条消息到来时会自动尝试连接写入,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Barry L.
相关产品推荐
相关产品推荐

