从“AI失忆症”说起:我为什么给 Claude Code 配了长期记忆
先讲一个每次开新会话都会遇到的场景:头天晚上花了两个小时跟 Claude Code 讨论清楚了项目里某个模块的架构取舍,把userService重构为事件驱动的方案,还约定了命名规范。第二天打开终端,敲下claude,它礼貌地打了个招呼,然后对这个项目一无所知。你又得把昨天的结论重新讲一遍,甚至得翻聊天记录把关键决策点贴回去。
这种“每次开箱即失忆”的体验,在重度使用命令行 AI 编程助手之后会越来越让人抓狂。Claude Code 本身的单次会话上下文其实做得很好,但它默认没有跨会话记忆,而一个真实项目的生命周期是以周、月为单位的。你在一个会话里积累的设计决策、踩坑记录、模块地图,过了夜就归零,这不是工具不行,而是缺失了“记忆层”。
claude-mem 就是冲着这个痛点来的。它是一款给 Claude Code 加装长期记忆的开源工具,基于会话自动总结、SQLite 本地存储、语义检索这三板斧,让 Claude Code 在新会话里能自动恢复项目上下文、用户偏好和历史决策。装完之后最直观的体验是:它开始“记得你是谁、记得项目聊过什么”,那些重复交代背景的沟通成本几乎可以砍掉。
这篇内容我会从项目设计思路、工作机制、安装配置、实际使用到问题排查,完整拆一遍 claude-mem 到底是怎么工作的、哪些环节值得借鉴,以及我实际用了一季度之后踩过的坑和总结的经验。适合已经在用 Claude Code、且感觉到“会话失忆”正在拖慢自己的开发者,也适合对 AI 编程工具如何做持久化记忆感兴趣、想了解其内部设计的人。
1. 项目整体设计与思路拆解:为 LLM 补上“跨会话记忆层”
1.1 痛点定位:会话隔离是 LLM 编程助手的先天短板
要理解 claude-mem 的设计动机,得先看清 Claude Code 这类工具的基础工作方式。它本质上是把大模型接到终端环境里,通过工具调用去读文件、执行命令、编辑代码。每个会话是一次独立的上下文窗口,窗口之内模型能记住你聊过的所有内容,窗口一关,这些内容就成了历史。
这在单次复杂任务里没有问题,但真实开发流程是碎片化的。你今天改 A 模块,明天修 B 模块的 bug,后天回过头来继续 A 模块的优化,中间还会穿插需求讨论、架构调整、依赖升级。每个会话都需要重建项目背景:目录结构是什么、当前分支在做什么、之前定过什么约定、有哪些文件是“雷区”不能乱动。这些背景信息如果每次都要人工补充,工具的效率就大打折扣。
有人会说,你可以把项目文档写成README.md或ARCHITECTURE.md,每次开会话时让 Claude Code 去读。这是个办法,但问题在于:文档是静态的,而代码仓库每天都在变化;且让模型每次主动去读文档,既消耗 token 又不可靠,它可能读漏也可能读完就忘。真正需要的是“自动沉淀、自动注入”,而不是“手动搬运”。claude-mem 做的正是这件事的自动化。
1.2 方案选型:为什么是 SQLite + TF-IDF,而不是向量数据库
实现长期记忆的第一反应是“上向量数据库”——这是目前 AI 应用的主流思路,把文本切成 chunk,用 embedding 存进向量库,查询时做相似度检索。但在 claude-mem 这个具体场景下,作者没有走这条“重”路线,而是选择了 SQLite 存储 + TF-IDF 相似度计算的轻量实现。
这个选择本身值得聊一聊。向量检索的优势在于语义理解能力强,“苹果手机”和“iPhone”能匹配上;但代价是要引入 embedding 模型、向量库依赖、额外的服务部署。claude-mem 的目标是给 Claude Code 做记忆层,对性能的要求是“毫秒级注入上下文”,对部署的要求是“零额外服务”。SQLite 单文件、无服务、稳定可靠,天然适合这个场景。而 TF-IDF 虽然对语义的理解不如 embedding 深,但在代码关键词、技术名词这类“词汇重合度较高”的文本上,效果已经够用,尤其是记忆内容本身就是从会话里提炼出的摘要,核心概念都会显式出现。
我在实际使用中验证了这套方案的可行性:项目运行几个星期后,记忆库里有上千条记录,检索耗时基本感觉不到延迟。很多场景下,TF-IDF 的“够用就好”其实比“花哨但重”的方案更落地。
1.3 记忆分级设计:摘要记忆、实体记忆与偏好记忆
claude-mem 的记忆不是“一刀切”地全部塞进库里,而是做了分层设计,这一点在项目文档里体现得很清晰。
第一层是“摘要记忆”,基于每个会话自动生成摘要,存的是“这个会话聊了什么、解决了什么、定了什么决策”。第二层是“实体记忆”,从会话中提取名词性的关键实体,比如模块名、函数名、技术栈名称、文件路径,建立索引,方便后续检索定位。第三层是“偏好记忆”,会根据用户的使用习惯推断出偏好,比如你常用 Python 还是 TypeScript、习惯用测试框架还是直接跑脚本、对代码风格的偏好等。
这个分层的意义在于:不同粒度的记忆对应不同的检索需求。“摘要”回答的是“这个项目之前讨论到哪了”,“实体”回答的是“某某模块是什么”,“偏好”回答的是“这个人希望怎么干活”。三层记忆配合起来,才能让模型在新会话里呈现出“像同一个老同事在跟你协作”的连续感,而不是“每次见面的陌生人”。这种设计思路,比我一开始设想的“把所有聊天记录全存下来”要高明得多——全量存储只会把上下文撑爆,而分级之后模型拿到的永远是最有效的那部分。
2. 核心机制解析:Claude Code 插件如何被“唤醒”并读写记忆
2.1 依靠 SessionStart、Stop、UserPromptSubmit 三个生命周期钩子
claude-mem 不是通过修改 Claude Code 源码来实现记忆的,而是完全基于 Claude Code 的插件机制——hooks 系统。这决定了它的接入方式非常干净,升级 Claude Code 时也不会被破坏。
它的工作流分为三段。会话开始前,SessionStart 钩子会被触发,claude-mem 会从记忆库里检索与当前项目相关的记忆,拼装成上下文注入给 Claude Code,让它在第一时间“想起”这个项目。会话进行中,UserPromptSubmit 钩子会在用户每次提交消息时被命中,根据当前消息内容做一次“帮助记忆实时检索”,把与当前讨论最相关的历史记忆实时插入上下文,这解决了“会话开始了但逐步聊到另一块内容时,模型又忘了”的问题。会话结束后,Stop 钩子被触发,claude-mem 会把整个会话内容抓下来做摘要,提取实体,分析偏好,写入 SQLite 等待下次使用。
这三个钩子正好完整覆盖了“开始前恢复、过程中增强、结束后沉淀”的闭环,设计逻辑比我预想的成熟很多。我一开始以为这种记忆工具无非是“结束后存一下、开始时读一下”,加了 UserPromptSubmit 做实时检索之后,体验提升了一个档次——你在会话中期问到一个早期聊过的问题,模型能直接答上来,而不是一脸茫然。
2.2 记忆写入流程:从会话记录到结构化存储的加工管线
深入看 claude-mem 写入侧的实现,本质是一条“非结构化 -> 结构化”的加工管线。
Stop 钩子拿到的是 Claude Code 录制的完整会话 JSON,包含用户消息、模型回复、工具调用记录。claude-mem 先把这些内容按 token 长度分段,把过长的会话切成多个块,防止超过模型的上下文限制;然后把每个块交给 Claude 模型,让它压缩生成一段摘要;再把摘要进一步“降维”成实体列表和偏好列表,分别存入不同的数据表。
这里有个工程细节值得注意:摘要生成是有损压缩,如果摘要承载了太多信息,记忆质量反而会下降。claude-mem 的策略是“摘要只保存关键决策和结论,不保存细节过程”,具体代码内容、具体报错文本靠实体索引指向文件路径和行号即可。这与人类做会议纪要的逻辑如出一辙:记结论、记决策、记待办,而不是逐字记录谁说了什么。
写入后的数据并不保证完美。我遇到过某些会话的摘要生成得特别空洞,比如“讨论了代码结构”这种没有信息量的句子,原因往往是会话本身没有聊出实质内容,或者内容太过笼统,模型无法提炼出有价值的结论。这不是工具的 bug,而是输入质量决定的——你的会话越聚焦,沉淀的记忆就越有营养。
2.3 记忆读取流程:注入上下文的时机、格式与优先级
读取侧的设计决定了记忆“是否真的能帮到模型”。claude-mem 的做法是:在 SessionStart 时,根据当前工作目录(也就是项目路径)去匹配记忆库中同项目的记录,取出最近的相关记忆,格式化成“项目记忆注入块”,插入到系统提示词之后、用户消息之前的位置。
这个位置选择很关键。Claude Code 的上下文窗口内,位置靠前的内容对模型行为的影响更大,相当于“初始状态”。把项目记忆放在这个位置,等于是在模型“睁开眼睛”之前就告诉它:你在哪个项目里、这个项目之前干过什么、有哪些约定,比让它中途再读取要有效得多。
UserPromptSubmit 阶段的检索则使用当前用户输入作为查询条件,走 TF-IDF 相似度计算,从库里捞 Top-N 条相关记忆,插入到当前消息的上下文中。这里的相似度阈值设置得很保守,宁可不注入也不要注入无关信息,因为错误的记忆比没有记忆更容易误导模型。这个“宁缺毋滥”的取舍,我实测下来对防止记忆串味非常重要。
2.4 配置体系与作用域:全局配置、项目配置和记忆开关
claude-mem 的配置是分层的:一个全局配置文件负责默认行为,项目目录里可以放一个局部配置做覆盖。这种设计在同类工具里很常见,但 claude-mem 的配置项有几个值得单独说。
核心配置项包括记忆开关、摘要开关、MCP 开关、数据库路径、相似度阈值等。记忆总开关可以整体关闭;摘要开关控制是否要对每个会话做摘要,关掉后只存实体不存摘要,可以减少 token 消耗;数据库路径默认为~/.claude-mem/claude-mem.db,可以改成项目内路径,这样记忆与项目代码一起走;相似度阈值直接影响检索的精确度和召回率,调太高会漏掉有用记忆,调太低会频繁注入无关内容。
项目级配置的优先级高于全局配置,这个设计让不同项目可以拥有不同的记忆策略。比如个人项目想记录所有偏好,公司项目可能出于隐私考虑只开摘要不开偏好。这种灵活性在实际使用中很重要,因为“记忆”本身就是一种隐私敏感的数据,能按项目精细控制分享边界,用起来才安心。
3. 实操全程记录:从安装到让 Claude Code 拥有记忆
3.1 安装与前置检查:Node 环境、Claude Code 版本与初始激活
claude-mem 的安装非常轻量,核心依赖只有一个:Node.js 环境。如果你已经在用 Claude Code,说明本机基本具备条件。我用的是 v20 以上的 Node,安装过程没有遇到版本兼容问题。
需要先确认本机 Claude Code 的版本支持 hooks 机制。较老的版本可能不支持或行为有差异,安装前先跑claude --version确认一下,如果版本过低,先更新 Claude Code。这个前置检查很重要,因为 claude-mem 完全是靠 hooks 工作的,版本不达标时要么装不上、要么装上但静默失效,查起来会非常隐蔽。
安装步骤就两步。全局安装:
npm install -g claude-mem然后在你的项目目录下激活。激活过程本质上是把 claude-mem 的插件注册到当前项目的.claude配置里:
claude-mem init执行完之后,工具会提示你修改 Claude Code 的配置,把 hooks 注册进去。新版 Claude Code 支持自动写入配置,但保险起见还是打开配置文件检查一眼,确认hooks: { SessionStart: [...], Stop: [...], UserPromptSubmit: [...] }三个条目都存在。这一步如果漏了,后续所有记忆功能都不会生效,而且不会有任何报错提示——这是最容易踩的坑。
3.2 配置文件逐项说明:数据库位置、检索阈值与记忆范围
激活后,~/.claude-mem/config.json会生成一份默认配置。我用实际经验说明几个关键项的调整思路。
数据库路径默认在用户根目录下,所有项目的记忆会集中在同一个数据库文件中,通过“项目路径”字段做区分。如果你希望某个项目的记忆完全独立(比如涉及敏感代码或机密需求),可以把databasePath改成项目内路径,例如.claude/claude-mem.db。但要注意,改成项目内路径后,这个项目的记忆不会出现在全局检索里,其他工具的 MCP 查询也读不到,这是一种隔离换取便利的取舍。
相似度阈值默认值我建议先不动,用一段时间观察检索质量再调。阈值调高时,注入的记忆更精准但更少;调低时召回更多但噪声也更多。我个人经验是,在默认值基础上调高 0.05 左右,对“避免记忆串味”有比较明显的作用,尤其是电脑上同时开多个项目的时候。
还有一个容易被忽略的配置项是“忽略路径列表”。比如项目里的node_modules、vendor目录或者生成的临时文件,如果在会话过程中被大量讨论(多见于依赖调试场景),这些内容会被当作重要记忆存进去,后续检索时会频繁命中垃圾信息。在配置里把这类路径加进忽略列表,能显著提升记忆库的“信噪比”。
3.3 MCP 服务器模式:把记忆能力接入更多 AI 客户端
claude-mem 在 2025 年之后新增了不少能力,其中一个重要的演进是支持 MCP(Model Context Protocol)服务器模式。装好之后多了一条命令:
claude-mem mcp这会启动一个 MCP 服务器,让任何支持 MCP 协议的 AI 客户端都能访问 claude-mem 的记忆库。也就是说,不只是 Claude Code 能使用记忆,Claude Desktop、Cursor、其他支持 MCP 的编辑器或工具,都能通过 MCP 接口读取同一套记忆数据。
这个设计让 claude-mem 从“Claude Code 专用插件”升级成了“通用记忆服务层”。我实际把 MCP 接入了 Cursor 后,两边共用一套记忆库,在 Cursor 里做代码审查时也能调出 Claude Code 会话里沉淀的架构决策,体验非常顺滑。MCP 模式的配置方式在各客户端里略有差异,但原理一致:在客户端的 MCP 配置里加一条命令类型为claude-mem mcp的服务。
MCP 模式还有一个用途,就是可以用外部脚本直接查询记忆库,做记忆的导出、审计、备份,这比直接操作 SQLite 要安全得多,因为 MCP 接口做了一层权限控制。
3.4 效果实测:跨会话上下文恢复的质量与速度
安装配置完成后,我做了个简单的效果验证。在项目里先开一个会话,故意讨论一个具体的决策:“决定把订单模块的状态机从 if/else 重构为 XState,让超时和取消走同一个事件”。会话结束后,第二天新开会话,问 Claude Code:“订单模块状态管理现在是什么方案?”它直接答出了 XState 和事件驱动,并且主动补充了“超时和取消共用事件”这个细节。
这是很直观的效果。而在没有记忆的情况下,它给出的答案大概率是“搜索代码后建议考虑引入状态机库”——不是它变聪明了,而是它“记得”昨天的讨论了。
速度方面,SessionStart 阶段的记忆检索开销在几百毫秒以内,体感上是“开一个新会话不会觉得比原来慢”。UserPromptSubmit 的实时检索也几乎无感。SQLite 本地存储的优势在这里体现得很明显,不用走网络请求,也不依赖外部服务。
记忆库的体积增长也比较可控。我连续用了一个多月,中等规模的项目,会话摘要和实体数据加起来大概十几 MB。相比向量数据库动辄几十 GB 的存储消耗,这个量级完全可以接受。
4. 常见问题与排查技巧实录:记忆不生效、串味、损坏的解决路径
4.1 记忆完全没生效:从配置到触发条件的逐层检查
最常见的反馈是“我装了但感觉它什么都没做”。这种情况优先排查三个点。
第一,确认 hooks 是否真的注册成功了。打开项目下的.claude相关配置文件,看三个钩子是否齐全。我见过配置写错缩进导致 yaml 解析失败的情况,工具不报错但 hook 形同虚设。第二,确认是否触发了会话归档。claude-mem 是在会话结束时写记忆的,如果你每次用完都直接关终端,Stop 钩子确实未必能正常触发。建议用/exit正常退出 Claude Code,或者确认有会话历史被写入。第三,确认 SessionStart 注入是否真的进入了上下文。可以开一个会话,让 Claude Code 描述“根据我的记忆库,告诉我这个项目之前在做什么”,如果它答不上来,大概率是注入失败,需要回去看配置。
这里的排查思路是逐层验证:配置层、触发层、效果层。网上很多“装了没用”的案例,最后都定位在第一步或第二步。
4.2 记忆串味:不同项目的记忆“互串”怎么处理
我实际遇到的最烦人的问题之一,是记忆串味。现象是:在 A 项目开会话,模型突然提到了 B 项目里的某个变量名或设计决策,显然是从记忆库里捡到了不相关内容。
原因通常有三个:多项目共用同一个全局记忆库,检索时相似度计算把不同项目的记录也捞了出来;项目路径的匹配逻辑在有嵌套目录时可能误判,比如同时有/project和/project-old,路径前缀相似会导致串味;或者在UserPromptSubmit的相似度检索阶段,阈值设置得太低,把不相关的记忆也注入了。
排查方法是先查数据库里的记录归属:/查询数据库看每条记录对应的projectPath是否准确。如果记录本身归属错了,那是写入阶段的问题;如果记录归属正确但检索时被捞出来,那就是读取阶段的阈值问题。前者可以手动修正数据库中的项目路径,后者则需要调高相似度阈值。
从根源上解决,最好的方案是每个项目用独立的数据库文件,项目路径和数据库路径一一对应。虽然管理上略麻烦,但从源头杜绝了串味的可能。我个人现在是“核心项目独立库、边角项目共用库”的策略。
4.3 记忆质量差:摘要空洞、实体不全的应对策略
另一个常见问题是记忆写了,但质量不高。比如摘要内容全是“讨论了某些功能”“进行了一些修改”这类正确的废话,或者实体列表里只有几个孤零零的路径,完全没有可检索性。
这种现象的本质是:Claude Code 的会话内容本身缺乏高密度信息。如果整个会话都在做依赖安装、环境调试这类机械性操作,生成的摘要当然空洞。这不完全是 claude-mem 的问题,而是输入端的信息熵太低。
改善方法有两个方向。一是提升会话质量:在会话中尽量用明确的语言描述问题和决策,避免使用“这个”“那个”之类含混的指代,决策型对话要有明确的结论句。二是手动干预:claude-mem 允许手动触发摘要生成,可以用命令行强制对某段历史对话重新总结,或者直接在数据库里编辑某条记忆。前者更常用,后者适合已经生成但质量特别差的记录。
4.4 数据库维护:备份、清理与手动编辑
SQLite 数据库虽然稳定,但还是建议养成定期备份的习惯。我的方案是写了一个简单的定时任务,每周把~/.claude-mem/claude-mem.db复制到项目的外部备份盘里。因为记忆库一旦损坏,里面的历史积累都归零,而那恰恰是 claude-mem 最值钱的部分。
记忆库的体积会随着使用时间增加而增长,虽然速度不快,但最好半年左右清理一次。清理策略是删除“超过三个月且从未被命中”的旧记录,保留近期的活跃记忆。可以用外部的 SQL 语句直接操作数据库,但操作前务必备份。
我踩过一次比较深的坑:手动删数据库里的表之后没有执行 VACUUM,导致磁盘上的数据库文件没有变小。后来用VACUUM命令压缩了一遍才恢复正常。如果你也要手动编辑 SQLite,记得删完数据跑一次VACUUM。
4.5 针对中文场景的经验补遗:中文记忆效果优化
claude-mem 的检索算法基于 TF-IDF,而 TF-IDF 的分词对中文并不是特别友好。英文天然按空格分词,中文没有空格,“状态机”会被当作一个词处理,相关检索时有偏差。
实际使用中我发现,中文记忆的检索效果通常比英文差一些。改善的办法是:在配置时尽量用英文缩写或拼音做项目标识;在会话中讨论技术概念时,中英文混着用,比如“状态机改成 XState”,比纯中文“改成状态机库”更容易被准确检索。这个方法有点投机,但确实有效。
5. 由 claude-mem 延伸:AI 编程工具的记忆层设计趋势
5.1 从“重新开始”到“接着干”:记忆是 AI 编程助手的下一站
顺着 claude-mem 的思路往外看,会发现整个 AI 编程工具的演进方向已经出现了一个明显的趋势:从“单次会话能力竞赛”转向“跨会话连续工作能力竞赛”。
过去一年,各家比较的核心指标是单次会话里能处理多复杂的任务——一次性能修多少 bug、能重构多少个文件。但真实开发是马拉松而非百米冲刺,单个会话能力再强,会话之间的断裂依然会打断工作流。claude-mem 用插件的形式补上了这个缺口,它没有改动 Claude Code 本身,但把它从“无状态终端”升级成了“有状态协作者”。
这个思路已经影响到了 Claude Code 自身的产品方向。后续版本中 Claude Code 本身也加入了记忆相关的能力,但 claude-mem 作为先行者仍然有价值:它的实现是透明且可控的,你随时能查它记住了什么,也能手动调整记忆内容,而不是依赖一个黑盒。
5.2 记忆的隐私边界:本地存储与可审计性是底线
任何做记忆的工具都要面对隐私问题。claude-mem 选择把数据完全落在本地 SQLite,不与云端同步,这个设计在隐私层面是加分的。
另外,claude-mem 支持对记忆进行审计和修改。我可以随时翻开数据库看它记住的实体和偏好,删掉我不希望被记录的敏感信息,比如某个内部服务的地址、某个密钥的名字。这种可审计性是记忆类工具的必要属性。如果一个工具的记忆是黑盒、用户不知道它记了什么,那即使再方便我也不敢在生产环境用。
对已经在用 claude-mem 的团队,我建议把记忆库的备份纳入团队资产管理,定期审计,尤其是涉及敏感代码库的项目。
5.3 还有哪些可改进的方向
claude-mem 本身已经很好用,但它依然有值得想象的空间。记忆的检索目前是基于 TF-IDF 的词汇匹配,如果未来引入轻量的语义 embedding 模型(比如本地跑的all-MiniLM-L6-v2),对中文和同义表达的理解会质的飞跃。记忆的“时间衰减”目前还不算完善,旧记忆的权重和新记忆没有明显区分,在长期项目中“几个月前的架构决策可能已经废弃”这种场景下,时间权重会很重要。如果它能根据代码库的实际变更去做记忆失效检测,记忆库的长期准确率会高很多。
这些都是“如果”,但正因为有这些想象空间,claude-mem 这个项目才不仅仅是“一个好用的工具”,更是一个值得持续关注的设计样本。
6. 我的个人使用心得与一套推荐配置
6.1 一些使用上摸出来的习惯
用了 claude-mem 一段时间,我对它的定位已经不只是“记忆插件”,而是一个轻量的个人项目知识管理系统。现在我每次开会话前,会习惯性地在提问里带上具体模块名和文件路径,因为这样不仅让 Claude Code 更准确,也会让 claude-mem 检索到更相关的历史记录。
收尾时我会刻意做一句概括,比如“结论是先用方案 A,替代原来的方案 B,原因分别是性能和可维护性”。这样一句话,往往能让 claude-mem 生成的摘要质量高很多,因为它给了模型一个清晰的“结论点”。如果会话草草结束,摘要往往也草草了事。
给两个项目分别建独立记忆库之后,我基本不再担心记忆串味,唯一要注意的是别把项目路径配成包含关系。另外,我在每次大版本升级工具后,都会跑一条命令检查 hooks 配置是否还在,因为升级偶尔会覆盖配置,记忆功能会在不知不觉中失效。
6.2 一套开箱即用的配置模板
这里给一份我目前在不同场景下验证过的配置结构,你可以直接照着改成自己的场景。
全局配置~/.claude-mem/config.json:
{ "databasePath": "~/.claude-mem/claude-mem.db", "memoryEnabled": true, "summaryEnabled": true, "entityExtraction": true, "preferenceLearning": true, "similarityThreshold": 0.52, "sessionEndTimeoutSeconds": 300, "ignoredPaths": ["node_modules", "vendor", ".git", "dist", "build"] }这些配置不需要全量照抄,重点看similarityThreshold和ignoredPaths。阈值 0.52 比默认值略高,适合同时维护多个项目、对记忆精准度要求比较高的场景。如果你发现召回不够,把它降回默认值附近就行。
而sessionEndTimeoutSeconds这个参数,控制的是会话结束后多长窗口内允许写入记忆。默认值够用,但如果你经常用Ctrl+C强行终止或者合上笔记本就退出,这个值可以适当加大,给 Stop 钩子留足触发时间。
项目级配置项目目录/.claude-mem/config.json:
{ "databasePath": ".claude/claude-mem.db", "memoryEnabled": true, "summaryEnabled": true, "ignoredPaths": ["docs/generated", "coverage", ".cache"] }当项目配置存在时,它完全覆盖全局配置,不会做嵌套合并。所以缺省字段全都要写全,否则那些能力会被默认值接管,行为可能不符合预期。
6.3 如果你遇到了记忆库文件异常
最后补一个 SQLite 文件异常时的处置经验。如果启动时提示数据库损坏,先把文件复制一份备份,然后用sqlite3执行PRAGMA integrity_check看看完整性。大多数情况下是写入过程中断电导致的 WAL 文件未合并,可以直接删掉-wal和-shm文件重启工具。如果完整性检查真的发现大量错误,那就只能从备份恢复了——这也是我前面反复强调定期备份的原因。
我自己的实际操作中,记忆库异常只遇见过一次,就是在虚拟机里频繁快照回滚导致的文件残留,删掉 WAL 后就恢复了。日常使用中 SQLite 的表现非常稳定,这也是我敢把全部记忆都押在单文件数据库上的底气。