peewee Lost connection to MySQL server during query解决办法

为什么会出现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服务, 应该就会抛出异常了:

image.png

解决

实现一个自己的基类, 重写父类的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
image.png

在实际业务代码中,当需要使用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)

其他经验

以下方法\color{red}{无法判断} database、 connection 是否失去链接,\color{red}{不要用}这些方法判断是否失去链接:

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容