关于 dryrun
dryrun 是面向 AI Agent、IDE 和 CI 的 PostgreSQL 架构分析命令行工具及 MCP 服务。它基于提交到项目中的离线快照提供架构信息,使助手能够验证查询和检查安全性,而无需获得数据库凭据。
主要功能
- 01捕获 PostgreSQL 架构快照
- 02检查架构规范与结构
- 03分析迁移锁和表重写
- 04依据架构验证 SQL
- 05比较快照并检测偏移
- 06通过 MCP 工具提供分析能力
适用场景
- 01在部署前检查迁移风险
- 02依据项目架构验证生成的 SQL
- 03让团队成员无需凭据即可查看架构
- 04比较不同版本的架构快照
MCP 相关
MCP 服务读取项目的离线快照,并提供架构探索、查询验证、执行计划分析、迁移检查、规则检查等工具。支持 stdio 或 SSE;部分工具需要连接实时数据库。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
9收录的工具列表 · 更新于 2 天前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| sql | string | 是 | SQL 查询。 |
| plan_json | object|array|string | 否 | 你已有的 EXPLAIN 计划,由用户粘贴或 CI 捕获:EXPLAIN (FORMAT JSON) 返回的 [{"Plan": ...}] 数组,或未包装的 {"Plan": ...} 对象。也接受这两种格式的 JSON 字符串,因为客户端可能会重新编码结构化参数。按原样读取;advise 绝不会重新运行它。 |
| include_index_suggestions | boolean | 否 | 包含索引建议(默认 true)。 |
详细介绍
DryRun PostgreSQL MCP
一个无需连接生产环境的 PostgreSQL MCP 服务。
dryrun 为 AI Agent、IDE 和 CI 提供完整的架构信息,基于离线快照,而非实时数据库连接。你可以检查架构、验证查询、检查迁移安全性并探索外键关系图。所有这些都无需让凭据离开 DBA 的机器。
dryrun 是 boringSQL 套件的一部分,与 RegreSQL 和 Fixturize 并列。
问题所在
LLM/AI 编码助手非常擅长编写代码和 SQL 查询,但它们对数据库一无所知。它们不知道你的架构、索引或约束。它们可能会生成一个在你最繁忙的表上获取 ACCESS EXCLUSIVE 锁的迁移,让你的应用停摆。
有些 PostgreSQL MCP 服务会要求你提供数据库连接。要执行管理任务,你可能还需要 SUPERUSER 权限。但这无异于自找麻烦。
我们已经见过这会导致什么:AI Agent 擦除了生产数据库,还有本应只读的 MCP 服务中出现了 SQL 注入漏洞。
模型不需要查询你的数据库,而是需要理解你的架构:结构、约束、统计信息和特定版本的行为。这些知识是结构性的。它会在部署迁移时发生变化,而非在两次查询之间变化。
DryRun 功能
dryrun 提供两种形式:CLI 工具和 MCP 服务。CLI 提取并分析你的架构。MCP 服务将分析结果提供给 AI 助手。它们有意设计为相互独立。
CLI - 提取并分析
CLI 连接到你的 PostgreSQL 数据库,检查完整目录(表、视图、索引、约束、分区、函数、枚举、RLS 策略、触发器、扩展、GUC),并将快照写入 .dryrun/history.db。该快照是其他所有功能的事实来源。
创建快照后,CLI 可以离线运行:
- Lint - 20 多条约定规则(命名、类型、主键、时间戳、分区)和 13 条结构审计规则(重复索引、外键覆盖、循环外键、vacuum 调优)
- 迁移安全性 - 锁类型分析、耗时估算、表重写检测,以及每条 DDL 语句的安全替代方案
- 查询验证 - 通过 libpg_query 解析 SQL,根据实际架构检查列引用,并检测反模式
- 快照差异 - 比较快照之间的架构、规划器统计信息或活动;检测与实时数据库之间的偏差
- 查询统计信息 - 按节点采集
pg_stat_statements,将 ORM 查询变体归并为查询形态,对比两次采集结果以找出新增或变慢的查询 - 多节点统计信息 - 副本级统计信息、seq_scan 热点、路由不均衡
MCP 服务 - 为 AI 助手提供架构知识
MCP 服务读取相同的快照。它通过 stdio 或 SSE 提供 9 个工具:架构探索与搜索、查询验证、执行计划分析、迁移检查、Lint、vacuum 健康检查,以及采集到的 pg_stat_statements 热门查询。连接实时数据库后,还会增加另外 3 个工具(explain_query、check_drift、columnar_report)。AI 助手可以在编写 SQL 时理解你的数据库。
无需数据库连接。助手永远不会看到凭据。
为什么选择离线
Schema 上下文应该放在文件中,而不是实时连接中。 列类型、行数估算、索引定义、FK 关系和 PostgreSQL 版本都可以一次性导出并提交到代码库。由一位有数据库访问权限的人导出 schema。其他所有人,无论是人类还是 AI Agent,都能在无需凭据的情况下获取完整的 schema 信息。
凭据不应该离开 DBA 的机器。 如果 MCP 服务需要 DATABASE_URL 才能发挥作用,那么每位使用它的开发者都需要生产环境凭据。这是一个与 AI 毫无关系的安全问题。
服务应该负责分析,而不是单纯转发。 返回原始的 \d+ 输出,只比自己把它粘贴到聊天中好一点点。真正的价值在于解读这些数据:检查迁移对你的 PostgreSQL 版本是否安全、标记缺少 FK 索引的情况,并根据实际 schema 验证列引用。
安装
需要 PostgreSQL 14 或更高版本。 不会拒绝较旧的服务端——dryrun 会发出警告并尽可能采集信息——但这些版本未经测试,某些数据流(尤其是规划器统计信息)将不可用。最低版本与上游仍受支持的最早版本保持一致。
Homebrew:
Homebrew 6.0 要求先信任第三方 tap,才能加载其中的 formula:
brew trust --tap boringsql/boringsql
brew install boringsql/boringsql/dryrun
在 Homebrew 5.x 及更早版本中,跳过 brew trust 步骤。如果你不想信任整个 tap,可以只信任该 formula:brew trust --formula boringsql/boringsql/dryrun。
npm / npx:
如果你已经安装了 Node,无需安装任何内容即可运行 dryrun:
npx @boringsql/dryrun --version
这会为你的平台(darwin-arm64、linux-x64、linux-arm64)获取预构建二进制文件、将其缓存并打印版本号。要将 dryrun 永久添加到 PATH:
npm install -g @boringsql/dryrun
dryrun --version
npm 包封装了相同的 Go 二进制文件;所有 CLI 命令的行为都完全相同。lint 等命令需要先有 schema 快照——请参阅快速入门。预构建二进制文件支持 macOS(Apple Silicon + Intel)、Linux(x64 + arm64)和 Windows x64。在其他平台(Alpine/musl、Windows arm64)上,请使用 Homebrew 或从源代码构建。
从源代码构建:
需要 Go 1.26+。如果尚未安装,请通过 go.dev/dl 安装。
git clone https://github.com/boringsql/dryrun.git
cd dryrun
go build -o bin/dryrun ./cmd/dryrun
二进制文件位于 bin/dryrun。
30 秒演示
安装 dryrun 后,无需数据库或任何设置,即可对克隆的本仓库中的现成 schema 快照运行 lint:
git clone https://github.com/boringsql/dryrun.git
cd dryrun/examples/demo
dryrun lint
(通过 npm 或 Homebrew 安装,但没有克隆仓库?你将没有 examples/demo——请跳转到快速入门,让 dryrun 使用你自己的 schema。下面的示例输出就是 lint 的结果。)
[ERROR] public.audit_log: table has no primary key
fix: add a primary key (bigint GENERATED ALWAYS AS IDENTITY recommended)
[WARN ] public.audit_log: gap in range partitions: ends at '2024-07-01' but next starts at '2024-10-01'
fix: inserts into the gap will fail unless a DEFAULT partition exists
[ERROR] public.task_comments: table has no primary key
fix: add a primary key (bigint GENERATED ALWAYS AS IDENTITY recommended)
[WARN ] public.projects.created_at: timestamp column uses timestamp without time zone instead of timestamptz
fix: use timestamptz for timestamp columns
[ERROR] public.tasks.project_id: FK 'tasks_project_id_fkey' on column(s) (project_id) has no covering index
fix: add an index on FK columns to avoid sequential scans on DELETE/UPDATE
[WARN ] public.users.email: column 'email' uses character varying(255), prefer text
fix: VARCHAR(n) adds a hidden CHECK constraint with no performance benefit
[WARN ] public.user_notifications: table is missing 'created_at' column
fix: add: created_at timestamptz NOT NULL DEFAULT now()
26 finding(s): 6 error, 20 warning, 0 info (13 tables checked)
无需数据库。完全基于离线快照运行。
同一个演示也可以通过 MCP 使用。在 examples/demo 目录中,将服务注册到你的助手:
claude mcp add dryrun -- npx -y @boringsql/dryrun mcp-serve
然后在该目录中提问:“我有哪些表,它们有什么问题?”
MCP 服务
只需一条命令,即可将服务接入 AI Agent。setup 会检测 Claude Code、Cursor、Codex 和 Zed,写入 Agent 的 MCP 配置,并在 AGENTS.md/CLAUDE.md 中添加指令,让 Agent 在编写 SQL 前先检查架构:
dryrun setup
要自行选择 Agent,或在非交互式 Shell 中使用,请传入 --agents:
dryrun setup --agents=claude,cursor # or: all
要手动注册服务:
# for claude code
claude mcp add dryrun -- dryrun mcp-serve
# for codex
codex mcp add dryrun -- dryrun mcp-serve
如果从源代码构建,请使用二进制文件的完整路径:
claude mcp add dryrun -- /path/to/dryrun mcp-serve
或者,无需安装,直接将客户端指向 npx:
claude mcp add dryrun -- npx -y @boringsql/dryrun mcp-serve
这种形式的原始客户端配置如下:
{
"mcpServers": {
"dryrun": {
"command": "npx",
"args": ["-y", "@boringsql/dryrun", "mcp-serve"]
}
}
}
服务会从当前项目的 .dryrun/history.db 中读取最新快照。无需数据库凭据;助手可通过离线快照获取完整的架构信息。
如果没有快照,服务仍会启动,其工具会提示尚未加载架构。使用 dryrun init --db "$DATABASE_URL" 捕获快照,或拉取队友推送的快照(dryrun snapshot pull --from-path ./snapshots,参见快速入门);服务会在下一次工具调用时加载快照,无需重启。
对于有多个数据库的项目,请针对每个数据库运行一次 dryrun mcp-serve,并在客户端配置中为每个服务添加一条配置。在单个 MCP 进程中原生支持多个数据库的功能正在 #7 中跟踪。
有关实时数据库设置、SSE 传输和 Claude Desktop 配置,请参阅教程。
快速入门
有两种入门方式,请选择适合你设置的方式。
选项 A:你可以访问数据库
如果你能连接到 PostgreSQL 实例(本地、开发或生产环境),只需一条命令即可完成所有操作:
dryrun init --db "$DATABASE_URL"
此命令会创建 dryrun.toml(包含 [project] id 和默认配置文件)、.dryrun/ 数据目录,并将数据库快照保存到 .dryrun/history.db。快照以 (project_id, database_id) 为键;如果项目有多个数据库(例如 auth、billing),请在每个配置文件中设置 database_id。完整配置参考请参阅 docs/dryrun-toml.md。
选项 B:其他人可以访问数据库
有凭据的人只需捕获一次快照并推送到共享目录——该目录可以位于仓库中,也可以放在双方都能访问的任意位置:
dryrun init --db "$DATABASE_URL"
dryrun snapshot push --to-path ./snapshots
他们需要同时提交 dryrun.toml 和 ./snapshots。其他人拉取快照:
dryrun snapshot pull --from-path ./snapshots
snapshot pull 会将快照加载到 .dryrun/history.db。他们的机器无需连接数据库。
提交 dryrun.toml 并非可选:快照以 (project_id, database_id) 为键,而 dryrun init 会根据实时数据库名称生成 database_id。队友如果在未使用 --db 的情况下运行 dryrun init,就会得到不同的 database_id;随后 pull 会报告 0 copied,因为它在源端不存在的键下查找快照。
推送的快照除了架构,还包含规划器和活动统计数据,因此依赖大小估算和清理数据的离线工具也能正常工作——普通 JSON 导出则无法做到这一点。如果需要使用注册表而非目录,请参阅 dryrun remote add 和 snapshot push --remote。如需向人工用户或 Agent 提供可读的 JSON,dryrun dump-schema 仍可生成该文件;它是导出文件,不是输入文件。
然后使用
dryrun lint
所有命令都从 .dryrun/history.db 离线运行。每个项目都有自己的 dryrun.toml 和 .dryrun/,没有全局状态。将 .dryrun/ 添加到 .gitignore。
快照存储在 .dryrun/history.db 中,以 (project_id, database_id) 为键。它是唯一的架构来源:MCP 服务、lint 和 drift 都从中读取数据。旧版 dryrun 留下的 .dryrun/schema.json 会被忽略。
数据库以 SQLite 的 WAL 模式运行,因此定时执行的 snapshot capture 可以与长时间运行的 mcp-serve 共用数据库:即使服务正在查询,捕获操作也可以提交,不必等待查询完成。WAL 会在旁边生成 history.db-wal 和 history.db-shm 辅助文件;最后一个进程正常退出时,这些文件会被删除,进程崩溃时则会残留,因此也要将它们与 .dryrun/ 一起忽略。需要注意两点:WAL 模式下的 history.db 即使在执行 lint 这类只读命令时,也需要对 .dryrun/ 有写入权限;WAL 需要共享内存,而网络文件系统不提供共享内存——位于 NFS 或 SMB 上的 .dryrun/ 会自动使用回滚日志(功能正确,但发生争用时速度较慢)。
多节点:从副本捕获活动数据
在主节点上执行 snapshot capture 会写入架构和规划器统计信息。活动计数器(idx_scan、n_dead_tup、最近一次 vacuum)位于各个副本上,因此也要捕获这些数据:
dryrun --profile primary snapshot capture --label primary
dryrun snapshot capture --from "$REPLICA1_URL" --label replica1
dryrun snapshot capture --from "$REPLICA2_URL" --label replica2
在 dryrun.toml 中配置 [[node]] 块后,dryrun snapshot capture --all 就能一次性完成所有捕获。
MCP 的 describe_table(节点明细)和 detect kind=anomalies 工具随后会展示各节点的 idx_scan,方便你发现路由不均衡问题。请参阅 docs/multi-node-stats.md。
每个项目使用多个数据库
dryrun snapshot capture 按 (project_id, database_id) 为快照建立索引。默认值即可使用——project_id 是你的文件夹名称,database_id 是 current_database() 返回的实际数据库名称:
dryrun init --db "$AUTH_DB" # captures auth
dryrun snapshot capture --db "$BILLING_DB" --label primary # billing gets its own stream
dryrun snapshot list --db "$AUTH_DB" # only auth snapshots
如需使用稳定的引用(并让 list / diff 无需重新输入 URL 即可运行),请在 dryrun.toml 中声明配置:
[project]
id = "myapp"
[profiles.auth]
db_url = "${AUTH_DATABASE_URL}"
database_id = "auth"
[profiles.billing]
db_url = "${BILLING_DATABASE_URL}"
database_id = "billing"
然后:
dryrun --profile billing snapshot list
dryrun --profile billing snapshot diff --latest
所有配置选项请参阅 docs/dryrun-toml.md。
所有与数据库相关的命令(init、probe、dump-schema、drift、stats apply、所有 snapshot 子命令)都接受 --profile;如果未提供 --db,则使用解析出的配置中的 db_url。lint 是离线命令:它读取 .dryrun/history.db,只有在显式传入 --db 时才会连接实时数据库。
注意: MCP 服务目前仅支持单个数据库。使用默认配置即可。或者,为每个数据库运行一个
dryrun mcp-serve进程。单个 MCP 进程内原生支持多个数据库的功能正在 #7 中跟踪。
在团队中共享快照
DryRun 在团队协作中的价值更高。多名开发者可以从任何符合 POSIX 标准的目录拉取快照。
要发布快照,你需要
cd project_name
# capture from the live DB (use cwd name for project name)
dryrun init --db "$DATABASE_URL"
dryrun snapshot capture --db "$DATABASE_URL" --label primary
dryrun snapshot push --to-path ./snapshots --all
开发者随后可以将快照导入本地历史记录
dryrun snapshot pull --from-path ./shared/snapshots --all
快照采用内容寻址方式({project}/{database}/{ts}-{hash}.json.zst),并且具有幂等性:重复推送同一个快照不会造成变化。
最简单的部署方式是使用专用的 git 仓库。创建快照仓库,并将 *.json.zst binary 添加到 .gitattributes,以免 git 尝试对比这些数据包。
拉取后,离线工具(lint、check_migration、drift)即可立即使用。
无需服务端,无需凭据。承诺依旧。
将快照推送到 OCI 注册表
任何 OCI 注册表都可以存储快照:GitHub Container Registry、Google Artifact Registry、Amazon ECR、Docker Hub、Harbor 或可自托管的注册表。注册表负责处理身份验证、保留策略和访问控制,因此无需运行服务。
按照使用 docker push 时的方式进行身份验证,注册远程端,然后推送:
docker login ghcr.io
dryrun remote add ghcr --ref ghcr.io/myorg/dryrun --default
dryrun snapshot capture --label primary --push
snapshot capture --push 可一步完成捕获和发布。使用方拉取:
dryrun snapshot pull --remote ghcr
默认情况下,push 和 pull 都只传输最新的一次记录,因此冷拉取(全新的 CI、空的 history.db)和共享存储的成本都很低,无论任一端保留了多少历史记录。使用 --full 同步整个历史记录,或使用 --since 7d(也可使用 2w、24h 或类似 2026-01-01 的 UTC 日期)指定时间范围。无论哪种方式,复制都按内容哈希增量进行,因此按固定周期推送的所有者每次只会上传新的观测数据。
--ref 是注册表基础地址。每个数据库都会在其下拥有自己的仓库:<ref>/<project_id>/<database_id>,因此 myapp 的 auth 数据库会存放在 ghcr.io/myorg/dryrun/myapp/auth。快照会映射为按内容哈希寻址的 OCI 工件,因此重复推送同一个快照不会产生任何变化,注册表中的共享 Blob 也会去重。对于 Google Artifact Registry,请使用 gcloud auth configure-docker us-docker.pkg.dev 代替 docker login;其余步骤完全相同。
身份验证。 默认情况下,dryrun 会复用你的 Docker 凭据(~/.docker/config.json 和凭据助手),因此任何可以通过 docker login 登录的注册表都无需额外配置即可使用。remote add 上的两个覆盖选项可满足其他情况:
--token-env VAR从环境变量读取静态 bearer 令牌,适用于签发短期令牌的注册表(例如,通过gcloud auth print-access-token提供给--token-env GAR_TOKEN)。--auth gcp直接使用 Google Application Default Credentials,因此在运行gcloud auth login后(或通过GOOGLE_APPLICATION_CREDENTIALS指定服务账号密钥),即可使用 Google Artifact Registry / Container Registry,而无需运行configure-docker。ADC 令牌会自动刷新。
有关按配置文件设置远程端以及跨项目共享同一数据流的信息,请参阅 docs/dryrun-toml.md。
更多
- 教程:了解离线、在线和多节点工作流,并查阅完整的工具参考
- 多节点统计信息:了解集群范围的统计信息收集、聚合规则和副本失衡检测
- 查询统计信息:了解
pg_stat_statements捕获、形状分组和差异比较 - 匿名化快照:了解如何生成可交给他人的快照,包括 PII 映射、掩码捕获,以及发送前应检查的内容
- 配置参考:了解
dryrun.toml配置文件、约定、远程端和 lint 规则 - CLI 稳定性:了解哪些命令稳定、哪些仍处于实验阶段
- 安全概览:了解 CLI/MCP 的划分和掩码处理
- boringSQL:博客和项目主页
- dryrun 项目页面:概览和文档
- 别让 AI 接触你的生产数据库:了解大多数 Postgres MCP 为何不安全,以及
dryrun有何不同 - RegreSQL:SQL 回归测试工具,也是
dryrun的配套工具 - Fixturize:为开发和测试对生产数据进行子集提取和掩码处理
许可证
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。