惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
D
DataBreaches.Net
博客园 - 三生石上(FineUI控件)
H
Hacker News: Front Page
Know Your Adversary
Know Your Adversary
Recorded Future
Recorded Future
The Hacker News
The Hacker News
Help Net Security
Help Net Security
月光博客
月光博客
L
LINUX DO - 热门话题
Hacker News - Newest:
Hacker News - Newest: "LLM"
T
Tor Project blog
Security Archives - TechRepublic
Security Archives - TechRepublic
aimingoo的专栏
aimingoo的专栏
Attack and Defense Labs
Attack and Defense Labs
Project Zero
Project Zero
V
Vulnerabilities – Threatpost
SecWiki News
SecWiki News
S
Security @ Cisco Blogs
Blog — PlanetScale
Blog — PlanetScale
V2EX - 技术
V2EX - 技术
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
A
Arctic Wolf
T
Threat Research - Cisco Blogs
WordPress大学
WordPress大学
H
Heimdal Security Blog
小众软件
小众软件
C
Check Point Blog
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Cyber Attacks, Cyber Crime and Cyber Security
Vercel News
Vercel News
云风的 BLOG
云风的 BLOG
Last Week in AI
Last Week in AI
L
LangChain Blog
博客园 - Franky
Martin Fowler
Martin Fowler
MongoDB | Blog
MongoDB | Blog
P
Proofpoint News Feed
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
J
Java Code Geeks
Apple Machine Learning Research
Apple Machine Learning Research
C
Cybersecurity and Infrastructure Security Agency CISA
C
CXSECURITY Database RSS Feed - CXSecurity.com
Microsoft Security Blog
Microsoft Security Blog
Google DeepMind News
Google DeepMind News
有赞技术团队
有赞技术团队
MyScale Blog
MyScale Blog
S
Schneier on Security

暗无天日

