我在使用 apscheduler 做一个定时任务项目,脚本代码中需要连接数据库做一些操作。所以写了一个这样的类来调用。但是在任务过程中会偶尔会发生任务堵塞情况,经添加日志检测后发现是在某一次任务执行过程中,调用 db_advertise 对象的某个方法似乎无法调用或者找不到这个对象(也可能这个对象死掉了)。导致程序一致卡死在这一步,既不报错,也没法终止。
发生该错误的场景有点随机的,任务启动后一般都会正常,只是在某一个随机时间点会发生这种情况,所以我猜测是不是类的实例化对象死掉了导致。
想请教下这是由于什么原理导致的,有什么办法可以避免?
这是我的数据库连接的文件(config.py)
from dbutils.pooled_db import PooledDB
import pymysql
import configparser
import threading
import time
parse = configparser.ConfigParser()
parse.read("./app/config.ini", encoding='UTF-8')
class DbMysql(object):
def __init__(self,host,port,user,password,database):
self.POOL = PooledDB(
creator=pymysql, # 使用链接数据库的模块
maxconnections=None, # 连接池允许的最大连接数,0和None表示不限制连接数
mincached=0, # 初始化时,链接池中至少创建的空闲的链接,0表示不创建
maxcached=1, # 链接池中最多闲置的链接,0和None不限制
# maxshared=1, # 链接池中最多共享的链接数量,0和None表示全部共享
blocking=True, # 连接池中如果没有可用连接后,是否阻塞等待。True,等待;False,不等待然后报错
maxusage=None, # 一个链接最多被重复使用的次数,None表示无限制
setsession=[], # 开始会话前执行的命令列表。如:["set datestyle to ...", "set time zone ..."]
ping=1,
host = host,
port = int(port),
user = user,
password = password,
database = database,
charset='utf8'
)
# 连接数据库
def connect(self):
conn = self.POOL.connection()
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
return conn,cursor
def close(self,conn,cursor):
cursor.close() # 关闭游标
conn.close() # 关闭数据库
def select(self,sql):
conn,cursor = self.connect()
cursor.execute(sql)
data = cursor.fetchall()
self.close(conn,cursor)
return data
def insertmany(self,query,rows):
conn,cursor = self.connect()
try:
cursor.executemany(query,rows)
conn.commit()
except BaseException as e:
conn.rollback()
finally:
self.close(conn,cursor)
def insert(self,query,row):
conn,cursor = self.connect()
try:
cursor.execute(query,row)
conn.commit()
except BaseException as e:
conn.rollback()
finally:
self.close(conn,cursor)
def update(self,sql):
conn,cursor = self.connect()
data = None
try:
data = cursor.execute(sql)
conn.commit()
except BaseException as e:
conn.rollback()
finally:
self.close(conn,cursor)
return data
db_advertise = DbMysql(
parse.get('db_advertise','host'),
parse.get('db_advertise','port'),
parse.get('db_advertise','user'),
parse.get('db_advertise','password'),
parse.get('db_advertise','database')
)
脚本任务中调用方法就是 from config import db_advertise。有多个脚本可能会同时调用这个类的方法