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

asyncpg+PostgreSQL禁用缓存遇RuntimeWarning问题及正确实现方式

解决asyncpg+PostgreSQL禁用缓存及RuntimeWarning问题

先修复RuntimeWarning错误

你遇到的RuntimeWarning是因为engine.connect()是异步方法,必须先通过await获取连接对象,再调用execution_options。直接链式调用会导致协程未被执行,触发警告。

修正后的retrieve_data_from_db函数:

async def retrieve_data_from_db(query, engine):
    """ Connects to the database and returns the results by a given query """
    # 先await获取连接对象,再设置执行选项
    conn = await engine.connect()
    conn = conn.execution_options(compiled_cache=None)
    try:
        executed_query = await conn.execute(query)
        # 只读查询无需commit,写操作才需要
        return executed_query
    except SQLAlchemyError as exc:
        print(exc)
        raise
    finally:
        await conn.close()

或者用async with的标准写法:

async def retrieve_data_from_db(query, engine):
    """ Connects to the database and returns the results by a given query """
    raw_conn = await engine.connect()
    async with raw_conn.execution_options(compiled_cache=None) as conn:
        try:
            executed_query = await conn.execute(query)
            return executed_query
        except SQLAlchemyError as exc:
            print(exc)
            raise
        # async with会自动管理连接关闭,无需手动调用close

正确禁用各类缓存

要确保获取实时数据库结果,需要针对不同层级的缓存逐一禁用:

1. SQLAlchemy查询编译缓存

通过execution_options(compiled_cache=None)禁用,上面的修正代码已包含该设置。这个缓存用于存储SQLAlchemy编译后的查询语句,禁用后每次查询都会重新编译,确保适配最新的数据库元数据。

2. asyncpg预编译语句缓存

你在engine URL中设置prepared_statement_cache_size=0的方式是正确的,需确保参数格式无误:

engine = create_async_engine(
    f'postgresql+asyncpg://{username}:{password}@{host}/{database}?prepared_statement_cache_size=0',
    pool_pre_ping=True,
    echo=True,
)

该参数会让asyncpg不缓存预编译的SQL语句,每次执行都直接发送原始SQL到PostgreSQL。

3. 事务隔离级别调整(确保实时读取)

PostgreSQL默认的READ COMMITTED隔离级别已能保证读取已提交的最新数据,但如果是长事务场景,可能会读取到事务启动时的快照数据。若需要强制获取最新数据:

  • 确保每次查询都在新事务中执行(即每次查询都重新获取连接)
  • 可以显式设置隔离级别:
conn = await engine.connect()
conn = conn.execution_options(
    compiled_cache=None,
    isolation_level="READ COMMITTED"
)

额外检查项

  • 若使用SQLAlchemy Session,需设置expire_on_commit=True,或在查询后手动调用session.expire_all(),避免Session缓存旧数据
  • 排查应用层是否存在其他缓存(如本地内存缓存、Redis等),这些也会导致读取过期数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 06:48:21