企业把 Agent 接入生产数据库时,真正棘手的通常不是 SQL 能不能执行,而是 Agent 会执行多少次 SQL。一次任务可能包含检索、验证、反思和重试等多轮推理;当大量 Agent 同时运行,这些不可预测的查询突发很容易拖慢订单、库存和支付等核心业务。
目前处于预览阶段的 AlloyDB PostgreSQL for agents,试图通过独立、按需启动的数据库实例解决这一矛盾:Agent 可以读取接近实时的生产数据,但其计算资源与主实例、备用实例和常规只读副本隔离,任务结束后还可以缩容到零。
关键变化不是“更多只读副本”,而是分离计算负载
传统做法通常是给 Agent 分配一个只读副本。这能降低主库压力,却仍有几个问题:
- Agent 流量具有突发性,为峰值长期保留副本会造成闲置成本。
- 多个 Agent 共享同一个副本时,复杂扫描、向量检索和普通点查仍会互相争抢 CPU、内存与缓存。
- 如果缓存层位于数据库和对象存储之间,它本身可能成为新的吞吐瓶颈。
- 扩容速度跟不上密集推理循环时,生产系统仍可能受到间接影响。
AlloyDB 公布的 agentic database architecture 采用共享存储、隔离计算的思路。新启动的沙箱数据库实例从统一的 Colossus 存储层读取新鲜数据,不需要与生产主实例、备用实例或传统只读副本共享数据库计算资源。
这类实例运行完整的 AlloyDB PostgreSQL 引擎,因此 Agent 不只能够执行简单的键值查询,还可以使用 SQL、B-tree 索引、向量检索、全文搜索和空间查询。官方披露的架构目标包括亚毫秒级 I/O、超过 Tbps 的聚合扫描吞吐,以及每秒超过 300 万次查询;这些数字应理解为平台级能力描述,实际工作负载仍需结合区域、查询模型、并发度和预览配额进行压测。
为什么工作负载隔离比单纯扩容更重要
Agent 对数据库的访问模式与传统 Web 请求明显不同。一条用户请求可能触发几十次甚至更多数据库操作,其中还夹杂着模型重试和工具调用。平均 QPS 看起来不高,不代表瞬时并发安全。
隔离式实例带来的核心收益有三点:
- 故障域隔离:Agent 的大范围扫描或低选择性向量查询不会直接消耗生产实例的计算资源。
- 弹性匹配推理周期:查询突发时启动实例,任务完成后缩容到零,更适合间歇性的 Agent 任务。
- 保留 PostgreSQL 能力:不必为了隔离而把数据导出到功能受限的专用检索系统,已有索引和 SQL 查询逻辑仍可复用。
但“隔离”不等于“没有风险”。Agent 仍可能读取超出任务范围的数据、生成昂贵 SQL,或者把敏感字段带入模型上下文。数据库实例隔离解决的是资源竞争问题,权限、数据最小化和查询预算仍需要应用团队负责。
可以这样实践:给 Agent 增加只读和并发护栏
下面是一个可改造的 Python 示例。它假设你已经按照预览版文档获得一个 Agent 专用 PostgreSQL 连接端点,并存在 inventory 表。运行前需要把 DATABASE_URL 换成实际连接信息,并根据自己的表结构修改查询字段。
安装依赖:
python -m pip install 'psycopg[binary,pool]>=3.2,<4'
export DATABASE_URL='postgresql://USER:PASSWORD@HOST:5432/DATABASE?sslmode=require'
保存为 agent_query.py:
import os
from concurrent.futures import ThreadPoolExecutor, as_completed
from psycopg.rows import dict_row
from psycopg_pool import ConnectionPool
DATABASE_URL = os.environ["DATABASE_URL"]
QUERY = """
SELECT sku, warehouse_id, available_quantity, updated_at
FROM inventory
WHERE sku = %s
ORDER BY updated_at DESC
LIMIT 20
"""
def lookup_inventory(pool: ConnectionPool, sku: str) -> list[dict]:
with pool.connection() as conn:
# 即使连接端点已经只读,也在事务级别增加一道防线。
conn.execute("SET TRANSACTION READ ONLY")
conn.execute("SET LOCAL statement_timeout = '1500ms'")
with conn.cursor(row_factory=dict_row) as cur:
cur.execute(QUERY, (sku,))
return [dict(row) for row in cur.fetchall()]
def main() -> None:
skus = ["SKU-1001", "SKU-1002", "SKU-1003", "SKU-1004"]
# 不要把数据库的弹性能力理解为无限并发许可。
# 应用侧仍应设置连接池和任务并发上限。
with ConnectionPool(
conninfo=DATABASE_URL,
min_size=0,
max_size=8,
kwargs={"application_name": "inventory-agent"},
) as pool:
with ThreadPoolExecutor(max_workers=4) as executor:
futures = {
executor.submit(lookup_inventory, pool, sku): sku
for sku in skus
}
for future in as_completed(futures):
sku = futures[future]
try:
print(sku, future.result())
except Exception as exc:
print(sku, {"error": str(exc)})
if __name__ == "__main__":
main()
这个示例刻意保留了三道护栏:连接池限制数据库连接数,线程池限制 Agent 工具调用并发,statement_timeout 限制单条查询占用资源的时间。生产环境还应增加全局速率限制、查询审计、重试退避和任务级查询预算,避免多个 Agent 在失败时同步重试。
如果组织采用 IAM 身份认证,应优先使用短期凭证而不是静态密码。AlloyDB 还提供与 IAM、VPC Service Controls、客户管理的加密密钥和审计能力的集成,但具体配置方式、可用区域及预览限制需要根据当前产品文档确认。
实时数据与湖仓数据可以分工,而不是互相替代
Agent 经常同时需要两类上下文:当前订单状态、库存余量等实时事务数据,以及数月历史销量、物流趋势等分析数据。把所有历史数据塞回事务库并不经济,把生产数据定期复制到分析系统又会引入延迟和 ETL 维护成本。
此次架构强调与 BigQuery 和 Apache Spark 的湖仓分析集成,使 Agent 可以把 AlloyDB 中接近实时的事务状态与历史湖仓数据结合起来。设计工作流时,可以采用清晰的职责划分:
- AlloyDB 负责当前状态、精确点查、索引检索和实时约束。
- BigQuery 或 Spark 负责大规模历史扫描、聚合与特征计算。
- Agent 编排层决定查询顺序、限制返回行数,并把结果压缩成模型真正需要的上下文。
“无需复杂 ETL”不意味着不需要治理。跨系统查询仍要控制数据扫描量、身份边界、字段脱敏和结果缓存策略。
上线前应验证的清单
由于 PostgreSQL for agents 目前仍处于预览阶段,适合先从可回退、只读且容易度量的场景开始,例如库存解释、订单状态分析、客服检索或供应链异常调查。正式采用前建议检查:
- Agent 实例是否在目标区域可用,启动时间和并发配额是否满足峰值需求。
- 生产实例的延迟和吞吐是否在 Agent 压测期间保持稳定。
- 每个 Agent、租户和任务是否拥有独立的查询预算与权限边界。
- 是否设置连接池、超时、最大返回行数、取消机制和指数退避。
- 向量、全文和空间索引是否与真实查询计划匹配,而不是只验证功能可用。
- 缩容到零后的冷启动延迟与按需计费是否符合业务目标。
- BigQuery、Spark 与事务数据的联合访问是否满足审计和数据驻留要求。
这套架构最值得关注的地方,不是让 Agent 获得一个“更快的数据库”,而是让实时数据访问、生产稳定性和按需成本不再必须三选一。不过,隔离计算只能提供基础设施护栏;权限最小化、查询治理和成本预算仍是把 Agent 安全带入生产环境的必要条件。