做开发或者运维时,数据库连接突然断开是常有的事。比如程序跑着跑着报错提示“MySQL server has gone away”,或者应用卡一下提示无法连接数据库。这时候如果没人手动干预,服务可能就瘫痪了。其实这类问题完全可以通过合理的重连机制来缓解。
为什么连接会断开
数据库连接不是永远有效的。常见的原因包括:网络波动、数据库服务器重启、长时间空闲被防火墙或中间件切断(比如 MySQL 的 wait_timeout 设置),还有服务器资源不足导致连接被强制释放。特别是云服务器环境下,网络环境复杂,断连更常见。
程序中怎么处理断开重连
以 Python 连接 MySQL 为例,很多人用 PyMySQL 或 MySQLdb。如果不做任何处理,一旦连接断了,下一次查询就会抛异常。可以在执行查询前判断连接是否还有效,无效则重建连接。
import pymysql
def get_connection():
return pymysql.connect(
host='localhost',
user='root',
password='123456',
database='test',
autocommit=True
)
def execute_query(sql):
conn = get_connection()
try:
with conn.cursor() as cursor:
cursor.execute(sql)
return cursor.fetchall()
except (pymysql.err.OperationalError, pymysql.err.InterfaceError):
# 连接出错,尝试重连
conn.close()
conn = get_connection()
with conn.cursor() as cursor:
cursor.execute(sql)
return cursor.fetchall()
finally:
conn.close()
上面的代码在捕获到连接类异常时,先关闭旧连接,再新建一个,然后重新执行 SQL。虽然简单,但能应对大多数临时断连的情况。
使用连接池更省心
对于 Web 应用,频繁创建和关闭连接开销大。推荐使用连接池,比如 DBUtils 配合 PyMySQL,或者 SQLAlchemy 的引擎自带连接池功能。连接池通常内置了连接健康检查和自动重连机制。
from sqlalchemy import create_engine
engine = create_engine(
'mysql+pymysql://root:123456@localhost/test',
pool_recycle=300, # 每隔5分钟重建连接,避免超时
pool_pre_ping=True # 每次取连接前先 ping 一下
)
其中 pool_pre_ping=True 是关键,它会在每次从池中取出连接时发送一个轻量 ping 请求,如果连接失效,自动废弃并创建新连接,对上层透明。
数据库配置别忽略
除了程序端,数据库本身的设置也很重要。比如 MySQL 的 wait_timeout 默认可能是 8 小时,但在高并发或网络不稳的环境可以调短一些,配合应用层更积极地重连。同时,客户端也可以设置连接参数,比如加上 ? 后的 connect_timeout=10&read_timeout=30,避免卡死。
实际场景举例
有个朋友做后台数据同步工具,每天凌晨从生产库拉数据。有天早上发现没数据,查日志才发现夜里连接断了,程序直接退出。后来他在主循环里加了重试逻辑:每次失败等 30 秒再连,最多试 5 次。从此再没因为断连丢过数据。
重连机制不需要多复杂,关键是尽早发现问题,并让程序具备一定的自我恢复能力。尤其是一些定时任务或后台服务,没人盯着,自动重连就是最后一道防线。