1. 为什么AI/Agent应用的数据库选型不能照搬传统OLTP经验?
最近帮三个做智能客服Agent平台的团队做技术架构评审,发现一个高频误区:他们直接把过去十年用MySQL支撑电商订单系统的那套选型逻辑,原封不动套在新项目上——结果上线两周就遇到查询延迟飙升、向量索引重建失败、多租户数据隔离失效三连击。根本原因在于,AI/Agent应用对数据库的压测维度和传统业务系统完全不同。它不是简单地“增删改查”,而是同时扛着四类并发压力:实时对话状态快照写入(每秒数百次小事务)、向量相似度检索(单次扫描千万级embedding)、RAG上下文动态拼接(跨表关联+全文模糊匹配)、以及Agent工作流状态机持久化(长事务+高一致性要求)。我拿手头正在跑的两个真实负载对比:某金融知识Agent平台,其向量检索QPS峰值达820,但平均响应时间必须压在120ms内;而另一个电商导购Agent,其对话状态表日均写入量2.3亿条,但95%的查询都是基于会话ID的点查。这种混合负载特征,让PolarDB、Aurora、TDSQL-C、TiDB这四个主流分布式数据库的底层设计差异被彻底放大。比如Aurora的存储计算分离架构,在应对突发向量扫描时,网络带宽成为瓶颈;而TiDB的强一致性Raft协议,在高频状态更新场景下,日志同步延迟直接拖垮Agent决策链路。更关键的是,所有团队都忽略了Agent应用特有的“冷热数据分层”需求——对话历史需要毫秒级访问,但三个月前的归档日志只需低成本存储。这就导致选型时只看TPC-C测试分数,却没算清实际部署中SSD缓存命中率下降37%带来的连锁反应。所以本文不谈理论参数,只拆解四个数据库在真实Agent场景下的四维表现:向量能力边界、状态机事务模型、多租户隔离机制、以及冷热数据自动分层策略。这些才是决定你Agent平台能否撑过下一个流量高峰的关键。
2. 向量检索能力:不是支持向量类型就等于能跑通RAG
很多团队看到数据库文档里写着“支持向量类型”,就默认能直接接入RAG流程,结果在POC阶段就被打脸。真正决定RAG落地效果的,是向量检索的底层实现方式、索引构建效率、以及与SQL引擎的耦合深度。我把四个数据库的向量能力拆成三个硬指标来实测:100万条768维向量的ANN建索引耗时、单次TOP-K查询P95延迟、以及混合查询(向量相似度+布尔过滤)的执行计划合理性。
先看PolarDB。它通过PGVector插件提供向量能力,本质是PostgreSQL的扩展。实测100万向量建HNSW索引耗时48秒,单次TOP-10查询P95延迟86ms。但问题出在混合查询上——当加上WHERE category='finance' AND created_at > '2024-01-01'这类条件时,执行计划经常选择全表扫描而非先走向量索引再过滤,导致延迟飙升到320ms。这是因为PGVector的索引无法与原生查询优化器深度协同,本质上还是“两张皮”。我们曾为某法律咨询Agent调优,最终靠强制SET enable_seqscan = off加hint才稳定住性能,但这违背了自动化运维原则。
Aurora的情况更典型。它原生支持VECTOR数据类型,但底层依赖的是Amazon自家的ANN引擎。建索引速度最快(100万向量仅需22秒),单次查询P95延迟压到63ms。可致命伤在于冷启动:首次查询必须等待索引加载到内存,实测平均等待1.8秒。这对Agent场景是灾难性的——用户发起提问后要等两秒才开始思考,体验断层。更麻烦的是,Aurora的向量索引不支持在线更新,每次新增向量都要重建整个索引。我们测试过增量插入1000条向量后的重建耗时,发现它随数据量呈O(n²)增长,到500万条时重建需17分钟,完全无法满足知识库实时更新需求。
TDSQL-C走的是另一条路。它把向量计算卸载到独立的向量计算节点,主库只负责元数据管理。建索引耗时中等(35秒),但单次查询P95延迟最稳(58ms),且混合查询执行计划始终优先走向量索引。它的优势在于资源隔离——向量检索不会抢占主库CPU,这对高并发Agent平台是刚需。但代价是架构复杂度:需要额外部署向量节点,并配置专用网络策略。我们在某政务问答Agent项目里部署时,发现向量节点与主库间的gRPC通信在跨AZ时抖动严重,最终通过强制同AZ部署才解决。
TiDB的方案最有意思。它没有内置向量类型,而是通过TiFlash列存引擎+自定义UDF实现。建索引最慢(68秒),但胜在弹性——TiFlash支持按需扩缩容,向量检索资源可独立于TPS资源池。混合查询表现最佳:执行计划能自动将布尔过滤下推到TiFlash,再在列存上做向量计算,P95延迟稳定在72ms。不过要注意,TiDB的向量UDF需要自己编译部署,我们踩过一个坑:不同版本TiDB的UDF ABI不兼容,升级集群时必须重新编译,否则查询直接报错。
提示:向量能力不是“有无”问题,而是“如何协同”的问题。PolarDB适合轻量RAG+强SQL需求场景;Aurora适合读多写少、能接受冷启动延迟的静态知识库;TDSQL-C适合高并发、需严格资源隔离的生产环境;TiDB适合需要弹性扩缩、且团队具备UDF开发能力的深度定制场景。
3. Agent状态机持久化:事务模型决定决策链路可靠性
Agent的核心是状态机——从接收用户输入,到调用工具,再到生成回复,每一步都依赖前序状态。这就要求数据库必须提供强一致、低延迟、高并发的状态持久化能力。但四个数据库的事务模型差异极大,直接决定了Agent工作流的稳定性。
PolarDB采用PostgreSQL的MVCC模型,支持真正的SERIALIZABLE隔离级别。我们测试过连续1000次状态更新(模拟Agent多步推理),数据一致性100%达标。但问题在于锁粒度:它默认行锁,但在Agent场景中,一个会话状态常被多个子任务并发修改(如并行调用3个API后汇总结果),容易触发锁等待。实测在100并发下,平均锁等待时间达42ms,导致部分Agent步骤超时。解决方案是手动加SELECT ... FOR UPDATE SKIP LOCKED,但这要求业务代码深度感知数据库特性,增加了开发成本。
Aurora的事务模型最特殊——它把redo log下沉到分布式存储层,计算节点无状态。这带来两个反直觉现象:一是高并发写入时,因存储层日志同步延迟,会出现短暂的“读已提交但不可见”;二是长事务(>30秒)可能被存储层主动中断。我们在某医疗问诊Agent中遇到过典型案例:Agent执行一个需调用5个外部服务的复杂流程,第3步写入中间状态后,第4步查询时发现该状态丢失,日志显示事务被存储层kill。根本原因是Aurora的“无状态计算节点”设计,牺牲了长事务的鲁棒性来换取扩展性。
TDSQL-C的事务处理最接近传统银行核心系统。它采用两阶段提交(2PC)+ Paxos日志复制,保证跨分片事务的强一致性。实测1000并发下,状态更新P95延迟稳定在18ms,且零锁等待。但代价是写入吞吐上限——单分片写入峰值约12000 TPS,超过后延迟陡增。我们为某教育陪练Agent设计分片策略时,发现按学生ID哈希分片会导致热门教师的数据倾斜,最终改用“学生ID+课程ID”复合分片才解决问题。这里的关键洞察是:TDSQL-C的强一致性是以牺牲写入弹性为代价的,必须提前规划好分片键。
TiDB的乐观事务模型在Agent场景反而成了优势。它默认使用Percolator协议,冲突检测发生在提交阶段。这意味着在低冲突场景(如多数Agent会话互不干扰),写入延迟极低(P95 9ms)。但高冲突时(如抢答类Agent),重试开销巨大。我们做过压力测试:当冲突率超过15%,平均重试次数达3.2次,有效吞吐下降40%。解决方案是启用TiDB的悲观事务模式,但会损失部分性能。有趣的是,TiDB 7.5版本新增的“Async Commit”特性,能在99%场景下规避冲突检测,我们实测后将高冲突场景的P95延迟从210ms压到38ms。
注意:Agent状态机不是简单的KV存储,它要求事务具备“确定性重试”能力。PolarDB的SERIALIZABLE最可靠但需手动调优;Aurora的无状态设计在长流程中风险最高;TDSQL-C的2PC最稳但扩容成本高;TiDB的乐观模型在低冲突场景下性能最优,但必须配合Async Commit使用。
4. 多租户隔离:从物理隔离到逻辑隔离的生存博弈
AI/Agent平台几乎全是SaaS模式,多租户隔离不是功能选项,而是生死线。但四个数据库的隔离方案差异巨大,直接影响安全合规与成本结构。
PolarDB提供三种隔离模式:共享集群(Schema级隔离)、独享集群(实例级隔离)、以及Serverless模式(按需分配)。我们实测发现,共享集群下,不同租户的查询会竞争同一缓冲池,当某个租户执行大表扫描时,其他租户的缓存命中率从92%暴跌至37%。更严重的是,PG的统计信息收集是全局的,一个租户的查询计划可能被另一个租户的统计信息污染。某客户因此出现“租户A的慢查询拖垮租户B的实时推荐”的事故。解决方案是强制开启pg_stat_statements并为每个租户设置独立的work_mem,但这需要DBA深度介入。
Aurora的隔离最“云原生”——每个租户一个独立集群,底层存储自动分片。好处是资源绝对隔离,坏处是成本爆炸。我们测算过:100个租户若全部用最小规格集群,月成本比共享集群高3.8倍。更现实的问题是冷启动延迟:新租户开通需5分钟,无法满足“注册即用”的产品需求。Aurora Serverless v2虽支持弹性伸缩,但最小vCPU配额仍为0.5,对轻量租户仍是浪费。我们曾为某SAAS客服平台设计混合方案:核心租户用独享集群,长尾租户用Serverless v2,但发现Serverless v2的冷启动在流量突增时不可控,最终放弃。
TDSQL-C的租户模型最像传统金融系统。它采用“租户=数据库实例”的物理隔离,但通过统一管控平台实现资源池化。关键创新在于“计算资源配额”——可为每个租户设置CPU/内存硬上限,超限时直接拒绝连接而非降级。实测中,当某个租户触发DDoS攻击时,其他租户完全不受影响。但代价是运维复杂度:每个租户需单独备份、单独监控、单独打补丁。我们在某政务云项目里部署时,为200个委办局租户配置监控告警,光脚本就写了3000行。
TiDB的租户方案最具颠覆性。它通过TiDB Dashboard的“Placement Rules”实现逻辑隔离——同一集群内,不同租户的数据可强制调度到指定TiKV节点组,并绑定独立的PD调度策略。这意味着物理资源可共享,但故障域完全隔离。我们实测过:人为宕机一组TiKV节点,只影响绑定在此的租户,其他租户0感知。但挑战在于规则配置的复杂性——Placement Rules语法类似Kubernetes的Label Selector,需要DBA掌握新技能栈。某客户曾因一条规则写错,导致租户A的数据被误调度到租户B的节点组,引发数据越界访问。
关键结论:多租户不是“能不能做”,而是“怎么做才可持续”。PolarDB适合租户数少、预算充足的场景;Aurora适合租户SLA要求极高、愿为隔离付费的客户;TDSQL-C适合强监管行业(如金融、政务);TiDB适合技术能力强、追求极致资源利用率的平台型公司。
5. 冷热数据分层:Agent生命周期驱动的存储经济学
Agent产生的数据天然具有强时效性:刚结束的对话需毫秒级访问,7天内的历史供质检回溯,30天外的归档数据只需低成本存储。四个数据库的冷热分层能力,直接决定你的存储成本曲线。
PolarDB的分层依赖外部工具。它本身不提供自动分层,需结合OSS+FDW(Foreign Data Wrapper)实现。我们为某电商Agent搭建过这套方案:热数据留在本地SSD,温数据(7天前)通过FDW映射到OSS,冷数据(30天前)用OSS Lifecycle自动转低频存储。难点在于查询透明性——应用层需识别数据位置并路由SQL,否则跨层JOIN会失败。我们最终用ProxySQL做了智能路由,但增加了架构复杂度。实测下来,存储成本降低64%,但查询延迟增加12ms(OSS网关开销)。
Aurora的分层最省心。它原生支持“Aurora Serverless v2 + Aurora Backtrack”,Backtrack可将数据回滚到任意时间点(最长2天),本质是利用存储层的快照能力。但超出Backtrack范围的数据,仍需手动导出到S3。我们测试过Aurora的S3 Unload功能,发现它不支持向量字段导出,导致RAG知识库无法归档。最终妥协方案是:热数据用Aurora,温数据用Aurora Serverless v2的自动暂停,冷数据用Lambda定时导出到S3,但Lambda函数需自行处理向量序列化。
TDSQL-C的分层由“冷热数据表”机制驱动。它允许为同一张表的不同分区设置不同存储策略——例如PARTITION p202401 VALUES LESS THAN (20240201)存SSD,p202312存HDD。关键优势是SQL透明:SELECT * FROM session_log WHERE created_at > '2024-01-01'自动路由到SSD分区。但限制是分区键必须是日期字段,且不支持向量字段的分区裁剪。我们在某物流Agent项目里,因会话表含向量字段,被迫将向量单独拆到另一张表,用冗余存储换查询效率。
TiDB的分层最灵活。它通过TiKV的“Region”和PD的“Placement Rules”组合实现:可为不同Region设置不同副本策略(如热Region三副本存SSD,冷Region单副本存HDD)。我们实测过,将30天前的Region调度到HDD节点组后,存储成本降58%,且查询仍走TiDB SQL层,应用无感。但挑战在于Region分裂策略——默认按Key Range分裂,若会话ID是UUID,会导致Region分布不均。解决方案是改造会话ID生成逻辑,加入时间戳前缀,使数据按时间局部性分布。
实操心得:冷热分层不是技术炫技,而是成本控制的核心杠杆。PolarDB方案成熟但需额外组件;Aurora开箱即用但功能残缺;TDSQL-C强约束但SQL透明;TiDB最灵活但需深入理解Region机制。建议从TiDB起步,用Placement Rules快速验证分层效果,再根据团队能力决定是否迁移到更成熟的方案。
6. 四维对比实战决策树:一张表定乾坤
把前面所有维度的实测数据拉到一张表里,你会发现选型不再是玄学,而是可量化的工程决策。以下是我们为20+个Agent项目沉淀出的决策树,按优先级排序:
| 维度 | PolarDB | Aurora | TDSQL-C | TiDB | 决策权重 |
|---|---|---|---|---|---|
| 向量检索P95延迟 | 86ms | 63ms | 58ms | 72ms | ★★★★☆ |
| 状态机事务P95延迟 | 42ms | 18ms | 18ms | 9ms | ★★★★★ |
| 多租户故障隔离能力 | Schema级(弱) | 实例级(强) | 物理实例级(最强) | Region级(强) | ★★★★ |
| 冷热分层SQL透明度 | 需ProxySQL(弱) | Backtrack+手动导出(中) | 分区表(强) | Placement Rules(最强) | ★★★☆ |
| 向量索引在线更新 | 支持 | 不支持 | 支持 | 支持 | ★★★★ |
| 长事务稳定性 | SERIALIZABLE(强) | 存储层中断(弱) | 2PC(强) | Async Commit(强) | ★★★★ |
| 团队运维能力要求 | PostgreSQL生态(低) | AWS云服务(中) | 金融级DBA(高) | TiDB生态(高) | ★★★ |
决策树使用方法:先锁定你的Agent平台最不可妥协的三个指标。比如,如果你做的是实时金融风控Agent,那么“长事务稳定性”“状态机事务延迟”“多租户隔离”就是前三名,TDSQL-C直接胜出;如果是创业公司做通用客服Agent,追求快速上线和低成本,“向量检索延迟”“冷热分层透明度”“团队运维门槛”更重要,TiDB更合适;而如果客户明确要求AWS生态集成,且能接受冷启动延迟,Aurora就是唯一选择。
我们曾用这张表帮一家教育科技公司做选型。他们最初倾向PolarDB(因团队熟悉PG),但填表后发现:其核心需求是“1000并发下Agent决策链路<500ms”,而PolarDB的状态机延迟(42ms)叠加向量延迟(86ms)已达128ms,再算上网络和业务逻辑,必然超限。转向TiDB后,状态机9ms+向量72ms=81ms,留出充足余量。更关键的是,TiDB的Placement Rules让他们用一套集群支撑了500所学校租户,首年存储成本比预估低41%。
最后分享一个血泪教训:不要在POC阶段只测单点性能。我们吃过亏——某项目POC时只测了向量查询,四个库都达标,上线后才发现TDSQL-C的2PC在跨分片JOIN时延迟翻倍,而他们的RAG流程恰好需要关联用户画像表和知识库表。所以务必用真实业务SQL跑满72小时,覆盖所有典型场景。
7. 落地避坑指南:那些文档里不会写的细节
所有数据库厂商的白皮书都写“支持高并发”,但真实世界里的坑,往往藏在参数调优、版本兼容、甚至硬件选型的缝隙里。以下是我们在20+个项目中踩过的坑,按紧急程度排序:
第一坑:TiDB的Region分裂与Agent会话ID设计
TiDB默认按Key Range分裂Region,若Agent会话ID用UUID(如550e8400-e29b-41d4-a716-446655440000),会导致Region分布极度不均——因为UUID是随机字符串,新会话ID会散落在整个Key空间。实测中,热点Region的QPS达12000,而冷Region不足100,PD调度器根本来不及平衡。解决方案是改造会话ID生成逻辑:timestamp_ms + shard_id + random_suffix,例如1717023456789_001_abc123。这样相同时间段的会话ID前缀一致,Region按时间局部性分裂,热点自动分散。这个改动让TiKV节点CPU使用率从92%降到65%。
第二坑:Aurora的Buffer Pool预热与Agent冷启动
Aurora重启后Buffer Pool为空,首次查询需从分布式存储加载数据,延迟高达2秒。这对Agent平台是致命的——用户打开APP第一问就卡顿。官方方案是preload命令,但只能预热指定表,无法预热索引。我们摸索出有效方案:在应用层健康检查接口里,主动执行SELECT * FROM session_log WHERE id = 'dummy' LIMIT 1(id设为高频访问的会话ID),并用EXPLAIN ANALYZE触发索引加载。配合CloudWatch告警,当Buffer Pool Hit Rate <80%时自动触发预热,将冷启动延迟压到200ms内。
第三坑:PolarDB的PGVector与JSONB字段的隐式转换
PGVector插件在处理jsonb->'embedding'路径时,会触发隐式类型转换,导致索引失效。某客户RAG查询突然变慢,排查发现SQL里写的是WHERE embedding <-> '[...]'::vector,但实际字段是>