读:AI Agent 安全日志——从可见性与隐私的两难说起 - 暗无天日 AI写作的语言指纹——如何让文字不那么像机器 - 暗无天日 读:50 条 Claude Code 技巧——一个工程经理的六个月使用心得 读:AI 辅助开发为什么让 E2E 测试更有价值 - 暗无天日 读:在Emacs中使用Claude Code(Spacemacs适配版) - 暗无天日 Claude Code 背后的工程哲学——读 Agent Harness Engineering 读:Agent Harness Engineering——AI 智能体不只是模型,还有套件 - 暗无天日 browser-harness:让 AI 直接接管你的浏览器 - 暗无天日 读:Security-First CI/CD —— DevSecOps 自动化实践指南 TIL: 数字小键盘的小数点陷阱与行内算术求值 - 暗无天日 读:Immutability 不是万能药,它是一种权衡 - 暗无天日 Conducty:给 Claude Code 加上项目记忆和并行执行能力 - 暗无天日 读 — GitHub Trending 里的 Claude Code 技能包 读 — Prompt Caching 省钱指南 TIL: Emacs 中那些跟鼠标配合的冷门快捷键 - 暗无天日 读:Anvil——把 Emacs 变成 AI 的工具服务器 读:Emacs 代码折叠终极指南 - 暗无天日 读:Clojure 搭车客指南 - 暗无天日 git推送失败后恢复仓库损坏的完整记录 - 暗无天日 多智能体系统的两个有效模式——以及对 Claude Code 用户的启示 - 暗无天日 用 Org Babel 写 Literate 博文:扩展执行 + 定制导出 proced:Emacs 内置的进程查看器 - 暗无天日 从 proced 定制中学到的 Elisp 模式 读:让 Emacs proced 在 macOS 上显示 CPU 和内存 异步编程的函数着色税 - 暗无天日 链式调用的代价:JavaScript 和 Clojure 的共同教训 - 暗无天日 hyperfine:命令行基准测试工具 - 暗无天日 管道中的变量去哪了?——子 shell 作用域陷阱 - 暗无天日 开源包装器的信任陷阱:四个危险信号 - 暗无天日 程序员愿意为 AI 写文档,却不愿为同事写 - 暗无天日 mktemp: Shell 脚本中临时文件的安全陷阱与最佳实践 - 暗无天日 WSL9x —— 在 Windows 9x 里跑 Linux 内核 6.19 用 ox.el 做你想做的事 —— org-export 高级编程指南 读:Hot-wiring the Lisp Machine —— 用纯 Elisp 构建零依赖的 Org 静态站点生成器 Elisp 性能优化的六个实战教训 - 暗无天日 fcitx5 下 Emacs 无法切换输入法的排查 - 暗无天日 ERT 测试交互命令的三种方式 - 暗无天日 SEM Assistant: 当 Elisp 守护进程遇上 LLM 用 dmsg 给 Elisp 加上结构化调试日志 用 org-habit 追踪非每日习惯 - 暗无天日 Clojure X-Men:当编程语言特性变成超能力 - 暗无天日 TIL: 用 diff-hl 在 fringe 中显示 git 变更 读:llm-test —— 用 LLM agent 驱动 Emacs 测试 TIL: AI 时代的橡皮鸭调试 - 暗无天日 fcitx 启动后键盘输入卡顿的排查 - 暗无天日 TIL: 早期网页的图片热区导航 - 暗无天日 读 Seeing the Whole System 用 Emacs 自动生成每周链接推荐 - 暗无天日 读:ASCII control characters in my terminal 读 What to learn - 暗无天日 Lisp 的括号之痛——一个愚人节玩笑揭开的老伤疤 - 暗无天日 一本书该"线性读"还是"并行读" - 暗无天日 读 How to Monetize a Blog:一篇伪装成变现指南的讽刺文 Python Mock 第三方依赖的四种策略 - 暗无天日 Emacs Lisp 热重载实用指南 - 暗无天日 Prot 的 Emacs 配置哲学 - 暗无天日 TIL: 从直播对谈中学到的三个 Emacs 技巧 - 暗无天日 TIL: 自动使用项目虚拟环境的 Python - 暗无天日 TIL: 让 Help buffer 自动获得焦点 一条命令让本地开发用上 HTTPS —— slim 工具介绍 用 fsck 检查和修复 Linux 文件系统 排查Linux进程"卡死"实战:从strace到gdb全流程 - 暗无天日 PostgreSQL 索引:从基础到你可能不知道的高级用法 - 暗无天日 用 .pdbrc 自定义 Python 调试器 ANSI 转义码的标准化现状 - 暗无天日 终端程序的潜规则 - 暗无天日 PARA Org-mode 测试配置 - 暗无天日 AI越强越辣鸡?控制论说这是必然的 - 暗无天日 AI 越强越需要你盯着——反馈循环实操指南 - 暗无天日 你的AI代理正在偷你的密钥——四种你没想到的泄露通道 - 暗无天日 LLM 在 DevOps 中的三种角色 - 暗无天日 写作风格的反建议 - 暗无天日 反驳本质复杂性——Dan Luu 论为什么《没有银弹》错了 - 暗无天日 文件充满了危险——Dan Luu 谈文件系统的可靠性陷阱 - 暗无天日 AI 时代的 PARA 方法:用 Org-mode 和 AI 打造个人知识管理系统 Linux 数据去重学习笔记 - 暗无天日 创建跨平台 ZIP 文件的隐藏陷阱:Extra Field - 暗无天日 X11 Forwarding 排障指南 - 暗无天日 IP欺骗端口扫描:当别人冒充你去扫描别人 - 暗无天日 Linux 输入栈全景解析:从硬件按键到屏幕响应 - 暗无天日 Unix 系统中那些被埋没的配置开关——以 FontConfig 为例 - 暗无天日 在Linux上限制儿童使用电脑 - 暗无天日 GIF不仅仅是一种图片格式——用GIF流做些奇怪的事 - 暗无天日 Leiningen 学习笔记:Clojure 项目构建与管理从入门到实战配置 - 暗无天日 Google SRE Book 读书笔记 - 暗无天日 yes 管道 head 发生了什么 - 暗无天日 为什么 nohup 在 crontab 中不起作用 Bash中的Indirection与Nameref - 暗无天日 Linux PAM 简介 - 暗无天日 从Linux ISO文件启动计算机 - 暗无天日 用 Bash 打造一个Screen Locker 用GitHub Actions自动构建EGO博客 - 暗无天日 blocking I/O 的作用 - 暗无天日 mobileog 手机端同步提示Error:2 No such file 的解决方法 回收 WSL2 VHDX 文件占用空间 使用 org-mode columnview 生成任务列表 - 暗无天日 Emacs 作为 MPD 客户端 - 暗无天日 移动文件路径却不破坏org file link的方法 - 暗无天日 如何合理的导出help link 成HTML - 暗无天日 笑话理解之Biology - 暗无天日
读:当 Agent 开始写数据库——六个防御模式 - 暗无天日
2026-05-17 · via 暗无天日

