Flask-Migrate迁移中新建engine执行批量插入挂起如何解决
问题原因
你的实现存在两个核心问题直接导致进程挂起:
- 事务锁冲突:Alembic运行
upgrade函数时默认已经开启了一个事务并持有目标表的锁,你额外创建的新引擎会生成独立的数据库连接,这个新连接需要等待原有Alembic事务释放锁才能执行插入操作,最终形成死锁导致挂起。 - 批量优化未生效配置缺失:SQLAlchemy 1.3.x版本的
bulk_save_objects默认会开启return_defaults参数获取插入记录的主键,该参数会打断批量executemany优化,变成单条插入反而降低效率。
修复方案
不需要额外创建新引擎,直接复用Alembic现有连接并补充批量配置即可,修改后的代码如下:
from alembic import op from sqlalchemy.orm.session import Session def upgrade(): list_of_objects_to_insert = get_and_process_objects_from_csv_file() # 直接获取现有连接的引擎,修改executemany配置 engine = op.get_bind().engine engine.update_execution_options(executemany_mode='values_plus_batch') session = Session(bind=engine) # 分批插入避免单次请求过大,每批1000条可根据实际调整 batch_size = 1000 for i in range(0, len(list_of_objects_to_insert), batch_size): batch = list_of_objects_to_insert[i:i+batch_size] # 关闭return_defaults避免打断批量插入 session.bulk_save_objects(batch, return_defaults=False) session.commit() session.close() print('Inserted all records from bulk list')
额外优化建议
- 可根据实际测试调整
batch_size数值,通常PostgreSQL单批插入500-2000条性能最优 - 如果需要进一步提升速度,可直接用SQLAlchemy Core的
insert语句配合values_list批量插入,性能比ORM的bulk_save_objects高15%-30% - 若调整后仍触发CircleCI超时,可在CircleCI配置中给该迁移步骤单独设置更长的
no_output_timeout参数
内容的提问来源于stack exchange,提问作者kenshin23
相关产品推荐
相关产品推荐

