pymysql获取链接卡死

问题遇到的现象和发生背景

我在使用python脚本处理一些计算需要操作MySQL数据库,使用了pymysql包封装了一个MySQL增改查删的类方法。定时执行脚本,但是有时会造成任务假死导致始终无法结束,第二次任务唤起时遭遇堵塞导致任务失败。经过添加日志查到是pymysql模块的connect()方法获取连接时卡死,即无法获取连接,也没有报错,一直停留在这一步。

这种问题是随机发生的,任务部署在服务器上。一般本地复现不了

用代码块功能插入代码,请勿粘贴截图
#mysql封装的类
class db_sdpku():
    instance = None
    def __new__(cls, *args, **kwargs):
        # 判断类属性是否已经被赋值
        if cls.instance is None:
            cls.instance = super().__new__(cls)
        # 返回类属性中单例的引用
        return  cls.instance

    def __init__(self):
        self.__db_host = parse.get('db_sdpku','host')
        self.__db_port = int(parse.get('db_sdpku','port'))
        self.__db_user = parse.get('db_sdpku','user')
        self.__db_password = parse.get('db_sdpku','password')
        self.__db_database = parse.get('db_sdpku','database')
    # 连接数据库
    def connect(self):
        conn = pymysql.connect(
            host=self.__db_host,
            port=self.__db_port,
            user=self.__db_user,
            password=self.__db_password,
            database=self.__db_database,
            connect_timeout=10,
            charset='utf8'
        )
        cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
        return conn,cursor
    def close(self,conn,cursor):
        cursor.close()  # 关闭游标
        conn.close()  # 关闭数据库
    def select(self,sql):
        logger.info(f'开始查询-{sql[0:100]}')
        conn,cursor = self.connect()
        logger.info(f'链接成功-{sql[0:100]}')
        cursor.execute(sql)
        data = cursor.fetchall()
        logger.info(f'查询结束-{sql[0:100]}')
        self.close(conn,cursor)
        return data


######以下是日志结果
INFO 2022-11-18 19:36:55 config 开始查询-select a.account_id,a.access_token,'2022-11-18' date
from advertisers a,cost_daily_reports c where c.date='2022-11-18' and c.cost>0
and c.advertiser_id=a.id AND a.wechat_account_id<>'';
这一句开始查询有打印,之后就没有的结果,所以问题基本就处在了conn,cursor = self.connect()。我设置了链接超时时间是10s,如果是因为超时程序一直在尝试去连接数据库,超过10s应该报错结束,但显然是没有的,一直持续在这一环节,最终整个任务的堵塞。像问问这是什么原因导致,还是我方法有用的不对

两点考虑
1.数据量的大小
2.不要频繁用类实例去连接数据库,可以考虑数据池。如:https://blog.csdn.net/moli_Y/article/details/127923274

你把复现教程发给我看一下啊

建议采用连接池的方式,避免并发的情况

pymysql连接池_SakuraKizuna的博客-CSDN博客_pymysql连接池

执行期间建议检查一下数据库连接会话数。

40行 self.close(conn,cursor) 该为 cursor.close() # 关闭游标 试试。
如果后续程序有调用 conn,改为 cursor.close() # 关闭游标 conn.close() # 关闭数据库 试试。

去MYSQL监控下链接数,多半是出现异常了,没正确调用close方法释放资源,导致链接数满了,链接数mysql默认才100,mysql命令行执行

show processlist

更改mysql最大连接数,有可能是在线连接数上限了卡死了
mysql>show variables like 'max_connections';(查可以看当前的最大连接数)

msyql>set global max_connections=1000;(设置最大连接数为1000,可以再次查看是否设置成功)

mysql>exit

pymysql 读取大数据内存卡死的解决方案

参考文章:

(1)pymysql 读取大数据内存卡死的解决方案

(2)https://www.cnblogs.com/mangM/p/11899498.html

把数据库封装改为数据池封装,这个会解决,你自己连接之后查询数据有没有将数据库断开或者进程销毁,没有得话python进程会很慢销毁,而且数据库断开重连机制还得有,最好采用数据池,我这里有封装得,如果需要可以给你