今天是我这个系列的第63天。熟悉这套连载的朋友都知道,我每天都会往一个“个人记录工具”里塞一点东西:一段踩坑笔记、一段可复用的代码、偶尔是产品思考。今天正好到了第63天,我不想再急着加新功能了,而是把这62天攒下的东西做一次结构性整理。结果这一整理,反而比之前连续加功能更有收获。
如果你也在做类似的每日打卡、长期记录、个人项目,或者在犹豫“要不要每天逼自己写点东西”,这篇就当我的心路历程加实操笔记看。我不会只讲“要坚持”这种正确的废话,而是把这63天里真正踩过的坑、摸索出来的工作流、以及今天做整合时用到的具体方法,全部摊开写出来。适合正在做长期记录、维护个人知识库、或者想把自己的零散输出变成可复用资产的人参考。
1. 当时定下的目标和前62天做了什么
1.1 这个系列是怎么开始的
第1天的时候,我的目标其实特别朴素:给自己做一个“不会丢”的记录系统。当时受够了散落在备忘录、聊天记录和自己的大脑里的碎片信息,所以决定搭一个本地优先的小工具,每天至少往里面写一条有效内容。规则只有三条:第一条,内容必须有可检索性,不能写完就沉底;第二条,必须能追溯上下文,任何一条记录都能看到是哪天、为什么记的;第三条,格式尽量统一,这样后续好做统计和分析。
这个项目没有用什么重型框架,核心就是一个 Python 脚本加 SQLite 数据库,界面我甚至都没单独做,直接用命令行和 Markdown 文件交互。一开始很多人问我“这跟直接用 Typora 或 Notion 有什么区别”,区别其实不在工具本身,而在流程:Notion 适合写,但不太适合做长期的数据归因;而我想的是一个可以跑统计、可以自定义检索、可以导出备份的记录库,所以必须能直接操作数据文件。定下目标后,从第1天到第20天,我主要在打地基:建表、写录入脚本、设计标签体系。
1.2 前62天的完成情况与里程碑
前62天大致分成了三个自然阶段。第1到20天是“地基期”,核心任务是让记录工具能跑通。我建了记录表、标签表、温故表,写了一个最简版本的命令行录入器,能接受日期、标签、正文、参考链接四个字段。第21到40天是“习惯期”,重点从工具转变成了内容。我开始把每天遇到的实际问题写进去,比如某个软件包的版本坑、某个 API 的返回值格式、某篇文章的要点摘录,这个阶段内容量涨得特别快,但也暴露出一个问题:标签体系开始失控。
第41到62天是“爆发与混乱期”。有一次我把一条长笔记拆成了三条,忘记加关联字段;还有一次我用了几种不同的日期格式,导致后面统计脚本直接报错。到第62天晚上,我清点了一下数据:有效记录 58 条,总字数约 4.2 万,标签 73 个,但其中至少有 20 个标签是重复或近义的。数据量大了之后,继续用蛮力堆叠已经不行了。第63天,也就是今天,我决定做一次阶段性整合。整合的目标不是加功能,而是把数据质量提上去,给下一个阶段铺好路。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 第63天的核心任务:阶段性整合而非堆新功能
2.1 为什么第63天选择“做减法和整合”
连续写了两个月,最容易产生的冲动是再加一个功能:加个日历视图、加个统计报表、加个多端同步。但我的判断是,现在最缺的不是功能,而是数据的一致性。举个很直观的例子:我统计过 73 个标签里,“bug”“踩坑”“报错”三个标签指向的内容高度重叠,但因为我每天录入时心情不同,同一个类别的记录被分到了三个地方。这种情况如果不做合并,后面想按主题检索就一定会漏。
另一个理由是,第63天正好是一个中间节点。前62天是试运行,内容、格式、使用频率全都在跳动;现在数据量到了一个可以用统计手段分析的量级,做一次清洗和重构,性价比最高。如果拖到第100天,可能就得清理几百条记录了。整合的总体思路是:先建脏数据清单,再逐个字段做规范化,最后统一调整结构。我给自己定的原则是“不动内容,只动结构”,也就是说每条记录的核心观点和正文完全保留,改的只是标签、日期格式、关联关系这些元数据。
做减法还有一个隐藏的好处:你会发现有些记录其实根本不需要。第63天我标记了 3 条“幽灵记录”,内容是当时觉得重要、现在看已经完全过时的临时信息。我没有直接删,而是加了一个 status 字段标记为 archived,保留数据但不再进入统计。这种做法比直接物理删除安全,万一将来想找回,还有后悔药。
2.2 技术选型复盘:本地文件 + SQLite 的取舍
这回整合让我重新审视了一遍当初的技术选型。我的存储方案是两层:一是原始 Markdown 文件,文件名是日期加时间戳;二是 SQLite 数据库,存元数据和索引。之所以不直接只存数据库,是因为 Markdown 文件是“人可读”的,即使哪一天数据库坏了,只要文件在,数据就在。SQLite 则负责提供检索能力,毕竟 Markdown 文件多了之后,靠 grep 和文件名检索效率太低了。
数据库结构我设计得比较简单,核心表是记录表(上方),字段有 id、record_date、tags、content_path、content_excerpt、status、created_at。记录表与文件的关联靠 content_path,正文全文放在 Markdown 文件里,不直接塞进数据库。这样做的好处是减少了数据库膨胀,同时也保证了正文可以用任何文本编辑器直接打开查看。
这次整合过程中,我验证了一个选型判断:把正文留在文件里、把索引留在数据库里的“双轨制”,在数据量只有几十条时显得多余,但到了几百条、上千条时优势会越来越明显。数据库只管查询,文件系统管存储,两个层面的职责完全分离。如果你也想做类似的东西,建议一开始就采用这种结构,后面重构成本会低很多。
2.3 从“能跑”到“好用”的关键补强
趁整合的机会,我补了两个之前一直想做但拖着的功能:全文搜索和批量导出。全文搜索我用的是 SQLite 自带的 FTS5 扩展。之前我也有搜索能力,但用的是 LIKE '%关键词%',写法简单但效率感人,而且不支持中文分词,搜“笔记”会把“秘密记下”之类的也拽出来,噪音很大。换上 FTS5 之后,配合 unicode61 分词器,虽然中文支持不算完美,但日常检索已经够用了。
批量导出的需求其实来自一次教训。有一回我误操作把整个目录挪了位置,导致几十条记录的 content_path 全部失效。虽然最后靠备份找回来了,但那次之后我意识到,记录系统里“逃生出口”比“入口”更重要。于是这次我写了一个 export.py 脚本,可以把指定日期范围内的记录导出为一个压缩包,里面包含全部 Markdown 文件和一份 metadata 汇总表,这样就算整个目录结构动了,也能根据 metadata 重建索引。
导出脚本不复杂,但有一个细节值得提:导出的 metadata 表用的是 CSV 格式,字段顺序固定,第一行是列名。这样设计是为了兼容性,因为 CSV 是几乎所有数据处理工具都能读的格式,以后想从记录工具迁移到别的系统,就不用再写一次专门适配的脚本了。这个思路我认为对任何在维护个人记录库的人都有参考价值:数据的所有权,永远要留给自己。
3. 一天内的实操流程记录
3.1 早上:先整理过去62天的问题清单
第63天的实操,我是从整理问题清单开始的。早晨我先花了大概40分钟,把前62天记录里的报错信息、待办标记、标注了“待补充”的内容全部捞出来,做了一个问题分类。分类标准有三个:与数据格式相关、与检索体验相关、与内容质量相关。这一步很关键,因为如果直接上来就改代码,很容易修了一个细节、忘了一个更大的结构性问题。
整理出来后,问题比我想象的集中。格式相关的问题最多,占比超过一半,主要集中表现在日期格式不统一、标签分割符号混用、个别记录有空行导致解析失败。检索体验的问题集中在搜索结果噪音大、标签近义词没合并。内容质量的问题则主要是那几条“幽灵记录”和一条只有标题没有正文的空记录。我把这些问题按优先级排了一下,决定先花整块时间解决格式规范化,因为这是大部分问题的根源。
在整理过程中我用了一个很土但很有效的办法:把所有记录文件放到一个临时目录里,用脚本扫描每个文件的元信息头,输出一个 CSV 汇总表。然后我直接在这个 CSV 里做标注,哪里日期格式不对,哪条记录标签为空,一目了然。这个“数据体检”的过程虽然花时间,但后面所有操作都有了依据,完全不是白费功夫。
3.2 下午:实现全文搜索和导出功能
下午的时间主要给了两个功能的实现。先是 FTS5 全文搜索。我在数据库里新建了一个虚拟表,字段包含 record_date、tags 和 content_excerpt,然后从 Markdown 文件里读取正文前500字作为摘要保存进来。建索引的 SQL 大概长这样:
sql复制CREATE VIRTUAL TABLE records_fts USING fts5(
title,
tags,
excerpt,
content='records',
content_rowid='id'
);
这里用到了 FTS5 的 contentless 或 external content 表特性,好处是虚拟表只存索引、不存重复的正文副本,数据源头依然是原表,避免了两份数据不一致的问题。索引建好后,搜索词命中后拿到的是一组 rowid,再去原表 join 查询完整元数据。
比较意外的是中文搜索时 FTS5 的问题。默认 unicode61 会把中文按单个汉字切分,搜“笔记”没问题,但搜“知识管理”会被切成“知识”和“管理”两个词,相关性排序不够理想。我临时用了一个不算特别优雅但有效的办法:在导入 excerpt 时把中文内容按常用词词典做了一次简单的正向最大匹配分词,用空格把词分开再存进去。这样搜索精度提升了不少。如果你也在用 FTS5 做中文搜索,这个思路可以借鉴,但如果词库没空维护,其实默认行为也勉强能用。
导出功能我写了大概80行 Python,逻辑不复杂:遍历指定日期范围的文件,复制到一个临时目录,同时把 metadata 导出成 CSV,最后打成一个带日期的 zip 包。唯一处理得小心的是文件名冲突的问题——早期我有一天写了两条记录,文件名都叫 2025-03-10.md,后一条覆盖了前一条。虽然正文没丢,但导出的文件名必须避免这个问题,所以我统一加上时间戳后缀。
3.3 晚上:回归测试与数据备份
晚上我留了将近两个小时做回归测试和备份。回归测试的核心目标只有一个:数据规范化之后,原来的查询、统计、导出脚本还能不能正常跑。我跑了三个场景:按标签查寻、按日期范围统计数量、导出指定时间段的数据。结果发现一个隐患:有一个统计脚本假设标签字段是逗号分隔,但我早期录入时用的是中文逗号,导致解析结果被切断。顺着这个线索,我把所有历史数据重新扫了一遍,发现一共 5 条记录存在类似的分隔符不一致问题,全部修掉了。
备份这个动作,今天做得比以往更谨慎。因为今天改动了数据库结构、更新了大量元数据,一旦出错,影响的不只是一条记录,而是整个记录库的完整性。我按照“三份备份”原则操作:第一份是完整目录压缩包,存本地移动硬盘;第二份是昨天的数据库文件快照,单独复制出来;第三份是 metadata 的 CSV 导出,放进了一个加密的压缩文件。整个备份过程大概耗时 15 分钟,做完之后心里才有底。
这里必须说一句:很多个人记录项目都是毁在“懒得备份”。别写到第60多天了才意识到备份重要,最好第1天就养成习惯。我现在的流程是每次大改动前强制备份一次,每次项目阶段性收官再额外做一个时间点快照,双保险。
4. 这63天踩过的坑和排查经验
4.1 编码与中文内容处理
第一个大坑是中文编码。第10天左右,我发现搜索“记录”会搜出一堆无关结果,排查了很久,最后发现是 Python 打开文件时默认用了系统编码,而部分文件是 UTF-8 带 BOM,导致字符串首字符多了一个不可见字符,索引内容全偏了。从那以后,我所有的文件读写统一显式指定 encoding='utf-8-sig',无论是写入还是读取,都在代码里写死,绝不在运行时依赖默认值。
如果你用 Python 处理中文 Markdown 文件,我强烈建议从一开始就把编码标准化。一个比编码更隐蔽的问题是换行符,Windows 上保存文件可能带 \r\n,在 Linux 下用脚本解析时如果没处理,会出现多余的 \r,导致 tag 分割时字符串多了个隐藏符号。我这次规范化的过程中,就把所有文件的换行符统一转换成了 \n。
4.2 SQLite 写入锁与并发问题
第二个值得写出来的是 SQLite 写入锁的问题。第35天我写了一个自动扫描脚本,想在后台持续监控某个目录并自动更新数据库,结果发现只要这个脚本持有写入事务,命令行的手动录入就会报 database is locked。SQLite 其实支持并发读,但写操作是串行的,多进程同时写就会撞车。
我的解决方案有三层:第一层是应用层做写入串行化,所有写操作都走同一个入口模块,相当于一个简化的“写锁单例”;第二层是给 SQLite 连接设置 busy_timeout,让写操作遇到锁时等待一段时间而不是立刻失败;第三层是尽量避免长时间事务,每条记录插入后立刻 commit。这套组合下来,到目前为止再没出现过锁冲突。
如果你也在用 SQLite 做个人项目的存储,这个经验大概率能帮你少走弯路。另外一定要记住:SQLite 是嵌入式数据库,不是为高并发写入设计的,它适合个人工具、低并发场景,千万别强行拿它当服务器数据库用。
4.3 记录习惯本身的中断与恢复
技术坑说完了,再说一个更隐蔽的坑:记录习惯的中断。第16天到第19天,我连续三天一条内容都没写。原因不是没东西可写,而是那几天我正好出差,每天回到酒店都懒得开电脑。三天之后,重新打开编辑器的时候,我有一种强烈的“不知道从哪里续上”的感觉,差点就放弃整个系列。
我后来是怎么恢复的?方法其实很简单:允许“低强度记录”。不要求每天必须写一篇长篇心得,当天实在没东西写,就写三行字,描述今天解决了什么问题,哪怕只有“今天没遇到新问题,把昨天的XX重新梳理了一遍”这句话也算记录。这个“写下最低限度的上下文”原则,直接让我的连续记录再没断过。
第63天回看,这个原则比任何技术方案都重要。长期记录的天敌不是“没时间”,而是“完美主义”。你会觉得今天写得不够好,于是不想写,结果一断就是更久。给自己留一个“低能耗模式”,是维持习惯的核心技巧。实际上,这套系列能连续走到第63天,靠的就是这个。
4.4 常见问题速查表
我把这63天里遇到的高频问题整理成一个速查表,方便你直接对照排查。这张表不仅是技术操作参考,也是内容运营层面的提醒,别像我一样等出了问题才去翻记录。
| 现象 | 可能原因 | 快速解决 |
|---|---|---|
| 搜索中文结果不准确 | FTS5默认按单字切分 | 分词后导入索引,或接受单字匹配 |
| 文件读取乱码 | 编码未统一 | 全部改为 UTF-8,读取时显式指定编码 |
| 数据库提示 locked | 多进程同时写 | 设置 busy_timeout,写操作串行化 |
| 文件名重复导致覆盖 | 文件名只有日期 | 文件名加时间戳或随机后缀 |
| 标签统计不准确 | 分隔符混用 | 统一使用英文逗号,并做数据清洗 |
| 记录中断好几天 | 疲劳或完美主义 | 启用低强度记录模式,每天至少三行 |
| 日期格式混乱 | 录入习惯变化 | 统一为 YYYY-MM-DD,脚本反复校验 |
| 导出缺漏文件 | 目录结构变化 | 导出 metadata 汇总表,重建索引 |
这张表的每一条我都在真实环境中触发过,里面至少有一半是可以从源头上避免的。个人项目的特点就是自由度高,但自由度的代价是,规范和约束必须自己给自己定。早一天建立数据规范,就少一堆后面返工的麻烦。
5. 怎么把“day N”这件事坚持下去
5.1 降低每天开始的成本
63天走下来,我认为长期记录能不能坚持,核心不在意志力,而在“开始的成本”。如果每次记录都要打开文章编辑器、重新排版、决定标题、想开头,那大概率坚持不了太久。我的做法是准备了一个极简模板文件,包括几个固定的小节字段:今天处理的问题、结论或收获、下一步动作、相关标签。每天只需要填这几个字段,10分钟内就能完成一次记录。
另一个降低成本的办法是“随时捕获”。我在手机上一有灵感,就先往一个临时收件箱里扔一句话,然后晚上统一整理进记录库。这个习惯能避免“晚上想记却想不起白天遇到了什么”的尴尬。所谓开始成本最低,就是让捕获的动作快过遗忘的速度。
5.2 给未来的自己留足上下文
写记录时我会问自己一个问题:三个月后的我,看到这条记录能直接看懂吗?如果答案是犹豫的,那就当场补充上下文。这比“记得多写一点”要具体得多。比如我不只写“今天改了一个 bug”,还会补上项目背景、报错的关键日志、解决思路和验证结果。这些上下文就是未来检索时的索引锚点。
很多人做记录追求“写得少而精”,但如果没有上下文支撑,少而精很容易变成“少而不可用”。我的经验是:记录最重要的是可复用性,不是简洁性。删减内容是编辑阶段的事,采集阶段宁可写全一点,也别为了排版好看丢了关键细节。
5.3 阶段性复盘比闷头执行更重要
这次第63天的整合,让我对“复盘频率”有了新的认知。日复盘的作用是纠偏,周复盘的作用是清理,月度或季度复盘的作用是系统性重构。只闷头执行不复盘,数据会越来越乱;只复盘不执行,则会变成空谈。我的建议是,至少在每个约定的里程碑节点(比如第7天、第30天、第60天)做一次完整的数据体检。
你可能没有像我一样写满63天,但如果你想开始做这件事,从今天开始并不晚。不需要等一个完美的日子,不用等到某个月1号。现在就建一个文件夹,打开文本编辑器,写下第一条记录。63天后,你也会站在一个属于自己的节点上,回看这段积累,会有一种特别踏实的感觉。这大概是所有长期记录类项目里,最不容易被量化但最有价值的回报。
