起因
批量耗时任务创建的api,最开始采用for循环串行执行耗时任务,使用的是请求初始化时的数据库session,技术上没问题。
报错
但业务上需要优化成并发。
上来直接改造多线程,发现子线程很快stoped,根本没执行
坑1 子线程的异常不会被主进程捕获
望着代码陷入自我怀疑,再三确认了多线程的代码没问题,想起来如题的坑,于是在子线程的函数中加入try catch,通过logging主动捕获并打印出异常。
坑2 多线程使用同一个会话报错
异常打出来了:
Instance '<Target at 0x7efe1a66bb80>' is not persistent within this Session
于是修改子线程函数,增加参数,接受一个新创建的会话。继续报错如下:
坑3 旧会话需要关闭,新会话要添加数据实体
Object '<Target at 0x7ff45077d3f0>' is already attached to session '1' (this is '2')
from sqlalchemy.orm import sessionmaker
from your_model import YourModel, engine
## 关闭旧会话
session_old.close()
# 将实体添加到另一个会话中
# 创建会话
Session = sessionmaker(bind=engine)
session = Session()
# 创建一个新实体或获取现有实体
entity = YourModel(...)
# 将实体添加到会话
session.add(entity)
# 进行操作
# ...
# 提交会话
session.commit()
# 关闭会话
session.close()
终于,世界恢复平静!