生产库操作别让 Agent 直连:用 dbward 把 SQL 变成可审批、可执行、可追溯的请求
AI 编码 Agent 已经能定位数据问题、生成迁移脚本,甚至通过 MCP 发起数据库查询。真正棘手的并不是它会不会写 SQL,而是如何把「提出一条 SQL」和「带着生产凭据执行它」拆开。把连接串交给 IDE、CI 或 Agent,速度很快,却同时扩大了误执行、提示注入和凭据扩散的风险面。
dbward 提供了一种更接近生产变更流程的边界:CLI、CI 或 MCP 客户端只提交请求;服务端根据策略决定是否需要批准;持有数据库凭据的 Agent 在获准后执行;全过程留下审计记录。它适用于 PostgreSQL 与 MySQL,核心组件采用 Apache-2.0,但项目也明确说明部分功能和预构建二进制包含商业许可证组件。因此在内部推广时,应把它理解为一个 open-core 的数据库操作网关,而不是笼统称作完全开源发行版。
先划清三种身份,而不是给所有人一把连接串
传统做法常把应用、运维脚本和自动化机器人都连到同一个生产数据库。dbward 的架构则划分为三层:
- 客户端:开发者 CLI 或 MCP 客户端,提交 SQL 与目标环境,但不保存数据库凭据;
- 服务端:运行审批工作流、策略、审计和令牌签发,也不保存数据库凭据;
- 执行 Agent:部署在受信任网络位置,持有数据库凭据,轮询并执行已获批准的操作。
这不是把审批 UI 放在数据库前面那么简单。服务端向执行 Agent 下发的是经 Ed25519 签名的执行令牌;README 说明令牌会绑定 SQL 的 SHA-256 哈希和目标数据库。这样,客户端请求与最终执行之间有可校验的关联。执行端又以出站 HTTPS 连接服务端,服务端不需要反向连入数据库网络;对于网络分区严格的生产环境,这比把控制面直接暴露给数据库更容易落地。
不过,边界并不会自动替你设计好。低权限账号、网络 ACL、备份与回滚窗口仍然是数据库自身的责任。dbward 的价值是把「谁能请求、谁能审批、什么条件下可执行」收束为一个显式流程,而不是替代数据库权限系统。
两分钟跑通的流程:提交、批准、恢复执行
官方 Quickstart 提供了 Docker 演示环境。下面的命令来自项目 README;它启动示例环境,并以 development 环境提交一个只读请求:
git clone https://github.com/dbward-dev/dbward.git cd dbward/examples/quickstart docker compose up -d docker compose run --rm alice execute "SELECT version()" -e development
开发环境的 dbward dev 会自动批准,适合验证安装链路;生产策略不应照搬这一默认值。正常审批模式中,请求并不会在人点下「批准」的瞬间自动执行。项目称之为 on-demand execution:提交方先创建请求,审批人批准后,提交方仍需显式执行 dbward request resume ,服务端才把请求标为待派发,执行 Agent 领取后连接数据库并回传结果。
这个多一步的恢复动作很有价值。它避免了「半小时前批准的 SQL,在业务高峰或上下文已变化时突然执行」的情况。对于迁移、批量更新或需要与发布窗口配合的操作,审批和实际执行可以分别发生在合适的时点。
给生产环境写一条最小策略,而不是只靠人工提醒
dbward 的工作流配置在 server.toml 中。下面是官方文档展示的结构:针对生产环境的查询和迁移,要求一个 admin 角色审批;而 staging 可以仅自动批准低风险请求。
[[workflows]] database = "*" environment = "production" operations = ["execute_select", "migrate_up", "migrate_down"] [[workflows.steps]] type = "approval" [[workflows.steps.approvers]] role = "admin" min = 1 [[workflows]] database = "*" environment = "staging" [workflows.auto_approve] mode = "risk_based" risk = "low"
这里的重点不是把所有 SQL 都阻塞住,而是把环境和操作类型写成可审查的规则。生产库的迁移、回滚和查询可以分别建工作流;执行策略还可以限制某个数据库、环境组合在时间窗内的最大执行次数。对会反复重试的 CI 或 Agent 来说,这比事后从日志里解释「为什么同一条 DDL 跑了十次」更可靠。
在提交前,MCP 客户端还可调用 dbward_preflight_sql 做 SQL 安全分析,而不创建请求。README 列出的检查包括风险分级、DDL 识别、DROP 阻断,以及 EXPLAIN 计划和修复提示。应把它当作预检层:先让 Agent 根据预检结果缩小影响范围,再把真正需要人工判断的请求送进审批队列。
MCP 接入:让模型会提请求,但拿不到生产密码
若使用支持 stdio MCP 的 AI 客户端,可以按官方配置加入本地服务:
{
"mcpServers": {
"dbward": {
"command": "dbward",
"args": ["mcp"]
}
}
}
项目目前列出 12 个 MCP 工具,例如执行查询的 dbward_execute_query、预检 SQL 的 dbward_preflight_sql、查看待审批请求的 dbward_list_pending、检查策略原因的 dbward_explain_policy_failure,以及读取表与字段信息的 dbward_inspect_schema。这意味着 Agent 可以先获取必要的 schema 上下文,再提出明确的操作请求;但它无法因为上下文里出现一句「直接删表」就绕过审批链路。
团队部署可使用远程 Streamable HTTP MCP,官方示例使用 https://your-server.example.com/mcp。远程模式的工具集合与本地不同:README 明确写明远程端提供 9 个工具,排除本地专用的迁移工具。因此不要假设本地 mcp 能力会原样出现在团队 HTTP 端点;上线前应按实际运输方式逐项测试工具可见性和权限。
审批网关不能替代的四件事
第一,把只读也按风险分级。读取用户邮箱、薪资或密钥派生表,未必比一次受控更新更低风险;策略应结合数据域与环境,而不只看 SQL 动词。
第二,给执行 Agent 单独的数据库账号。dbward 的隔离设计让客户端和服务端不接触凭据,但执行 Agent 若使用超级用户,边界仍然过宽。应按库、schema 和操作授予最小权限。
第三,把紧急通道当成受审计的例外。项目提供带必填理由的 break-glass 机制,且仅限 operator/admin,不通过 MCP 开放。生产团队仍需定义触发条件、复盘人和事后时间限制,避免「紧急」成为常规绕过。
第四,把审计记录接进现有事件流程。dbward 的审计日志使用哈希链,且提供验证命令;这能帮助发现记录被篡改,但不能替代集中日志、告警和变更单。值得把请求 ID、部署版本、工单号和事故复盘链接关联起来。
落地时别跳过三项运行准备
一是把角色映射先做小。 先只设置 requester、approver 和 operator 三类角色,审批人从真实值班或数据负责人中选择;不要把「能登录控制台」等同于「能批准生产变更」。当团队扩展到多数据库、多环境后,再为不同数据域拆分策略,审批记录才有解释力。
二是为失败准备可观察的状态。 请求卡在 pending、执行端离线、策略拒绝和 SQL 执行失败应被视作不同事件。发布时至少记录请求 ID、目标环境、执行账号、审批结论和结果摘要;同时监测执行 Agent 的连接状态。否则,团队可能只看到 Agent 没有回复,却无法判断是安全拦截还是基础设施故障。
三是从可逆、低影响任务开始演练。 例如在 staging 查询版本或创建测试迁移,确认提交、批准、恢复执行、审计验证和故障告警均能跑通;随后再引入有明确回滚方案的生产操作。审批系统最容易在真正紧急时暴露角色、通知与值班链路的问题,预演比事后补配置更便宜。
如果团队正尝试让 Claude Code、Cursor 或内部 Agent 帮忙处理数据库任务,最小可行路径不是立刻开放生产连接,而是选一个 staging 库:用 dbward dev 验证网络与执行链路,再为 production 写一条只覆盖低频操作的审批工作流,最后接入 MCP 预检和少量只读任务。
dbward 最适合解决的,是「自动化已经足够会操作,权限模型却仍停留在共享连接串」这一断层。它通过请求、策略、人工批准与受信任执行端的分离,让 AI 参与数据库工作时有明确的停点、责任边界和证据链。对于不需要审批、完全隔离的本地开发库,它可能显得过重;但一旦请求会触及真实生产数据,这种摩擦恰恰是必要的安全设计。