Erdmates Logo
Erdmates
返回博客
AIMCP模式设计PostgreSQL

被AI代理读取的数据库:MCP时代的模式设计原则

AI代理通过MCP直接连接数据库的情况越来越多。本文整理如何设计名称、注释和约束,让代理不会误解模式,以及如何安全地划分权限。

2026年10月12日8 分钟阅读

AI代理开始直接读取数据库

MCP(Model Context Protocol)是一项开放标准,旨在统一AI工具连接外部数据和系统的方式。Anthropic于2024年11月25日发布了MCP,并于2025年12月9日将其捐赠给Linux Foundation旗下的Agentic AI Foundation。接入面向数据库的MCP服务器后,AI代理可以查询表列表和列,并直接执行SQL。

这带来了设计视角上的变化。人类开发者可以查阅公司内部Wiki或询问同事,但代理看到的大多是数据库目录(catalog)——表名、列名与类型、约束、注释。只有让模式本身成为文档,代理才不会连接错误的表或弄错单位。

本文以PostgreSQL为基准,整理五条对人有益、对代理更为重要的原则。

1. 名称不要缩写,按含义命名

代理会靠猜测来理解usr_amt_cd这样的缩写。而猜测可能出错。

-- 应避免的命名:缩写、没有单位、无意义的标志
CREATE TABLE ord (
  id     BIGINT PRIMARY KEY,
  usr    BIGINT,
  amt    NUMERIC,
  flg    CHAR(1),
  dt     TIMESTAMP
);

-- 推荐:含义、单位、时区体现在名称和类型中
CREATE TABLE orders (
  id            BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  customer_id   BIGINT        NOT NULL,
  amount_krw    NUMERIC(12,0) NOT NULL,
  is_refunded   BOOLEAN       NOT NULL DEFAULT false,
  ordered_at    TIMESTAMPTZ   NOT NULL DEFAULT now()
);
  • 把单位和货币写进名称:amount_krw、duration_ms、weight_g
  • 布尔值以is_、has_开头:用is_refunded代替flg
  • 同一概念在所有表中使用同一名称:如果有的地方叫user_id,有的地方叫member_no,代理就无法知道两者是否是同一个东西
  • 时间使用TIMESTAMPTZ:没有时区的值,无论是人还是代理,理解都会出现分歧

2. 用COMMENT ON把含义留在目录中

PostgreSQL的COMMENT ON会把说明存储在目录(pg_description)中。与代码注释或Wiki不同,它随数据库一起存在,因此查询模式的工具可以通过同一途径一并读取。

COMMENT ON TABLE orders IS '客户订单。在支付完成时创建,即使取消也不删除行(以is_refunded标记)。';
COMMENT ON COLUMN orders.amount_krw IS '支付金额(韩元,含增值税)。折扣后的金额。';
COMMENT ON COLUMN orders.is_refunded IS '是否全额退款。部分退款请参见refunds表。';

存储的说明可以这样查询。

SELECT a.attname                                  AS column_name,
       format_type(a.atttypid, a.atttypmod)       AS data_type,
       col_description(a.attrelid, a.attnum)      AS description
FROM pg_attribute a
WHERE a.attrelid = 'orders'::regclass
  AND a.attnum > 0
  AND NOT a.attisdropped;

应该写些什么呢?

  • 值的单位和包含范围(是否含增值税、折扣前还是折扣后)
  • 状态值的含义及其转换规则
  • 是否为软删除,以及"真正有效的行"的条件
  • 与其他表的关系中需要注意的地方(如部分退款在另一张表中等)

3. 用约束表达规则——代理看不到应用代码

如果"该列的值只能是pending、paid、shipped之一"这条规则只存在于应用代码中,那么对代理来说,这条规则并不存在。用约束声明后,它可以从目录中读取,而且即使有人试图写入错误的值,数据库也会拒绝,成为最后一道防线。

CREATE TABLE customers (
  id     BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  email  TEXT NOT NULL UNIQUE
);

CREATE TABLE shipments (
  id           BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
  order_id     BIGINT NOT NULL REFERENCES orders (id),
  status       TEXT   NOT NULL
               CHECK (status IN ('pending', 'paid', 'shipped', 'delivered')),
  shipped_at   TIMESTAMPTZ,
  CHECK (status <> 'shipped' OR shipped_at IS NOT NULL)
);
  • 明确声明外键,代理就不必猜测JOIN路径,而可以从目录中确认
  • CHECK能体现允许的值以及列与列之间的规则
  • NOT NULL、UNIQUE传达"始终存在""只有一个"这样的事实

