面向 Agent 的数据库排查 Skill。让 Agent 能查数据库,同时不必把生产库的写权限交到一次提示词的判断上。
问题
Agent 排查线上问题时需要读数据库:找表、看字段、按业务键查记录、对比环境。但一旦同一个入口也能写,风险就不再由「这次查询对不对」决定,而由「护栏是否真的存在」决定。
database-cli 把执行收在一个入口上:scripts/db-query 是唯一真实执行路径,负责 SQL 安全检查、结果集上限、连接管理和审计。MCP 只是它之上的一层可选适配器,不是第二个查询引擎。
安全模型
其中最关键的一个刻意放在配置文件里——拼命令的一方无法自行主张写权限。
只放行无副作用的起始关键字。DDL、权限、事务、存储过程、锁、导出,以及带副作用的函数一律拦截。
环境必须写明 "writable": true 才接受 --allow-write。这个声明存在配置文件里,Agent 无法通过构造命令绕过;临时连接没有配置项承载它,需要另传 --writable,因此也无法把受保护的库改写成临时连接来规避。
在上一条成立的前提下,仍需为每次写入显式传入 --allow-write。UPDATE / DELETE 必须带 WHERE。
执行前先在服务端 COUNT 真实影响行数,超过 max_write_rows(默认 1000)直接拒绝。WHERE 1=1 这类看似有 WHERE、实则全表的语句不会放行。
EXPLAIN ANALYZE 对 DML 也拦:
MySQL 8.0.18+ 会真的执行被分析的语句,而首关键字是 EXPLAIN 会让它绕过所有按起始 token 生效的检查——WHERE 强制要求、影响面上限、以及审计的读写判定。
护栏演示
下面的输出取自真实执行,不是示意。点标签切换场景,也会自动轮播。
场景 ① 与 ② 都以退出码 2 拒绝,数据库上没有发生任何变更。场景 ③ 不需要写权限。
brew install sq
git clone https://github.com/CassianFlorin/database-cli.git
cd database-cli只读本地配置与 sq 可用性,不连数据库:
scripts/db-query --setup-status凭据写入被 gitignore 的本地配置;生产环境建议用 --password-env 而非明文:
scripts/install \
--env qa01 \
--url "mysql://db-qa01.example.internal:3306/orders" \
--username readonly_user \
--password-env QA01_DB_PASSWORD \
--non-interactive# 跨可见 schema 搜索字段名
scripts/db-query --env qa01 --search-objects "%order_no%" --object-type column
# 按业务键取记录
scripts/db-query --env qa01 \
--sql "SELECT id, order_no, status FROM orders.cc_order WHERE order_no = 'A1001'"修数流程
前置检查、变更、回滚、后置检查——四件事在一条命令里生成,供人工复核。
返回真实影响行数与写前快照。不需要任何写权限。行数与预期不符时应当停下。
从写前镜像生成反向 SQL,只生成不执行。字面量按目标 driver 转义。
把四步编排成一条命令。默认 executed: false,加 --allow-write 才执行。
# 先看影响面,无需写权限
scripts/db-query --env qa01 --preview-write "UPDATE cc_order SET status = 1 WHERE order_no = 'A1001'"
# 生成回滚 SQL(只生成,不执行)
scripts/db-query --env qa01 --key-columns id \
--generate-rollback "UPDATE cc_order SET status = 1 WHERE order_no = 'A1001'"
# 完整修复包
scripts/db-query --env qa01 --key-columns id \
--repair "UPDATE cc_order SET status = 1 WHERE order_no = 'A1001'"MCP 适配层
给需要结构化工具调用的客户端准备的可选入口,全部委托给同一个 CLI。
就绪状态、缺失前置条件与下一步动作,不连数据库。
列出连接;运行中新增连接无需重启客户端。
搜索 schema、表、字段、索引、存储过程;查看结构。
只读查询;后者可在获得授权后执行 DML。
影响面预览与回滚生成,均不需要写权限。
完整修复包;以及不执行的 SQL 安全校验。
适配层刻意保持很薄:它不实现查询逻辑,也不暴露 CLI 没有的能力。add_connection 有意不支持声明写权限——否则运行中的 Agent 就能给自己开写权限,配置侧的声明也就失去了意义。
支持范围
通过 sq 连接。也可以直接复用已有的 sq source handle。
| 数据库 | driver | 说明 |
|---|---|---|
| MySQL / MariaDB | mysql mariadb | 元数据搜索走 INFORMATION_SCHEMA |
| PostgreSQL | postgres | 元数据搜索走 information_schema 与 pg_catalog |
| SQLite | sqlite3 | 文件路径连接,端到端测试即用它 |
| DuckDB | duckdb | 文件路径连接 |
| SQL Server | sqlserver | 元数据搜索请用 --inspect |
| ClickHouse | clickhouse | 字面量按反斜杠转义方言处理 |