为什么会出现Lost connection to MySQL server during query
如果服务长时间没获得请求, 数据库链接超时就会断开
治标不治本的解决方法
网上的解决办法是 增长数据库的链接时长
这种解决办法 治标不治本, 你怎么知道 最长没有请求是多长?
另外, 可能是其他原因导致的 Lost connection to MySQL server during query
程序解决 Lost connection 问题
如何模拟 Lost connection to MySQL server during query
首先,要解决这个问题, 得先模拟这个现象
怎么模拟?
难道要把数据库连接时长改短, 然后等上 1、2分钟, 然后测试吗?
其实,可以通过 kill 掉数据库进程, 实现模拟(为什么我知道这个方案, 我推测 + 尝试出来的)
Step 1. 控制台登录数据库
Step 2. 用 show processlist 可以看到当前数据库的进程
Step 3. 启动你的 web 服务
Step 4. 再次用 show processlist , 看看多出来 哪些进程
Step 5. 用 kill ${id} 可以杀掉进程
Step 6. 访问你的web服务, 应该就会抛出异常了:
解决
实现一个自己的基类, 重写父类的connect 函数, 增加 ping 操作, 因为 ping 能解决 Lost connection的问题。
db_conf = {
'database': 'your_database_name',
'host': '192.168.1.1',
'port': 3306,
'user': 'your_database_user',
'password': 'user_password'
}
class BaseModel(Model):
"""base model"""
pymysql_conn = None
class Meta(object):
"""meta"""
logging.info(f'{__file__} database is {Settings.DB_CONF[Settings.SP]}')
database = MySQLDatabase(**db_conf)
@classmethod
def connect(cls):
"""
"""
if not cls.pymysql_conn:
# pymysql_conn 是 pymysql.connections.Connection 对象
cls.pymysql_conn = cls._meta.database.connection()
logging.info(f'connect result: {cls.pymysql_conn}')
cls.pymysql_conn.ping()
return cls.pymysql_conn
在实际业务代码中,当需要使用peewee 的model 进行数据库操作前, 先调用 connect 函数
# 示例代码
# 所有model类 继承上面实现的BaseModel类
class YourModel(BaseModel):
pass
# 某个 service 类里:
class XXXService(object):
def 查询库存(self):
YourModel.connect() # 增加这个操作后, 就不会Lost Connection
query_result = YourModel.select().where(你自己的查询条件, eg. YourModel.id == 1)
其他经验
以下方法 database、 connection 是否失去链接,这些方法判断是否失去链接:
cls._meta.database.is_closed() # 就算丢失链接, 依然返回 False ,我本以为会返回True)
cls._meta.database.connect(reuse_if_open=True) # 第一次总是返回 True, 之后总是返回False , 就算丢失链接
即:
result = cls._meta.database.connect(reuse_if_open=True) --> result = True
result = cls._meta.database.connect(reuse_if_open=True) --> result = False
result = cls._meta.database.connect(reuse_if_open=True) --> result = False
手工 kill Mysql进程
result = cls._meta.database.connect(reuse_if_open=True) --> result = False
# 使用 YourModel.connect() 后
result = cls._meta.database.connect(reuse_if_open=True) --> result = False
注: pymysql_conn 是 pymysql.connections.Connection 对象
pymysql_conn.open 无法准确判断 链接是否 open, 出现异常后 再判断, 才能 判断是否 open
意思是:
pymysql_conn.open --> True
pymysql_conn 执行查询: 正常
手工 kill Mysql进程
pymysql_conn.open --> True
pymysql_conn 执行查询: 异常
pymysql_conn.open --> False