如果你是一名后端开发或者DBA,大概率经历过这种场景:开发在群里喊了一句“帮忙在订单表加个索引”,然后DBA手动登到生产库执行,执行完在聊天记录里回一句“好了”。整个过程看起来没什么问题,但半年后复盘某个线上事故时,你根本找不到是谁在什么时间改了什么,这就是典型的SQL变更失控。我这次要聊的,就是GitHub上8.8k Star的一个轻量级方案,一个简单高效的MySQL审核平台,社区里叫它Yearning。它解决的问题很具体:把“提交SQL、审核SQL、执行SQL、留痕、回滚”这件事搬到Web页面上,让每一次数据库变更都有流程、有记录、可追溯。
这个平台适合谁?如果你所在团队还处于“SQL变更靠口头沟通”的阶段,或者你想在业务库和开发之间加一道可控的审核层,那这篇内容值得看完。我会从部署、建数据源、走通一条工单、到常见坑位,把整个实操链路拆开讲,最后补上我自己落地过程中踩过的坑和调整建议,希望对正在调研或准备引入审核平台的你有帮助。
1. 先说清楚:为什么SQL上线需要一个“审核平台”
1.1 没有审核的生产变更是高风险裸奔
很多小团队对SQL审核的第一反应是“我们有DBA人工看,不需要平台”。这个想法在项目早期成立,但等库多了、人多了之后就会出问题。你有没有遇到过这些情况:一条 UPDATE 忘记带 WHERE,直接把整张表的数据改掉;一条 ALTER TABLE 在大表上执行,导致业务锁表;开发在测试环境执行没问题,但同一个表在正式环境的数据量差了100倍,执行计划直接失效。
这些事故的根源并不是某个人技术不行,而是SQL变更缺少一层可感知、可拦截的机制。人工审核能解决一部分问题,但人的注意力是有限的,尤其是当一天要处理几十个工单的时候,很容易漏掉关键风险点。审核平台的作用不是取代DBA,而是把“经验判断”沉淀成自动检查规则,把“通过了就执行”变成可留痕的流程。
Yearning这类平台解决的核心问题,就是让SQL不再绕过流程直接作用到生产库。每次变更都必须经过提交、自动检测、人工审核、执行、记录几个环节,中间任何一步出了问题都能找到人,也能通过回滚机制把影响降到最低。
1.2 这个平台到底干了什么
用一句话概括Yearning的能力:它把MySQL变更和查询统一收口到一个Web平台里,前端面向开发者和DBA,后端连接你的业务数据库。开发者在平台上提交SQL工单,平台会先用内置规则扫描一遍,指出哪些地方有风险,然后由有权限的审核人确认是否放行,最后平台再代替人执行到目标库。
这里还要提一下Yearning核心的几个功能模块。第一是SQL审核,支持DDL和DML两大类,DDL的典型场景是加索引、改表结构,DML的典型场景是数据订正、批量更新;第二是SQL查询,支持把查询权限也收进来,并且所有查询日志可审计;第三是回滚,基于binlog解析生成反向SQL;第四是权限管理,可以将用户划分为admin、DBA、开发人员、查询人员等角色。
功能不少,但整个平台是Go写的,部署形态很轻,这正好是它Star数高的原因之一。很多团队不需要Archery那种重型全家桶,只想要一个能快速跑起来、把审核流程先建立起来的工具,Yearning在这个位置是非常合适的。
1.3 为什么我建议中小团队先选轻量方案
我在调研审核工具的时候其实对比过好几个方案。有的平台功能全、界面复杂,但对硬件和依赖要求也高,光初始化配置就能让一个新手折腾一整天;有的平台没有Web界面,需要自己在命令行里做二次开发;还有一些只是语法审核器,并没有完整工单流。
Yearning的定位很明确,就是“简单高效”。8.8k Star这个数字说明它的社区认可度很高,但真正打动我的是它能让团队在半小时内把一套审核流程跑通,而不是花两周去研究文档。对于20人以下的后端团队、两三个DBA兼职维护十几个库的场景,轻量方案远比重型平台更容易落地。
这里我也想劝一句:不要为了追求功能齐全而上重平台。审核流程的核心是先让所有变更过一道门,规则可以后续慢慢加,流程可以逐步优化。一个能坚持用下去的轻量平台,比一个功能强大但没人愿意配置的重平台有价值得多。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 部署之前,先把这三个边界搞清楚
2.1 元数据库和业务库是两个概念
部署Yearning之前,容易被搞混的一点是:它自身也需要一个MySQL实例来存平台数据,比如用户信息、工单记录、审核日志。这个存储平台自身数据的库,叫元数据库,和你后面要接入审核的业务数据库不能混为一谈。
我见过有人把Yearning连到业务主库上,结果一启动就把业务库里建了一堆 yearning_ 开头的表,这种操作非常危险。元数据库尽量单独部署一个MySQL实例,如果条件有限,也要至少单独建一个database,并且严格限制账号权限,只给这个库的权限,不要给整个实例的超级权限。
如果你手上暂时没有多余的MySQL实例,可以先用Docker快速起一个专门给Yearning用。网上很多“docker安装mysql”的教程可以直接参考,但要注意几点:字符集建议设置为 utf8mb4,时区设置为 +08:00,数据目录挂载到宿主机持久化,这样容器重启不会丢数据。把这个“内部库”和后面接入的平台业务数据源分开,后续维护会清爽很多。
2.2 想做回滚?binlog参数先对齐
Yearning的回滚功能很吸引人,但它不是凭空生成的,需要MySQL开启了binlog,并且相关参数满足条件。如果你在部署平台时才去改参数,通常已经晚了,因为有些参数是要在MySQL实例启动前配置好的。
关键参数有三项:log_bin、binlog_format、binlog_row_image。生产环境建议 log_bin=ON,binlog_format=ROW,binlog_row_image=FULL。如果你的库用的是默认的 STATEMENT 格式,那Yearning没法精确解析出回滚SQL;如果 binlog_row_image 不是FULL,可能拿不到修改前的完整镜像,回滚质量也会打折扣。
另外还有一个容易忽略的点:连接MySQL执行回滚解析的账号,需要额外的复制权限。最稳妥的做法是在业务库里创建一个专用账号,授权给Yearning,然后按照官方文档要求给这个账号加上 REPLICATION SLAVE、REPLICATION CLIENT 权限。很多团队部署完平台后发现回滚按钮不可用,排查到最后就是账号权限少了一个。
2.3 平台和业务库之间的网络与账号
Yearning是部署在一个地方,业务库可能分布在不同的内网网段甚至不同机房。你需要提前确认网络连通性,最简单粗暴的验证方式是从Yearning所在主机执行 mysql -h业务库IP -P端口 -u账号 -p 看能不能连上。如果连不上,后面在平台里配置再多数据源也没用。
容器部署时还有一个很常见的坑:Yearning跑在Docker容器里,你在容器里看到的 127.0.0.1 是容器自身,不是你宿主机。所以当Yearning容器要连宿主机上的MySQL时,千万不要填 127.0.0.1,要填宿主机在局域网里的实际IP,或者使用 host.docker.internal 这类特殊域名(具体视Docker环境而定)。否则日志里会出现类似连接被拒的错误,你会误以为是MySQL密码写错了。
业务库的连接账号也建议遵循最小权限原则。Yearning执行DML需要目标库的 SELECT、UPDATE、DELETE、INSERT 权限,执行DDL需要 ALTER、INDEX、CREATE 等权限,但如果你有多种类型的库要接入,最好按库分别授权,别用一个万能账号走天下。
3. 快速部署:我用Docker跑通整个流程的记录
3.1 准备元数据库
我这边测试环境用的是一台内网机器,Docker和MySQL都已经就绪。第一步是先给Yearning建一个独立的元数据库和专用账号,SQL如下:
sql复制CREATE DATABASE yearning DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
CREATE USER 'yearning'@'%' IDENTIFIED BY '换成你自己的强密码';
GRANT ALL PRIVILEGES ON yearning.* TO 'yearning'@'%';
FLUSH PRIVILEGES;
注意这里只授权了 yearning 库,不要顺手给全局权限。如果这个账号后续要用作binlog解析,那就单独再找一个业务库账号加复制权限,别把超级权限都塞给平台专用账号,不然万一平台被入侵或者配置失误,影响面太大。
元数据库的版本不用太纠结,MySQL 5.7和8.0都能跑Yearning,但生产环境建议用8.0,毕竟新版本在安全性、字符集处理上都更好,也符合长期维护节奏。
3.2 启动Yearning容器
Yearning从3.x版本开始,部署方式比早期简单很多,基本的启动方式是通过环境变量把元数据库的连接信息传给容器。下面是我当时用的 docker-compose.yml,改掉密码和IP就能直接用:
yaml复制version: '3'
services:
yearning:
image: yearning/yearning:3.1.0
container_name: yearning
restart: always
ports:
- "8000:8000"
environment:
MYSQL_ADDR: "192.168.1.10:3306"
MYSQL_USER: "yearning"
MYSQL_PASSWORD: "换成你自己的强密码"
MYSQL_DB: "yearning"
volumes:
- /etc/localtime:/etc/localtime:ro
启动之后可以用 docker compose up -d 拉起来,然后通过 docker logs -f yearning 观察日志。正常情况下日志会显示数据库连接成功,端口监听8000。需要提醒的是,不同版本的环境变量名可能存在差异,如果启动后日志提示缺参数或者连不上库,第一时间去官方仓库的Release说明里核对当前版本的环境变量,这是我踩过一次的坑。
在元数据库账号密码没问题、网络通的情况下,启动过程基本在几十秒内完成。如果日志一直报连接拒绝,优先查网络和账号授权,不要急着怀疑镜像问题。
3.3 打开安装页初始化
容器起来之后,浏览器访问 http://服务器IP:8000,会进入初始化界面。不同小版本的界面流程略有差异,但核心步骤一致:创建管理员账号、填写元数据库连接信息、确认初始化。
这里我强烈建议把管理员密码设置成高强度密码,并且不要用这个管理员账号日常操作所有工单。初始化完成后,第一件事是进入用户管理,建一个专门给自己日常用的账号,再按需要建开发人员账号和审核人员账号。
整个初始化过程不需要改代码、不需要编译,这也是我推荐用Docker部署的原因。比起源码编译依赖一堆Go环境,容器化方式更适合快速验证。如果你后续想升级版本,换一下镜像Tag再重新创建容器即可,元数据都在MySQL里存着,不会丢。
4. 实战:从提交DDL工单到自动执行、回滚
4.1 接入第一个业务数据源
Yearning启动完后,需要用管理员账号登录后台,在数据源管理里添加你要管理的业务库。注意这个数据源是最终要执行SQL的库,不是存储Yearning自身数据的元数据库,两个别填反了。
我接入的第一个业务库是一个订单库,填写项大体包括:数据源名称(比如“订单核心库”)、环境类型(测试、预发、生产)、数据库地址、端口、账号、默认字符集。填完之后先点一下测试连接,确认能连上再保存。
连接账号我单独在订单库里创建了一个,权限只给了这个库需要的查询和变更权限。不要为了省事直接复用元数据库账号,更不要用MySQL的root账号去连业务库。Yearning在执行SQL的时候是以你配置的这个身份去执行的,如果权限过大,一条危险的工单即使过了审核,执行时也可能产生比预期更大的破坏力。
4.2 设计一套最简单的审核流程
Yearning是有流程审批功能的,但我不建议第一次就配五级审批链,那样只会让所有人都觉得流程繁琐。我的建议是先按最简单的“提交人 -> 审核人 -> 执行”模型来做。
具体在后台里做三件事:第一,建用户,把自己的审核账号和开发账号分开;第二,建立角色并分配权限,比如开发人员可以提交工单但没有审核执行权;第三,在流程配置里指定某类数据源的审核人。这样每个工单提交后,对应的审核人会收到待办通知,审核人确认无误后,再由审核人或平台执行。
如果你后续有DBA团队,可以把执行权单独给DBA,开发人员只负责提交SQL,执行动作由DBA完成。如果团队小、信得过的审核人能身兼数职,也可以让审核人同时拥有执行权限。流程设计要顺着团队现有的协作习惯来,别一上来就弄个重流程,否则大家很快就会想办法绕过平台。
4.3 用一张真实工单跑通全流程
下面我用一个真实场景演示完整链路。某天业务方提诉求:订单查询变慢,需要给 orders 表的 user_id 和 created_at 建一个联合索引。
开发人员登录Yearning后,新建一个DDL工单,填写数据源、库名,在SQL输入框里粘贴下面这条语句:
sql复制ALTER TABLE orders ADD INDEX idx_user_id_created_at (user_id, created_at);
很多人把SQL粘进去后就直接提交了,其实应该先点一下“检测”。Yearning会对这条DDL做语法解析和基本的规则检查,比如是否命中禁止的操作类型、是否影响大表等。以这条加索引为例,只要表数据量不是特别离谱,检测通常能通过;如果表太大,平台可能会提示“影响行数较多”,要求人工复核。
提交之后,审核人登录后台找到这条待办工单,需要关注几个关键信息:目标库是否是生产环境、SQL语法是否正确、索引命名是否符合规范、当前表的数据量以及执行DDL可能产生的锁时长。我当时的审核意见是同意,然后点了“执行”。
执行完成后,工单状态会变成已完成,操作日志里会留下谁在什么时间提交、谁审核、谁执行、执行结果如何。整个动作不超过五分钟,但所有痕迹都被记录下来了,这就是平台最大的价值。
4.4 高危DML回滚的实现逻辑
DDL工单跑通后,我再举一个DML回滚的案例。场景是一条数据订正SQL,更新了一批用户的手机号,执行到一半发现更新条件写错了。如果直接连库操作,这时候只能靠备份恢复,或者手动写反向SQL,效率极低,还容易出错。Yearning的DML回滚功能在这种场景下会非常有用。
回滚的前提前面说过:MySQL开启了binlog,格式为ROW,且Yearning能解析到对应的binlog。当一条DML工单执行成功后,系统会记录执行产生的binlog位置信息,然后展示回滚入口,你可以选择立即生成对应的反向SQL。反向SQL的意思是:把UPDATE改成对应的UPDATE恢复原值,把DELETE改成INSERT,把INSERT改成DELETE。
我实际使用后的感受是,回滚SQL不是100%完美,它受binlog保留时长影响。如果执行时间离你发现事故的时间太长,binlog被清理了,回滚就做不了了。所以发现数据订正错误后要第一时间去平台上看回滚入口,别拖到binlog过期。
还有一点要强调:回滚SQL生成后,建议先在测试环境执行一遍,确认影响行数和预期一致,再用新的DML工单方式交到生产执行。别把回滚功能当成无限后悔药,它只是把事故恢复时间从小时级缩短到分钟级。
4.5 定时执行和批量变更建议
Yearning还支持定时执行工单,这个能力配合大表操作特别好用。比如你要在千万级大表上做一个在线加字段的操作,即使测试环境验证过,也最好安排在凌晨低峰期执行。定时执行可以避免你半夜爬起来手动敲命令,平台到点会自动跑,执行结束后留下日志。
不过这里有个实操提醒:定时执行不是把提交时间设好就不管了,你仍然需要在执行前几分钟登录看一眼工单审核状态是否已完成。因为审核流程如果没走完,定时任务到点不会绕过审核去执行,而是会卡在等待状态。我第一次用定时执行时就遇到过这个问题,后来养成了习惯:每次设置定时后,顺手看一眼审核人有没有处理完。
批量变更的场景我更建议拆小批执行。比如几十万行的历史数据要刷字段,别在一个工单里塞一条大SQL,而是分多批,每批几百条或几千条,边跑边观察。平台虽然能帮你一次执行完,但数据库负载和行锁影响还得靠你自己控制。
5. 团队接入和影响范围:不是只有DBA一个人在玩
5.1 每个角色该怎么配合
接入了审核平台之后,团队的工作方式会有一个明显变化。开发人员不再是直接连生产库执行任何语句,而是在平台上提交工单,相当于多了一道“自己先检查一遍”的动作。审核人员则从“帮人跑SQL”变成“理解并确认SQL风险”,工作重心更接近真正的代码评审。
我落地时最明显的感觉是:开发人员提交工单写得越规范,审核效率越高。后来我们规定,DDL工单必须写清楚目的和影响表,DML工单必须附带 SELECT 预先查看影响行数的确认语句,审核人员看到这类工单基本都能快速放行。久而久之,大家反而形成了提交前自查的好习惯。
5.2 查询与审计权限怎么收口
审核平台另一个常被忽略的价值是查询审计。很多公司并不是没有审计要求,而是根本不知道员工在生产库里查了什么、导出了什么。Yearning的查询功能可以对接指定的业务库,用户登录平台后直接在线查询,而每一次查询都会留下日志。
如果你所在的团队对数据安全要求比较高,可以在后台把开发人员的直接查询权限收掉,让他们统一走平台的在线查询,并且按需配置库、表级权限。对于包含敏感信息的列,我也建议尽量通过脱敏或者白名单方式来控制,不要让查询功能变成数据导出的又一个入口。查询审计的价值不在于限制每一个人,而是万一出了数据泄露事件,你能在几秒钟内定位到“谁、在什么时间、查了什么内容”。
5.3 重点配置的审核拦截规则
审核平台的自动检查规则并不需要全部打开,关键是把高风险的几个规则配置好,效果就非常明显。我个人的优先级排序如下:
| 规则类型 | 拦截原因 | 建议 |
|---|---|---|
| 不带WHERE的UPDATE/DELETE | 全表更新/删除,极易造成灾难 | 必须拦截,强制人工确认 |
| DROP TABLE / TRUNCATE | 结构性删除,回滚几乎不可能 | 必须拦截,高危操作走单独审批 |
| SELECT * | 浪费IO,容易拖垮大表 | 建议拦截,要求显式列出字段 |
| 大事务变更 | 执行时间长,引发主从延迟和锁等待 | 按影响行数阈值预警 |
| 唯一键冲突的高频写入 | 不可见业务异常,容易反复报错 | 结合业务语义判断 |
配置规则时不要追求“零风险”,因为任何规则都有可能误伤合法操作。更合理的做法是设置“拦截+人工审核”的降级通道,特别紧急的工单可以由审核人强制放行并备注原因,这样既保留了灵活性,也让每一次放行都有据可查。
5.4 长期看对流程和事故处理的影响
上线审核平台半年后,我对它的价值感受更深了。以前复盘事故要翻聊天记录、查执行日志,经常靠猜。现在只需要在Yearning里按时间查工单,就能看到某条SQL是不是通过审核后执行的,谁审核的,执行完有没有回滚动作。这种可追溯性对内部流程审计、团队人员交接、新人培训都有直接帮助。
另外,新加入的同事再也不需要问“我们生产环境怎么连、有没有现成的账号”这类问题了。登录平台、提交工单、等审核,是唯一的数据库变更新手路径。数据库权限入口被平台统一收口,连查库都要走审批的团队,数据安全水位会明显高出一截。
6. 常见问题与排障记录
6.1 部署期最容易踩的五个坑
我把这段时间遇到过的客户端问题整理成一个速查表,如果你在部署过程中遇到类似情况,可以对照排查。
| 现象 | 可能原因 | 处理方式 |
|---|---|---|
| 容器启动后一直报连接不上数据库 | 填了127.0.0.1,容器内访问不到宿主机 | 改成宿主机的局域网IP |
| 浏览器访问8000端口打不开 | 防火墙未放行端口 | 确认安全组和firewalld规则 |
| 初始化完成后登录失败 | 使用了过低版本或初始化数据未落库 | 清空元数据库重新初始化 |
| 平台能登录但连接业务库失败 | 业务库授权IP限制,或网络不通 | 从Yearning所在机器手动测试连接 |
| 回滚按钮置灰不可用 | binlog未开启或格式不是ROW | 修改MySQL参数并重启实例 |
这里还想特别说明一点:很多部署问题其实不是平台问题,而是我把“容器内网络”和“宿主机网络”搞混了。Docker部署的应用和宿主机部署的应用在网络视角上很像两台不同的机器,排查连通性时不要想当然。
6.2 使用中常见的疑问处理
有同事问我,为什么某条SQL自动检测没通过,但审核人还是可以执行?这是平台设计上的一个特点:规则是辅助而非绝对禁止,审核人有权限在备注原因后强制放行。这种设计在实际运维中很有价值,因为总会有特殊的业务需求需要打破常态。
还有人问,如果平台本身挂了,生产库变更是不是就完全停摆?从我们规范看,是的。平台挂了就说明数据库变更需要暂停,这是一个刻意的“故障模式”。宁可让变更暂停一小时,也不要让变更绕过流程偷偷执行。如果团队纪律不好,很容易在平台故障时打开直连数据库的口子,一开就再也关不上了。
另外,Yearning的工单历史是存在元数据库里的,我建议在常规MySQL备份之外,把元数据库的备份也纳入运维体系。就算只是每天一次全量备份,也足够在误删元数据时保住主要记录。
6.3 运行稳定后我会重点看的几个后台项
平台稳定运行后,不需要天天盯着工单列表,但有几项我会定期检查。一是审核时效,统计一下从提交工单到审核通过的平均时间,如果超过半天就要考虑是审核人配置太少还是工单描述不清楚。二是异常执行记录,专门看有没有被强制放行的高危SQL,如果频率过高说明规则配置可能太严,需要调整。
三是用户账号权限,定期清理离职人员账号和长期不用的查询账号。到这里我需要提一个更朴素的判断标准:工具只是工具,决定这套体系好不好的,永远是团队愿不愿意把数据库变更当成一件需要评审的事情,而不仅仅是能跑就行。
最后再分享一个小技巧:在把Yearning推向全团队之前,先自己用测试库完整走两遍“提交-审核-执行-回滚”流程,把所有角色账号都建好,再拉第一批开发进来试点。很多团队失败是因为流程没理顺就让全员用了,结果问题全都暴露在生产工单上。你先把流程里的坑填完,后面推广就会顺很多。
