OceanBase 4.3.3 开启 VSAG 向量索引后 MyBatis 批量插入频繁超时的避坑指南
具体场景是使用 Spring Boot 配合 MyBatis-Plus 的 saveBatch 方法进行数据刷入,每批次设置 200 条记录。在没有索引的情况下,5 万条数据几秒钟就能跑完,毫无压力。但一旦挂载 VSAG 索引,系统就开始频繁抛出 JDBC SQLState: XA102, Error Code: 4012 - Transaction timeout or statement timeout exceeded。这个报错非常具有欺骗性,因为它看起来像是网络波动或数据库负载过高导致的超时,但实际上深层原因是索引维护机制在拖后腿。
为了定位问题,我尝试了最直接的方案——在 Session 级别强行拉长超时时间。我将 ob_query_timeout 和 ob_trx_timeout 全部调到了 120 秒以上,试图给数据库更多的时间去处理单次写入。结果证明这只是治标不治本,虽然报错频率降低了,但依然无法根治,依然会触发超时崩溃。这说明问题不在于简单的“时间不够”,而在于 VSAG 索引在同步维护时的资源占用和锁竞争。
从技术原理上分析,VSAG 是一种基于图的向量索引。这种索引的特点是在查询时速度极快,但在写入时,为了维护图结构的连通性和准确性,每次插入新向量都需要进行复杂的邻居搜索和指针更新。在批量插入场景下,这种同步维护的开销会被成倍放大。每批次写入时,索引构建过程可能会长时间占用事务锁,导致后续的批次在等待队列中积压,最终在达到阈值后集体崩盘。
目前最让我纠结的是,在这种高吞吐的向量导入实战场景中,同步维护索引显然是一个性能瓶颈。我一直在思考 OceanBase 是否支持将 VSAG 索引的维护改为异步模式,或者提供某种类似“延迟构建”的机制。如果能实现先将数据快速入库,再由后台进程异步构建索引,那么这种迁移场景才真正具备可操作性。
针对目前 4.3.3 版本的实战经验,如果大家也遇到了 vector_data 这种高维字段写入缓慢的问题,建议不要盲目增加超时时间,而应尝试从写入策略上下手。例如,在海量数据迁移阶段,先删除 VSAG 索引,待数据全部刷入完成后,再通过 CREATE INDEX 统一构建。这种“先入库、后建索引”的模式,比在写入过程中实时维护索引的效率要高出好几个数量级。
总结这次踩坑,高维向量索引的写入成本远超普通 B+ 树索引。在处理 1536 维这种量级的数据时,必须意识到同步索引维护对事务性能的巨大冲击,尤其是在使用 MyBatis 批量操作时,要警惕 Error Code: 4012 背后隐藏的索引构建开销。