MySQL连接池应对连接中断与服务器宕机的处理方法咨询
处理MySQL连接池中的失效连接问题
我来帮你理清楚这个场景下的问题,并给出可行的解决方案。
现有代码的问题&场景分析
首先,你的getDbCnx()函数在连接池初始化完成后,每次调用只是从池中取出空闲连接,但不会验证这个连接是否仍然有效。当MySQL服务器宕机,或者池中连接因闲置超时被服务器断开后,你拿到的会是一个“失效连接”:
- 执行查询时会抛出类似
Lost connection to MySQL server during query或MySQL server has gone away的错误 - 现有异常处理只覆盖了初始化阶段的权限错误、数据库不存在错误,完全没处理连接失效的情况;甚至如果
dbConn是无效状态,调用dbConn.close()还会触发新的异常
解决方案:连接有效性验证+自动重试
要解决这个问题,核心思路是:每次从连接池拿到连接后,先验证它是否可用;如果失效,就关闭该连接并重新获取新连接。
修改后的getDbCnx()函数
下面是优化后的代码,增加了连接验证、失效连接处理和重试机制:
import mysql.connector from mysql.connector import errorcode def getDbCnx(retries=3): # 避免无限重试,设置最大重试次数 if retries <= 0: print("Max retries reached, unable to get valid database connection") return None dbConn = None try: # 从连接池获取连接 dbConn = mysql.connector.connect( pool_name="connectionPool", pool_size=3, pool_reset_session=True, **dbConfig ) # 验证连接有效性:执行一个轻量查询 with dbConn.cursor() as cursor: cursor.execute("SELECT 1") cursor.fetchone() except mysql.connector.Error as err: # 关闭失效连接(如果存在) if dbConn is not None: try: dbConn.close() except: pass # 忽略关闭时的异常 # 处理不同类型的错误 if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: print("Error: Invalid username or password") return None elif err.errno == errorcode.ER_BAD_DB_ERROR: print("Error: Target database does not exist") return None # 匹配连接失效相关的错误码 elif err.errno in [ errorcode.CR_SERVER_LOST, errorcode.CR_SERVER_GONE_ERROR, errorcode.CR_CONN_HOST_ERROR ]: print(f"Connection lost to MySQL server: {err}. Retrying... ({3 - retries + 1}/3)") # 递归调用,减少重试次数 return getDbCnx(retries - 1) else: print(f"Unexpected database error: {err}") return None else: return dbConn
代码说明
- 连接有效性验证:通过执行
SELECT 1这个轻量级查询,确认连接是否能正常与服务器通信。如果查询失败,说明连接已失效。 - 失效连接处理:一旦检测到连接失效,立即关闭该连接(从连接池中移除),然后递归调用函数重新获取连接。
- 重试机制:设置最大重试次数,避免因服务器长期不可用导致无限递归。
- 异常覆盖:补充了连接失效相关的错误码判断,同时优化了资源清理逻辑,避免无效连接的
close()操作引发新异常。
额外建议
- 可以在
dbConfig中添加连接超时参数,比如connection_timeout=30(设置连接超时30秒),避免在服务器不可用时长时间等待。 - 协调DBA调整MySQL服务器的
wait_timeout和interactive_timeout参数,尽量匹配你的业务场景,减少因闲置导致的连接断开。
内容的提问来源于stack exchange,提问作者Vishal Sharma
相关产品推荐
相关产品推荐

