asyncpg连接池set_config设置参数后current_setting返回空值问题
问题根因
出现这个问题是asyncpg连接池的默认机制导致的:
- asyncpg连接池默认开启连接状态重置能力:为了避免复用连接时出现跨请求状态污染(比如上一个请求设置的会话参数、创建的临时表遗留到下一个请求),连接池会在连接每次借出、归还时,把会话状态重置为连接刚创建完成的初始状态。你在
init回调里手动调用set_config设置的自定义参数,不属于连接的默认初始状态,会在第一次重置时被清空,恢复为自定义参数的默认空值。 - 你在控制台的测试现象也符合这个逻辑:第一次执行
set_config时,连接池分配一个连接执行语句,执行完归还连接时触发状态重置,设置的参数被清空;第二次执行查询时,不管拿到的是不是之前用过的连接,参数值都已经是空字符串。
补充说明:你给set_config传第三个参数为False本身是正确的,代表设置会话级而非事务级参数,问题不在这个参数的使用上。
解决方案
优先使用asyncpg官方原生支持的方案,不需要自定义init回调:
直接在create_pool时传入server_settings参数,把所有需要全局设置的会话参数放在这个字典里即可。asyncpg会在连接初始化的最早期应用这些配置,这些配置会被标记为连接的初始状态,后续重置连接时不会被清空;同时asyncpg会自动处理参数转义,避免SQL注入风险,配置也会一次性下发,性能比循环单条执行set_config更好。
修改后的代码示例:
db_pool = await asyncpg.create_pool( database=os.getenv("POSTGRES_DBNAME" if not is_test_db else "POSTGRES_DBNAME_TEST"), user=os.getenv("POSTGRES_USER"), password=os.getenv("POSTGRES_PASSWORD"), host=host, server_settings={ "element_type.boolean": str(ElementsTypes.Boolean.value), "entity_types.element": str(EntityTypes.Elements.value), # 其余自定义配置按相同格式追加即可 }, loop=loop )
注意:server_settings字典里的所有值必须是字符串类型,符合PostgreSQL配置参数的格式要求。
不建议通过关闭连接池reset配置的方式绕过问题,关闭状态重置会导致严重的连接状态污染问题,极易出现难以排查的业务异常。
内容的提问来源于stack exchange,提问作者Prosto_Oleg
相关产品推荐
相关产品推荐

