我插入了4000行中的95行视频元数据后,遇到以下错误。sqlalchemy.exc.TimeoutError:大小为5的QueuePool溢出10达到极限,连接超时,超时30(此错误的背景位于:{{3 }}。
基础
engine = db.create_engine(connect_string)
con = engine.connect()
_SessionFactory = sessionmaker(bind=engine)
Base = declarative_base()
def session_factory():
Base.metadata.create_all(engine)
return _SessionFactory()
视频对象
class Video(Base):
__tablename__ = 'video'
video_to_person = Table('video_to_person', Base.metadata,
Column('video_id', String, ForeignKey('video.vid')),
Column('person_id', Integer, ForeignKey('person.id'))
)
_vid = Column("vid",String, primary_key=True)
_webpage_url = Column("webpage_url", String)
_upload_date = Column("upload_date", Date)
_uploader = Column("uploader", String)
_view_count = Column("view_count", DECIMAL)
_like_count = Column("like_count", DECIMAL)
_dislike_count = Column("dislike_count", DECIMAL)
_format = Column("format", String)
_duration = Column("duration", DECIMAL)
_title = Column("title", String)
_description = Column("description", String)
persons = relationship("Person", secondary=video_to_person)
视频存储库:
class VideoRepository():
def create_video(self, vid: Video):
session = session_factory()
session.add(vid)
session.commit()
session.close()
如何改善连接管理?
更新: 感谢到目前为止的答复。挑战之一是我所有的模型类(视频类)从Base继承。 Base始终创建一个新的引擎对象。我将研究进一步的重构。
答案 0 :(得分:1)
如该特定错误的doc中所述,由于您的应用程序超出了它根据create_engine调用设置的限制可以并行打开/使用的连接数,因此收到此错误。在这种情况下,它将使用默认值,即pool_size=5
,max_overflow=10
和pool_timeout=30
。
这意味着使用单个引擎,您最多可以使用15个并发连接到数据库,达到该限制时,一旦有新请求实例化新连接,它将等待30秒,如果没有同时释放了15个已经建立的连接,这会引发错误。
如doc中所述,这可能有不同的原因:
- 应用程序正在根据池中配置的值处理太多并发请求以完成工作
- 应用程序未将连接返回到池
- 该应用程序正在尝试运行长时间运行的事务
- 应用程序处于死锁状态
鉴于提供的信息,我猜是:
您使用了过多的线程(即>> 15),有时引擎无法提供新的连接
您使用的线程数有限(可能为16个),并且代码中出现死锁。
我的建议:
检查缓慢的查询日志并查找长时间锁定表的查询
重构代码,以免每次会话时都调用[Base.metadata.create_all][2](engine)
。通常在应用程序启动时(而不是每次插入记录时)调用此东西。如果需要,请至少设置checkfirst=True
,以免触发CREATE TABLE语句。这可能是造成僵局的原因
如果可能,请使用批量插入。您将免费获得巨大的性能提升,并将更好地利用您的连接池。
一旦确定了问题的根本原因(并且仅在此之后),您可以调整两个参数pool_size
和max_overflow
。您可以轻松地将pool_size增加到15或25,并将max_overflow增加到15