当团队成员纷纷将数据库连接串粘贴给AI助手后,作者分享如何建立可识别、可限权、可审计的AI数据库访问体系,包含实战架构方案。
六个月前,团队里只有一个人能通过 AI 工具查询生产数据库。现在人人都能了。有人把连接字符串粘贴到 AI 助手里,效果出奇地好,于是这个做法迅速传开。现在三位工程师、一位产品经理和一位支持主管都在向聊天机器人提问,这些问题悄无声息地转化成了针对实时数据的 SELECT 语句。
这确实带来了巨大的便利。但同时也是一个治理盲区。如果有人问"为什么这个客户上周二的数据看起来很奇怪",你能回答是谁——或者是什么——运行了那条触及他们记录的查询吗?在连接字符串散落各处、凭据共用的情况下,诚实回答通常是"不知道"。
本文要讨论的是如何弥合这个差距:如何在保持可识别性、作用域可控和可审计的前提下,给团队提供 AI 驱动的数据库访问能力。目标不是拖慢任何人的速度,而是确保当访问者从一个人扩大到二十个人时,你仍然知道发生了什么。
人们将 AI 工具连接到数据库的默认方式,是直接给它一个连接字符串:
postgresql://app_user:s3cr3t@db.internal:5432/production
在一个团队中这样做,会同时引入四个问题。每个查询在日志里看起来都一样,因为大家都共享同一个数据库身份。密钥散落在提示词、聊天历史、配置文件和截图中。想要轮换它,就得追遍每个粘贴过的地方。而且数据库根本不知道某条语句是来自人类还是模型。
数据库自身的审计日志在这种情况下也救不了你,因为从它的视角看,只有一个用户 app_user 在执行所有操作。你已经丢失了对治理最重要的两个事实:访问权归属于哪个人,以及这个人的工具是否被授权做了它所做的事。
解决这个问题的模式是在 AI 客户端和数据库之间放置一个经纪人——通常是一个 MCP(Model Context Protocol)服务器。各个工具不再各自持有原始凭据,而是连接到一个受治理的网关,由网关持有连接并强制执行规则。
Model Context Protocol 是一个开放标准,通过一致的接口将 AI 助手与外部系统连接。对于数据库场景,MCP 服务器对外暴露一小套操作(列出表、获取 schema、执行只读查询),成为身份、权限和日志记录的单一落脚点。
通过一个网关路由所有人,带来了散落连接字符串无法具备的五个属性:
像 Draxlr 这样的托管 MCP 服务器实现了这种形态——通过 OAuth 连接、只读、凭据保存在服务端——但模式本身比任何产品都重要。你完全可以自己搭建同样的东西。以下内容两种方式都适用。
无论使用哪种经纪人,不可妥协的是每条查询的日志,要包含足够的上下文来回答"谁做了什么、为什么"。最少要记录:操作者身份、SQL、目标数据库、时间戳,以及将查询关联回触发它的对话的相关 ID。
一个简单的审计表结构如下:
CREATE TABLE ai_query_audit (
id BIGSERIAL PRIMARY KEY,
actor_email TEXT NOT NULL, -- the human, via OAuth
ai_client TEXT NOT NULL, -- claude, cursor, chatgpt...
database_name TEXT NOT NULL,
sql_text TEXT NOT NULL,
row_count INTEGER,
status TEXT NOT NULL, -- 'allowed' | 'rejected'
reason TEXT, -- why rejected, if it was
correlation_id UUID NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE INDEX idx_audit_actor_time ON ai_query_audit (actor_email, created_at DESC);
经纪人在每次尝试时写入一行——包括被拒绝的那些,而被拒绝的往往才是有意思的。这样一来,前面的问题就有答案了:
-- Who touched customer 4821's data in the last week?
SELECT actor_email, ai_client, created_at, status, sql_text
FROM ai_query_audit
WHERE sql_text ILIKE '%customer_id = 4821%'
AND created_at >= now() - INTERVAL '7 days'
ORDER BY created_at DESC;
actor_email | ai_client | created_at | status | sql_text
---------------------+-----------+---------------------+---------+------------------------------------------
dana@acme.com | claude | 2026-08-19 14:02:11 | allowed | SELECT * FROM orders WHERE customer_id...
support@acme.com | chatgpt | 2026-08-18 09:41:55 | allowed | SELECT status, total FROM orders WHERE...
你可以基于这张表构建治理仪表盘——查询最多的人、被拒绝的写操作随时间的趋势、哪些表被访问最频繁、异常的下班后活动等。这才是安全团队真正需要的可观测性层。
并非每个人都需要相同的覆盖范围。AI 访问的最小权限至少应该和你给员工的 RBAC 一样精细——实际上应该更精细,因为只要被允许,模型会很乐意尝试任何事。两个杠杆可以完成大部分工作:某个身份能看到哪些数据库,以及是否为只读。
经纪人侧的一个策略配置大概长这样:
roles:
support:
databases: [production_readonly]
mode: read-only
row_filter: "region = :user_region" # row-level scoping
analytics:
databases: [production_readonly, events_warehouse]
mode: read-only
engineering:
databases: [production_readonly, staging]
mode: read-only
注意这里完全没有写模式。对于 AI 探索工作流,这通常是正确的:模型可以读取数据、帮助你理解世界,但不能修改任何一行数据。如果某个提示词生成了 DELETE FROM subscriptions,经纪人会拒绝它并记录这次尝试,而不是执行它。
行级过滤器也是让这件事在面向客户的场景中安全运行的关键。在经纪人侧绑定一个类似 tenant_id = :current_tenant 的过滤器,那么支持人员问"显示最近的订单"时,永远只能看到自己区域的数据——无论模型如何措辞 SQL。
治理不应对实际操作的人可见。对他们来说,仍然是纯粹的英语问答:
User: How many trial accounts converted to paid last month, by plan?
AI 客户端通过经纪人获取 schema(这样它用的是真实的列名而不是幻觉出来的),生成 SQL,然后经纪人在该用户身份下以只读方式执行:
SELECT s.plan,
COUNT(*) AS conversions
FROM subscriptions s
JOIN users u ON u.id = s.user_id
WHERE u.trial_started_at >= date_trunc('month', now()) - INTERVAL '1 month'
AND u.trial_started_at < date_trunc('month', now())
AND s.status = 'active'
GROUP BY s.plan
ORDER BY conversions DESC;
用户得到了答案。与此同时,一行记录落入了 ai_query_audit,带有用户的邮箱、使用的客户端和相关 ID。没有人输入过凭据;也不会有人事后问"等等,谁跑了那条查询"却查不出来。
只记录查询而不记录身份。 一份满是匿名 SQL 的日志几乎等于没有。操作者人类身份这一列是将日志变成审计轨迹的关键——首先要记录它。
把共享服务账户当作"AI 用户"。 如果每个队友的 AI 流量都认证为同一个账户,你只是用更多步骤重新构建了连接字符串的问题。每个人(或每个 Agent)对应一个身份,绑定到你的 IAM。
配置文件中长期有效的令牌。 永久密钥无法干净地撤销,而且容易泄露。优先使用会过期、能在有人离职时被中央撤销的 OAuth 授权。
只读形同虚设。 "我们告诉人们不要执行写操作"不是控制手段。需要在经纪人层面强制执行,这样一条被拒绝的 UPDATE 才是一个被记录的事件,而不是一次信任练习。
忽视影子 MCP。 一旦有了受治理的路径,就要让它成为唯一的路径。如果人们仍然能直接让工具指向数据库,你的审计日志就在最危险的查询所在的地方有了漏洞。
日志没有保留期或防篡改机制。 一份能被人悄悄编辑的审计轨迹算不上真正的审计轨迹。把日志发到只能追加的地方,并设置与你的合规需求相匹配的保留窗口。
散落的连接字符串给团队带来了速度,却带走了问责制。速度可以保留。在 AI 客户端和数据库之间放一个经纪人,让每个人以自己的身份认证,保持访问只读且按角色划分作用域,记录每次尝试——允许的和被拒绝的——并附带身份信息。无论你是自己搭建这个经纪人还是采用托管 MCP 服务器,属性都是一样的:可归属、可撤销、最小权限、可审计。
检验标准很简单。如果有人问"谁在凌晨两点查询了生产库、为什么",你应该能用一条 SELECT 回答。
你的团队现在是怎么处理这个的——共享凭据、自建代理,还是托管网关?你每条查询实际记录了什么?我很想在评论区听到什么有效、什么坑过你们。