4. 用视图整理要呈现给代理的部分

如果让代理每次都从原始表计算"月销售额",那么每次提问时,是否包含退款、如何处理时区都可能不一样。把达成共识的定义固定为一个视图并附上说明,代理只需使用这个视图即可。

CREATE VIEW monthly_revenue AS
SELECT date_trunc('month', ordered_at AT TIME ZONE 'Asia/Seoul') AS month_kst,
       sum(amount_krw)                                          AS revenue_krw,
       count(*)                                                 AS order_count
FROM orders
WHERE NOT is_refunded
GROUP BY 1;

COMMENT ON VIEW monthly_revenue IS '月销售额(韩元)。按韩国时间划分月份,不含全额退款的订单。';

5. 权限最小化——边界靠GRANT,其余只是辅助手段

为代理使用的账号创建单独的角色,只授予所需模式的读取权限。

CREATE ROLE ai_reader LOGIN;  -- 密码和认证方式按运营环境的策略设置

GRANT USAGE  ON SCHEMA analytics TO ai_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO ai_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA analytics GRANT SELECT ON TABLES TO ai_reader;

-- 用于防止失误的默认值(并非安全边界)
ALTER ROLE ai_reader SET default_transaction_read_only = on;
ALTER ROLE ai_reader SET statement_timeout = '15s';

有一点需要注意。default_transaction_read_only和statement_timeout是用户可以在会话中重新更改的设置。它们能减少误发写入查询、繁重查询长时间运行的情况,但并不能阻止这些情况。真正的边界是通过GRANT授予的权限。

  • 个人信息列最好直接从代理专用模式的视图中排除,这样更安全
  • 如果需要按行划分范围,请使用ALTER TABLE ... ENABLE ROW LEVEL SECURITY和策略(CREATE POLICY)
  • 不连接生产环境的主库,而是连接只读副本(备库),可以减轻繁重的分析查询对服务的影响

使用Erdmates设计

在Erdmates中为表和列写好说明后,导出为PostgreSQL DDL时会一并生成COMMENT ON TABLE、COMMENT ON COLUMN语句(MySQL则为表的COMMENT)。反过来,导入现有数据库的SQL时,也会读取COMMENT ON语句,将其还原为ERD中的说明。在ERD中通过连线确认外键关系的同时打磨好名称和说明,人和代理看到的就是同一份文档。

总结

在代理直接操作数据库的时代,模式设计并不是什么新技术,而是更严格地遵守老原则。体现含义的名称、留在目录中的说明、以约束声明的规则、承载共识定义的视图、最小权限。具备这五点的模式能让代理少犯错,即使犯了错,数据库也会将其拦下。

立即使用Erdmates开始

使用AI驱动的ERD编辑器开始数据库设计。免费使用。

免费试用演示免费开始

相关文章

bigint、UUID v4 还是 UUID v7?主键选择指南(含 PostgreSQL 18 的 uuidv7())

比较 bigint、UUID v4 和 UUID v7 主键的优缺点,介绍 PostgreSQL 18 内置的 uuidv7() 带来的变化,以及不同场景下的选择方法。

PostgreSQL 19预览:影响模式设计与运维的变化(基于Beta 4)

以官方发布说明(Beta 4)为准,整理即将正式发布的PostgreSQL 19的变更中直接影响表设计、迁移和运维的内容。同时介绍在Beta阶段被撤回的功能,以及升级前需要确认的行为变化。

用pgvector设计RAG向量表:从维度、索引到过滤

以pgvector 0.8为准,整理在PostgreSQL中用pgvector存储文档嵌入向量时的表结构、各向量类型的维度限制、HNSW索引以及元数据过滤的设计。

Erdmates Logo
Erdmates

使用自然语言设计数据库,通过AI驱动的ERD编辑器与团队实时协作。

服务

  • 功能介绍
  • 价格方案
  • 演示
  • SQL 转 ERD

资源

  • 博客
  • 帮助
  • 联系我们

法律声明

  • 服务条款
  • 隐私政策
  • 第三方提供
公司名称: Produx|代表人: 최정회
地址: 강원특별자치도 원주시 솔우물2길 4-1 (무실동)
电子邮件: master@erdmates.com
隐私保护负责人: 최정회|托管服务提供商: Amazon Web Services

© 2026 Produx. 版权所有。