上篇 当 Agent 成为生产调用者 聊了 Agent 打破运维假设的宏观框架。Arpit Bhayani 在 这篇文章 里把镜头拉近到数据库层,逐个拆解传统数据库架构建立在哪些假设之上,以及 Agent 如何把每个假设都踩了一遍。六个防御模式,全是已有技术的重新组合,不需要新工具。

模式一:给 Agent 建专用角色,绑超时

Agent 查数据库没人盯着。一条查询跑了 30 秒,人写出来的代码会有人发现不对劲去排查,Agent 不会,它可能只是在推理循环里卡住了。

PostgreSQL 可以在角色上直接绑超时,不用动应用代码:

CREATE ROLE agent_worker;
ALTER ROLE agent_worker SET statement_timeout = '5s';
ALTER ROLE agent_worker SET idle_in_transaction_session_timeout = '10s';

statement_timeout 管单条语句的执行上限,超了自动取消。 idle_in_transaction_session_timeout 管事务开启后的空闲等待上限。Agent 经常在事务中间停下来等 LLM 返回结果,这个参数就是治这个毛病的:思考可以,别占着事务连接不放。

超时绑在角色上而不是应用上,好处是同一个数据库里人走普通角色、Agent 走 agent_worker 角色,各管各的超时,互不干扰。

模式二:软删除 + 操作者追踪

Agent 会删数据,而且可能因为推理出错、重试或者误解任务而删掉不该删的。人删数据好歹是有意为之,出问题找得到人;Agent 删数据是自主决策的结果,你没法事后问它"你当时怎么想的"。

所以不能让它硬删。加三列标记删除:

ALTER TABLE orders ADD COLUMN deleted_at TIMESTAMPTZ;
ALTER TABLE orders ADD COLUMN deleted_by TEXT;
ALTER TABLE orders ADD COLUMN delete_reason TEXT;

再建一个视图给 Agent 用:

CREATE VIEW active_orders AS
  SELECT * FROM orders WHERE deleted_at IS NULL;

Agent 查 active_orders ,看不到已删除的行,也恢复不了。

deleted_by 这一列比另外两列都重要。出事后两小时你要查"Agent X 到底删了什么",靠的就是它:

SELECT * FROM orders
WHERE deleted_by = 'agent:customer-support-v2'
ORDER BY deleted_at DESC;

值用 agent:角色名user:用户ID 两种前缀区分来源,排查时一眼分清是人干的还是 Agent 干的。

模式三:幂等键

Agent 天生会重试。所有编排框架都是"至少执行一次"的语义:步骤失败了重跑,网络抖动让它以为没成功就再来一遍。写入路径不做幂等保护,重试一次就多一行脏数据。

幂等键的原理不复杂:Agent 每次写入带一个稳定标识符,数据库靠唯一约束拒绝重复,重试多少次都只留一条记录。

先建一张带幂等键的状态变更表:

CREATE TABLE order_state_log (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  order_id UUID NOT NULL REFERENCES orders(id),
  previous_status TEXT,
  new_status TEXT NOT NULL,
  changed_by TEXT NOT NULL,
  changed_at TIMESTAMPTZ DEFAULT now(),
  reason TEXT,
  idempotency_key TEXT UNIQUE
);

键从编排层的 task_id + 操作类型 + 目标 ID 组合生成,同一个逻辑操作不管重试几次都出同一个键。一行Shell 就能算:

echo -n "task-abc-123:update_status:order-456" | sha256sum | cut -c1-32
c72a5000a3e5135734decc054b677e3b

Agent 第一次写入成功,第二次重试时 UNIQUE 约束静默拒绝,响应照样返回成功。数据库里始终只有一条记录,不会因为重试而膨胀。

这种"只追加不修改"的思路跟 Event Sourcing 同源,只不过 Event Sourcing 是整条链路只追加,这里是单表级别:每条状态变更都是一行新记录,"撤销"就是再插一行,不走 UPDATE 或 DELETE。

模式四:独立连接池 + PgBouncer

Agent 连数据库的方式跟人不一样,连的久、连的多、数量不可控。

连的久:Agent 发一条查询,停下来等 LLM 推理,再发一条,再等。连接占用时间拉长到查询时间 + LLM 推理时间 x 推理步数,比普通请求长一个数量级。

连的多:一个高层任务可能生成多个子 Agent 并行干活,一个任务变五个连接。

数量不可控:开发时 3 个 Agent,上线时变 30 个,没人想起来更新连接池配置。

所以 Agent 要用独立的连接池,跟人工流量分开:

pool_size = 10,           max_overflow = 5,         pool_timeout = 3,         pool_recycle = 300,       

