You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Alembic异步迁移报connect未等待、MissingGreenlet错误

问题根因

报错核心是Alembic默认的同步执行逻辑与配置的postgresql+asyncpg异步数据库驱动不兼容:异步SQLAlchemy引擎的所有IO操作必须在greenlet_spawn启动的异步上下文中执行,直接在Alembic默认同步流程中调用异步连接方法,既不会正确等待协程执行触发RuntimeWarning: coroutine 'connect' was never awaited警告,也会因为缺少greenlet上下文抛出MissingGreenlet错误。

此前两种尝试不生效的原因:

  • 直接将run_migrations_offline()、run_migrations_online()标记为async无效:Alembic命令入口为同步调用逻辑,不会主动await标记为async的迁移函数,只会返回未执行的协程对象。
  • 直接用asyncio.run()包裹原有同步迁移逻辑无效:原有同步迁移逻辑没有做异步连接到同步操作的适配,Alembic本身的迁移API是同步接口,必须通过异步连接的run_sync方法注入到异步上下文中执行。
修复步骤
  • 第一步:重写alembic目录下的env.py文件,使用官方适配异步驱动的逻辑,不要导入项目中自定义的异步引擎、get_async_session这类运行时异步对象,避免提前触发未被上下文管理的异步IO。完整可用的env.py代码如下:
import asyncio
from logging.config import fileConfig

from sqlalchemy import pool
from sqlalchemy.ext.asyncio import create_async_engine
from alembic import context

# 导入项目中定义的ORM模型Base,以及所有需要迁移的模型类,避免模型未加载导致检测不到
from models import Base, Account

config = context.config

if config.config_file_name is not None:
    fileConfig(config.config_file_name)

# 配置自动迁移检测的元数据
target_metadata = Base.metadata


def run_migrations_offline() -> None:
    """离线迁移模式逻辑,无需真实连接数据库"""
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
        url=url,
        target_metadata=target_metadata,
        literal_binds=True,
        dialect_opts={"paramstyle": "named"},
    )

    with context.begin_transaction():
        context.run_migrations()


def _do_run_migrations(connection):
    """同步迁移执行核心逻辑,供异步连接的run_sync方法调用"""
    context.configure(connection=connection, target_metadata=target_metadata)
    with context.begin_transaction():
        context.run_migrations()


async def _run_async_online_migrations() -> None:
    """在线迁移模式的异步逻辑封装"""
    # 从alembic.ini读取连接串创建异步引擎,不要复用项目运行时的引擎实例
    connectable = create_async_engine(
        config.get_main_option("sqlalchemy.url"),
        poolclass=pool.NullPool,
    )

    async with connectable.connect() as connection:
        # 将同步迁移逻辑注入异步连接的上下文中执行
        await connection.run_sync(_do_run_migrations)

    await connectable.dispose()


def run_migrations_online() -> None:
    """在线迁移模式入口,通过asyncio.run启动异步迁移流程"""
    asyncio.run(_run_async_online_migrations())


if context.is_offline_mode():
    run_migrations_offline()
else:
    run_migrations_online()
  • 第二步:检查alembic.ini中的sqlalchemy.url配置,确认连接串前缀为postgresql+asyncpg,账号、密码、地址、端口、库名配置正确。
  • 第三步:清理alembic/versions目录下之前生成的无效空迁移文件,避免旧的错误文件干扰检测。
验证操作

执行迁移生成命令:
alembic revision --autogenerate -m "init_account_table"
正常执行后不会再抛出greenlet相关错误和协程未等待警告,生成的迁移文件中会包含Account表的创建逻辑,后续执行alembic upgrade head即可完成表结构同步。

内容的提问来源于stack exchange,提问作者enchance

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 23:21:49