vitess不能直接当mysql代理用,因其不兼容全部mysql协议行为,如默认不支持prepare语句、不转发部分系统变量、对set names响应有差异,需使用官方mysql驱动并配置interpolateparams=true绕过预编译。

为什么不能直接把Vitess当“MySQL代理”用
很多人以为在Golang服务里配个vitess的地址就能像连普通MySQL一样用——不行。Vitess不是透明代理,它不兼容全部MySQL协议行为,比如不支持PREPARE语句(除非开启EnablePreparedStatements)、不转发某些系统变量、对SET NAMES响应有差异。Golang的database/sql驱动默认会发这些指令,一连就报ERROR 1105 (HY000): vttablet: ... unknown field或unexpected EOF。
实操建议:
- 必须用
vitess/go/vt/vttablet/tabletserver/throttle配套的mysql驱动(即vitess官方维护的github.com/vitessio/vitess/go/mysql),而不是go-sql-driver/mysql - 连接字符串中显式禁用预编译:
?interpolateParams=true&parseTime=true&multiStatements=false(interpolateParams=true让参数拼在SQL里,绕过PREPARE) - 初始化
sql.DB前调用mysql.RegisterDriver(),否则sql.Open("mysql", ...)会走错驱动
如何让Golang服务正确解析Vitess返回的分片路由信息
Vitess的VSchema定义了表分片逻辑,但Golang应用本身看不到这些元数据。你写的SELECT * FROM user WHERE user_id = 123能路由到正确分片,全靠Vitess的vtgate做SQL解析和重写。问题在于:如果查询带IN子句、跨分片JOIN或没带分片键,vtgate可能返回ERROR 1105 (HY000): target: ks.-.primary: error: ... cannot route query。
实操建议:
- 所有DML必须带上分片键(如
user_id),且不能用IN (1,2,3)这种多值——改用UNION ALL或循环单条执行 - 避免
SELECT *,明确列出字段;Vitess对*的列推导在复杂嵌套查询中容易出错 - 用
vtctlclient提前验证路由:vtctlclient -server=localhost:15999 GetRoutingRulesForQuery "SELECT id FROM user WHERE user_id=1"
怎样处理Vitess特有的错误码和重试逻辑
Vitess返回的错误不是标准MySQL errno,比如ER_DUP_ENTRY是1062,但Vitess可能返回1105并附带target: ks.0.primary这样的上下文。Golang里用errors.Is(err, sql.ErrNoRows)会失效,因为底层错误类型是*mysql.SQLError,且Code字段是uint16,不是int。
实操建议:
- 用
mysql.IsSQLError(err)判断是否为Vitess SQL错误,再检查err.(*mysql.SQLError).Code - 对
1105(通用错误)和1213(死锁)做指数退避重试,但1062(唯一键冲突)必须由业务层捕获后转为http.StatusConflict - 不要依赖
err.Error()字符串匹配——Vitess版本升级可能改变错误消息格式
本地开发时怎么绕过vtgate启动一堆组件
跑通一个vttablet+vtgate+etcd最小集群要开5个进程,本地调试太重。有人试过直接连vttablet端口(15000),结果发现它只接受vtgate的gRPC协议,不暴露MySQL协议端口。
实操建议:
- 用
vitess/examples/local里的docker-compose.yaml一键拉起,但把vtgate的mysql_port映射出来(默认3306) - 开发时在
sql.Open里用localhost:3306,生产环境才切到vtgate-svc:3306(K8s Service) - 禁用
vtgate的健康检查SQL(如SELECT 1),避免Golang驱动初始化时触发路由失败——在vtgate启动参数加--health_check_interval=0
真正麻烦的是DDL变更:Vitess不支持在线加索引,ALTER TABLE会锁整个分片。上线前得先用vtctlclient ApplySchema生成分片级SQL,再人工确认每个vttablet都执行成功——这点很容易被忽略。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