pool_timeout 设为 3 秒是故意的。拿不到连接就快速失败、带退避重试,别在队列里等着。排队等待是级联故障的经典起点。

Agent 数量多了以后,在 Agent 和 PostgreSQL 之间加一层 PgBouncer(连接池代理),设为事务级池化:

pool_mode = transaction       max_client_conn = 500         default_pool_size = 20        reserve_pool_size = 5         

事务级池化的意思是:Agent 的多步任务期间一直占着连接,但每个事务一提交,PgBouncer 就把底层 PostgreSQL 连接转给别的 Agent 用。20 个真实连接就能服务 500 个 Agent 连接。

模式五:查询注释监控

Agent 出的 bug 跟普通应用 bug 不一样。普通应用报错,日志里有堆栈,工程师能查。Agent 的错误是语义级的:查询语法正确,返回了结果,但结果本身是错的。日志里完全看不出来。Agent 拿到慢查询结果照用不误,拿到空结果集不知道是数据真的不存在还是查询写错了,继续往下走,可能拿错误数据做决策。

解法是给每条 Agent 查询打标签,标明是哪个 Agent、哪个任务、哪一步发出的:

SELECT * FROM orders WHERE fulfillment_status = 'pending';

注释会出现在 pg_stat_activitypg_stat_statements 和慢查询日志里。 pg_stat_statements 是 PostgreSQL 扩展,需要先启用( CREATE EXTENSION pg_stat_statements )才能查。按 Agent 分组的监控视图:

SELECT
  (regexp_match(query, 'agent_id=([^,]+)'))[1] AS agent_id,
  count(*) AS call_count,
  round(mean_exec_time::numeric, 2) AS avg_ms,
  round(total_exec_time::numeric, 2) AS total_ms
FROM pg_stat_statements
WHERE query LIKE '%agent_id=%'
GROUP BY 1
ORDER BY total_ms DESC;

某个 Agent 占了 60% 的数据库时间,马上能定位到。没注释的话, pg_stat_statements 里一堆 SQL,只能猜"这大概是哪个 Agent 发的"。

模式六:语义化 Schema + 视图层

Agent 通过 Text-to-SQL、MCP 工具或直接读 schema 来了解表结构。列名叫什么,直接决定 LLM 生成的 SQL 对不对。

看两组对比就明白了:

CREATE TABLE orders (
  id UUID PRIMARY KEY,
  usr_id UUID,             stat_cd INT,             flg_1 BOOLEAN,           upd_ts TIMESTAMPTZ     );
CREATE TABLE orders (
  id UUID PRIMARY KEY,
  customer_id UUID NOT NULL REFERENCES customers(id),
  fulfillment_status TEXT NOT NULL CHECK (
    fulfillment_status IN ('pending', 'processing', 'shipped', 'delivered', 'cancelled')
  ),
  requires_signature BOOLEAN NOT NULL DEFAULT false,
  last_modified_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

第二套里 fulfillment_status 一看就知道是订单履行状态, CHECK 约束把合法值列全了,LLM 不用猜。第一套里 stat_cd 是个状态码,2 是什么 7 是什么,LLM 只能蒙。

老表改名迁移成本太高,可以在上面盖一层视图:

CREATE VIEW agent_orders AS
SELECT
  id,
  usr_id         AS customer_id,
  CASE stat_cd
    WHEN 1 THEN 'pending'
    WHEN 2 THEN 'processing'
    WHEN 5 THEN 'shipped'
    WHEN 7 THEN 'delivered'
    WHEN 9 THEN 'cancelled'
  END            AS fulfillment_status,
  flg_1          AS requires_signature,
  upd_ts         AS last_modified_at
FROM orders
WHERE deleted_at IS NULL;  

Agent 只查视图,不碰底层表。视图把缩写翻成语义化名字,把状态码翻成文字。再给列加注释,等于给 LLM 写参考手册:

COMMENT ON COLUMN agent_orders.fulfillment_status IS
  '订单在履行流程中的当前状态。用这个字段筛选需要操作的订单:'
  'pending 和 processing 是活跃订单。'
  'cancelled 订单不应被修改。';

注释写得好,Text-to-SQL 生成的查询就准。

小结

六个模式全靠 PostgreSQL 已有能力就能实现:角色参数、软删除、唯一约束、连接池、查询注释、视图和列注释。不用上新工具、不用换新框架。变的只是默认配置的态度:以前这些是"锦上添花"的活,Agent 时代变成了"雪中送炭"的事。