Vitess v18.0.3 破坏性变更解析:ExecuteFetchAsDBA 正式拒绝多语句 SQL

发布时间:2026/9/20 22:28:24
Vitess v18.0.3 破坏性变更解析:ExecuteFetchAsDBA 正式拒绝多语句 SQL 数据库分布式数据库云原生后端数据存储【免费下载链接】vitessVitess is a database clustering system for horizontal scaling of MySQL.项目地址https://gitcode.com/gh_mirrors/vi/vitess点击查看免费下载导读Vitess v18.0.3 发布了一个影响运维与自动化脚本的破坏性变更ExecuteFetchAsDBA包括vtctldclient、vtctl、vtctlclient三条命令行入口不再静默接受多语句multi-statementSQL而是直接报错拒绝执行。本文以官方发布说明为主体结合仓库源码rpc_query.go、grpcvtctldserver/server.go、wrangler/tablet.go剖析该变更的动机、例外规则与迁移路径帮助你在升级到 v18.0.3 前排查受影响脚本并掌握新版本推荐的ExecuteMultiFetchAsDBA用法。背景ExecuteFetchAsDBA 是做什么的ExecuteFetchAsDBA是 Vitess 中一个绕过查询引擎直连底层 MySQL的运维通道。它通过 vttablet 的DBA 连接池在指定 tablet 上直接执行 SQL常用于手工修复复制状态stop replica/start replica执行无法被正常查询路由处理的 DDL 或管理命令初始化 schema配合ApplySchema --batch-size。从仓库源码可以完整看到它的调用链vtctl 命令层go/vt/vtctl/vtctl.go 中commandExecuteFetchAsDba解析--max-rows、--disable-binlogs、--reload-schema等参数后调用wr.ExecuteFetchAsDbaWrangler 层go/vt/wrangler/tablet.go 将请求封装为vtctldatapb.ExecuteFetchAsDBARequest转交 vtctld 服务端vtctld gRPC 服务层go/vt/vtctl/grpcvtctldserver/server.go 通过s.tmc.ExecuteFetchAsDba将请求转发给目标 tablet 的 tabletmanagertabletmanager 执行层go/vt/vttablet/tabletmanager/rpc_query.go 真正执行 SQL 并返回querypb.QueryResult。v18.0.3 的变更正是落在最后这一层对传入的 SQL 先做语句拆分与解析校验再决定是否放行。破坏性变更多语句 SQL 被直接拒绝按照 release_notes.md 的定义自 v18.0.3 起vtctldclient ExecuteFetchAsDBA以及同义的vtctl/vtctlclient命令在收到包含多条语句的 SQL 时直接返回错误且不会尝试执行其中任何一条语句。官方示例中下面的命令会直接报错三条语句停复制、改复制源、启动复制一条都不会被执行vtctldclient ExecuteFetchAsDBA my-tablet \ stop replica; change replication source to auto_position1; start replica注意;分隔多语句属于典型的多语句 SQL过去会被静默接受如今被拒绝。如果你在升级前有类似脚本需要在升级到 v18.0.3 前改造。为什么拒绝旧行为的三个隐患在 v18.0.3 之前ExecuteFetchAsDBA会静默接受多语句 SQL 并尝试逐条执行但这带来三个严重问题1. 只有第一条语句的错误会被上报执行过程中第 2、3 及后续语句的错误会被静默吞掉。假设 5 条语句中第 4 条失败调用方只能看到前 3 条成功的结果失败被完全掩盖极易造成命令执行成功的假象。2. 连接池被脏连接污染后续语句的结果集没有被消费ExecuteFetchAsDBA会把用过的连接以脏状态归还连接池。之后任何从池中取出该连接的查询都可能拿到残留的未读结果集、会话状态或锁导致完全不可预期的错误。这属于典型的资源泄漏型 Bug排查成本极高。3. schema 缓存与底层数据库不一致对于多语句 schema 变更vttablet 只会基于第一条变更重载 schema 缓存导致缓存中的表结构与底层数据库实际结构不一致后续查询可能因此路由错误或解析失败。这三个隐患的修复思路在 v18.0.3 中落地为一条硬性规则拒绝多语句杜绝脏状态进入连接池。唯一的例外连续 CREATE TABLE / CREATE VIEWExecuteFetchAsDBA仍然允许一种特殊形态的多语句 SQL所有语句均为CREATE TABLE或CREATE VIEW的语句序列。保留这个例外是为了支持一种非常常见的 schema 初始化模式——ApplySchema --batch-size。ApplySchema在底层正是通过ExecuteFetchAsDBA把一个大 schema 文件按--batch-size拆分成多个批次下发执行的若某个批次只有 1 条CREATE TABLE走普通单语句路径若某个批次包含连续的建表/建视图语句则走仅 CREATE 类语句的豁免路径。源码中的依据位于 go/vt/vttablet/tabletmanager/rpc_query.goanalyzeExecuteFetchAsDbaMultiQuery负责把 SQL 拆分为单条语句并逐一解析返回值countCreate统计解析出的CREATE TABLE/CREATE VIEW语句数量注释明确说明countCreate 也包含 CREATE VIEW内部会忽略非表语句且无法解析但形态上像持久化 CREATE TABLE/VIEW 的语句按最坏情况处理。也就是说校验逻辑不是简单数;的个数而是先解析、再分类只有全部由 CREATE 类语句组成的多语句序列才被放行任何混入INSERT、UPDATE、STOP REPLICA等语句的多语句 SQL 都会在 v18.0.3 被拒绝。源码视角校验到底发生在哪一层把仓库源码翻出来可以看到这套拒绝机制的实际落点与演进痕迹v18.0.3 的校验逻辑在 v18.0.3 中rpc_query.go 的ExecuteFetchAsDba调用了内部方法executeMultiFetchAsDba并传入一个校验回调func(queries []string, countCreate int) error { if len(queries) 1 { return vterrors.Errorf(vtrpc.Code_INVALID_ARGUMENT, multi statement queries are not supported in ExecuteFetchAsDba) } return nil }回调拿到拆分后的语句列表queries与 CREATE 语句计数countCreatelen(queries) 1且不是 CREATE 豁免场景 → 返回INVALID_ARGUMENT错误一条都不执行单语句或纯 CREATE 序列 → 正常执行。调用链上的逐层转发vtctld gRPC 服务端grpcvtctldserver/server.go将请求中的Query、MaxRows、DisableBinlogs、ReloadSchema逐字段透传给 tabletmanager RPC同时用 trace span 记录tablet_alias、max_rows等属性便于分布式追踪Wrangler 层wrangler/tablet.go注意这里同时暴露了ExecuteFetchAsDba与ExecuteMultiFetchAsDba两个方法——后者接收sql注意参数名是sql而非query并返回多个QueryResult正是 v18.0.3 提供的多语句替代通道。一个明显的版本演进痕迹当前仓库源码的注释rpc_query.go还透露出一个后续演进As of v23 we do not allow multi-statement SQL in ExecuteFetchAsDba at all, and ExecuteMultiFetchAsDba will be the only way to execute multiple statements.也就是说在更晚的版本v23 及以后中连纯 CREATE TABLE/VIEW 序列这个例外也被移除了ExecuteFetchAsDba将完全只接受单条语句多语句统一走ExecuteMultiFetchAsDba。如果你现在就在规划长期升级路径建议直接按v18.0.3 已收紧、v23 全面禁止的演进方向改造脚本。升级迁移建议改用 ExecuteMultiFetchAsDba对于确实需要批量执行多条语句的运维场景v18.0.3 提供了专门的替代命令ExecuteMultiFetchAsDba。从源码看rpc_query.go它同样支持DisableBinlogs、ReloadSchema、DisableForeignKeyChecks与自定义SessionVariables并返回按顺序排列的多个QueryResult且不会把脏连接归还池中——这正是旧ExecuteFetchAsDba多语句行为缺失的三项保证。迁移时建议按下表对照调整场景v18.0.2 及以前v18.0.3 及以后单条管理语句如FLUSH TABLESExecuteFetchAsDbaExecuteFetchAsDba不变复制维护stop replica/start replica可塞进一条多语句逐条调用ExecuteFetchAsDba或改用ExecuteMultiFetchAsDba批量 DDL / 初始化脚本多语句直接传用ExecuteMultiFetchAsDba或交给ApplySchema --batch-size纯 CREATE TABLE / CREATE VIEW 序列多语句直接传ExecuteFetchAsDbav18.0.3 仍豁免v23 需迁移同时请检查两类脚本线上自动化脚本凡是用分号拼接多条 SQL 再传给vtctl/vtctldclient ExecuteFetchAsDba的必须拆分或改命令自定义工具链如果自己封装了 RPC 直接调用 tabletmanager 的ExecuteFetchAsDba同样受该变更约束。本次发布的整体情况v18.0.3 共合入47 个 Pull Request除本次ExecuteFetchAsDBA破坏性变更外其余均为 Bug 修复、CI/构建与依赖升级例如详见 changelog.mdEvalengine修复week溢出#14861、current date/time返回值类型#15084Query Serving修复列别名展开#14955、GROUP BY/HAVING别名解析#15381、流式调用 Go routine 泄漏#15300等VReplication/Online DDL枚举值重排修复#15351Schema Tracker修复 nil server vschema 导致的崩溃#15092构建Go 版本升级至go1.21.8#15407。与本变更直接相关的两个 PR 是#14984ProtectExecuteFetchAsDBAagainst multi-statements, excluding a sequence ofCREATE TABLE|VIEW即保护逻辑与例外规则的实现和#1501318.0.3 release notes: ExecuteFetchAsDBA breaking change即本文所依据的发布说明文档。小结与建议v18.0.3 对ExecuteFetchAsDBA的收紧是一次典型的安全优先破坏性变更以牺牲多语句便利性为代价换取了错误可见性、连接池洁净与 schema 缓存一致性。升级前请务必完成三件事全量排查调用ExecuteFetchAsDBA的脚本拆分其中的多语句 SQL将批量执行需求切换到ExecuteMultiFetchAsDBA留意 v23 起的进一步收紧纯 CREATE 序列豁免也将移除提前规划长期兼容方案。相关源码与文档可继续在仓库内深挖release_notes.md、changelog.md、rpc_query.go、grpcvtctldserver/server.go、wrangler/tablet.go。赞分享数据库分布式数据库云原生后端数据存储【免费下载链接】vitessVitess is a database clustering system for horizontal scaling of MySQL.项目地址https://gitcode.com/gh_mirrors/vi/vitess点击查看免费下载相关推荐Vitess v17.0.6 破坏性变更解析ExecuteFetchAsDBA 正式拒绝多语句 SQLVitess v17.0.6 破坏性变更解析ExecuteFetchAsDBA 正式拒绝多语句 SQL 本文基于官方发布说明与仓库源码系统性解读 Vites数据库分布式数据库云原生后端数据存储Vitess v18.0.3 破坏性变更解析ExecuteFetchAsDBA 拒绝多语句 SQL 及其迁移指南Vitess v18.0.3 破坏性变更解析ExecuteFetchAsDBA 拒绝多语句 SQL 及其迁移指南 本指南以 Vitess v18.0.3 发布数据库分布式数据库云原生后端数据存储Vitess v18.0.3 版本全解析ExecuteFetchAsDBA 多语句加固与 47 项修复的实战指南Vitess v18.0.3 版本全解析ExecuteFetchAsDBA 多语句加固与 47 项修复的实战指南 v18.0.3 是 Vitess 18.0数据库分布式数据库云原生后端数据存储创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考