资讯动态

Karakeep 数据库迁移实战指南:从 Schema 定义到 Drizzle 迁移工作流

发布时间:2026/9/11 10:42:44 来源:尧图企业网站定制
Karakeep 数据库迁移实战指南从 Schema 定义到 Drizzle 迁移工作流【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder本文聚焦 Karakeep原 Hoarder自托管书签应用的数据库层围绕官方开发文档中定义的Schema 变更 → 生成迁移 → 应用迁移完整工作流展开。读者将掌握如何修改packages/db/schema.ts中的表结构、用一条命令生成 Drizzle 迁移、在应用启动或手动执行时应用迁移以及如何使用 Drizzle Studio 可视化检查 SQLite 数据库。全文以仓库内的真实源码与迁移记录为依据帮助你在本地开发或二次开发时安全、可复现地演进数据库结构。数据库在 Karakeep 架构中的位置Karakeep 是一个书签一切链接、笔记、图片的自托管应用其所有业务数据——用户、书签、标签、列表、AI 摘要、RSS 订阅、备份任务等——都持久化在 SQLite 数据库中。数据库相关代码集中收拢在仓库的packages/db包中schema.ts全部表的 TypeScript 定义约 1300 行是数据模型的唯一事实来源drizzle/Drizzle Kit 生成的增量 SQL 迁移文件与元数据drizzle.config.tsDrizzle Kit 的配置方言、Schema 路径、输出目录drizzle.ts运行时数据库连接与 Drizzle ORM 实例migrate.ts迁移应用入口sqlite.ts底层 better-sqlite3 连接的打开与 PRAGMA 设置。官方开发文档 03-database.md 给出的核心工作流只有四步改 Schema →db:generate→db:migrate→可选db:studio。本文接下来将逐一深入这四步并补充源码级细节。第一步修改 Schema——packages/db/schema.ts数据库的一切变更都从 schema.ts 开始。该文件使用 Drizzle ORM 的sqliteTable()声明式定义表结构当前已包含 30 余张表覆盖 Karakeep 的全部业务域业务域表导出常量名职责认证与账户users、accounts、sessions、verificationTokens、passwordResetTokens、apiKeys用户、OAuth 账户、会话、密码重置、API Key含 scope 与 lastUsed 追踪书签核心bookmarks、bookmarkLinks、assets、bookmarkTexts、bookmarkAssets书签本体、链接元数据、附件资源、全文文本、资源与书签关联标注与阅读highlights、userReadingProgress高亮、阅读进度标签与列表bookmarkTags、tagsOnBookmarks、bookmarkLists、bookmarksInLists、listCollaborators、listInvitations标签规范化、书签-标签多对多、列表、列表协作与邀请自动化customPrompts、ruleEngineRulesTable、ruleEngineActionsTable自定义 AI 提示词、规则引擎含多列表支持集成rssFeedsTable、rssFeedImportsTable、webhooksTableRSS 订阅、导入会话、WebhookAI 对话chatSessions、chatMessages对话式交互系统管理backupsTable、config、invites、subscriptions、importSessions、importSessionBookmarks、importStagingBookmarks备份、键值配置、邀请码、订阅、导入流水线从源码可以看出 Schema 层的几个设计惯例主键统一使用 CUID2而非自增 ID。例如users表的id字段id: text(id) .notNull() .primaryKey() .$defaultFn(() createId()),createId来自paralleldrive/cuid2保证分布式环境下无需中心化自增即可生成全局唯一主键。时间戳字段有统一的辅助函数schema.tsfunction createdAtField(colName createdAt) { return integer(colName, { mode: timestamp }) .notNull() .$defaultFn(() new Date()); } function modifiedAtField() { return integer(modifiedAt, { mode: timestamp }) .$defaultFn(() new Date()) .$onUpdate(() new Date()); }其中modifiedAtField同时注册了$onUpdate意味着每次记录更新时自动刷新时间戳业务代码无需手动维护。此外还存在毫秒精度的createdAtMsField/modifiedAtMsField变体供对时间精度要求更高的表使用。枚举值以内联enum声明如用户的roleadmin/user、backupsFrequencydaily/weekly、tagStyle七种标签风格默认titlecase-spaces等Drizzle 会在 SQL 层用 CHECK 约束保证数据合法性。修改或新增表后不要手动去编辑 SQL——Drizzle 会基于 Schema 与已应用迁移的差异自动生成迁移脚本。第二步生成迁移——pnpm run db:generate在仓库根目录执行官方文档指定的命令pnpm run db:generate --name description_of_schema_change--name参数用于给本次 Schema 变更一个人类可读的描述如add_bookmark_quota该描述会体现在生成的迁移文件名中。这条命令在根 package.json 中被映射为db:generate: pnpm --filter karakeep/db run generate最终落到 packages/db/package.json 中的generate: drizzle-kit generate即调用 Drizzle Kit 的生成器。Drizzle Kit 依据 drizzle.config.ts 工作其关键配置如下export default { dialect: sqlite, schema: ./schema.ts, out: ./drizzle, dbCredentials: { url: databaseURL, }, } satisfies Config;dialect: sqliteKarakeep 的数据层方言为 SQLite全部迁移均生成 SQLite 兼容 SQLschema指向schema.ts即上一步修改的 Schema 文件out指向drizzle/目录生成的迁移 SQL 与快照元数据存放于此dbCredentials.url来自共享服务端配置serverConfig.dataDir若配置了数据目录则数据库文件为${serverConfig.dataDir}/db.db否则回退到仓库根目录下的./db.db。生成的迁移文件命名形如0044_add_password_salt.sql、0073_ai_tag_style.sql按序号递增。仓库当前的 drizzle/ 目录中已积累从0000_luxuriant_johnny_blaze.sql到0093_reader_view_assessment.sql的近百个增量迁移完整记录了项目从首个 Schema 至今的演进历史——包括密码加盐、规则引擎、RSS 订阅开关、用户设置合并、协作列表、存储配额、AI 偏好等里程碑变更。每份迁移文件旁边还有meta/目录保存 Drizzle 的快照元数据用于 diff 对比。第三步应用迁移——pnpm run db:migrate生成迁移脚本后在仓库根目录执行pnpm run db:migrate该命令同样经由根 package.json 的db:migrate: pnpm --filter karakeep/db run migrate转发到 packages/db/package.json 的migrate: tsx migrate.ts最终执行 migrate.tsimport { migrate } from drizzle-orm/better-sqlite3/migrator; import serverConfig from karakeep/shared/config; import { db } from ./drizzle; if (serverConfig.degradedMode) { console.log(Skipping database migrations in degraded mode); } else { migrate(db, { migrationsFolder: ./drizzle }); }几个值得注意的实现细节迁移是幂等且可重复的Drizzle 的migrate()会读取./drizzle目录下的全部迁移文件并与数据库内置的迁移记录表比对只应用尚未执行过的增量。因此重复运行pnpm run db:migrate是安全的不会重复执行旧迁移。降级模式degradedMode下自动跳过迁移当服务以降级模式启动时迁移不会执行见 migrate.ts同时在 drizzle.ts 中数据库会以只读方式打开——这是为生产环境中只读副实例或只读部署场景设计的保护机制避免多实例并发迁移导致竞争。数据库连接本身由 drizzle.ts 中的openSqliteDatabase()建立其 PRAGMA 设置在 sqlite.ts 中可见if (options.walMode) { sqlite.pragma(journal_mode WAL); sqlite.pragma(synchronous NORMAL); } else { sqlite.pragma(journal_mode DELETE); } sqlite.pragma(cache_size -65536); sqlite.pragma(foreign_keys ON); sqlite.pragma(temp_store MEMORY);journal_mode WAL默认启用 WAL 模式读写并发能力更强是否启用由serverConfig.database.walMode控制foreign_keys ON显式开启外键约束保证关联数据的引用完整性cache_size -65536将 SQLite 页面缓存设为 64 MiBtemp_store MEMORY临时表与临时索引驻留内存提升排序、JOIN 等操作性能。此外instrumentation.ts 会对prepare()返回的 Statement 的run()/get()/all()方法做 OpenTelemetry 埋点为每条 SQL 生成db.systemsqlite、db.statement、db.operation属性的追踪 Span未注册 TracerProvider 时该埋点自动退化为空操作不影响正常运行。第四步Drizzle Studio——可视化检查数据库官方文档还推荐了开发阶段的利器在仓库根目录运行pnpm run db:studio该命令对应 packages/db/package.json 的studio: drizzle-kit studio。Drizzle Studio 会启动一个本地 Web 界面让你以可视化表格的方式浏览、过滤、编辑数据库中的记录而不必手写 SQL。它在以下场景尤其有用验证迁移应用后的表结构与预期一致快速查看某条书签、标签或用户的字段值排查数据问题在手工修复测试数据时直接编辑记录。注意 Studio 与迁移命令共用 drizzle.config.ts 中的dbCredentials.url因此它连接的就是同一个db.db数据库文件。开发工作流与注意事项综合官方文档与源码Karakeep 的数据库演进标准流程可以总结为修改 schema.ts新增/变更表、字段、索引或关系在仓库根目录执行pnpm run db:generate --name 变更描述生成增量迁移 SQL检查生成的迁移文件内容是否符合预期执行pnpm run db:migrate应用到本地数据库可选执行pnpm run db:studio可视化验证结果。几条基于仓库实现得出的实践建议每次 Schema 变更都必须配套生成迁移迁移文件是部署到生产环境的唯一结构变更通道跳过迁移直接改库会导致 drizzle/ 中的快照与真实库不一致后续db:generate的 diff 会失真给--name一个有意义的描述迁移文件名会长期保留在 drizzle/ 目录中清晰的名字如add_password_salt、add_api_key_scopes本身就是变更日志理解降级模式行为生产部署若开启degradedMode迁移会被跳过且数据库只读此时需在正常模式下单独完成迁移后再切换对应 migrate.ts 与 drizzle.ts 的实现测试环境可用内存库快速验证drizzle.ts 提供了getInMemoryDB(runMigrations)辅助函数测试代码可在:memory:数据库上直接跑完所有迁移快速获得与生产一致的结构观察迁移历史以理解 Schema 演进从0000到0093的迁移文件完整记录了 Karakeep 的功能演进轨迹阅读它们可以更深入地理解当前 schema.ts 中每个字段的来历。小结Karakeep 的数据库层以 Drizzle ORM 为核心形成了TypeScript Schema 单一事实来源 增量 SQL 迁移 运行时自动应用的完整闭环。通过pnpm run db:generate --name ...、pnpm run db:migrate、pnpm run db:studio三个命令开发者即可完成从 Schema 变更到可视化验证的全流程。本文所述的每一步都能在 packages/db 包内找到对应实现配合官方文档 03-database.md 使用即可安全、可复现地驱动 Karakeep 数据模型的持续演进。【免费下载链接】hoarderA self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search项目地址: https://gitcode.com/GitHub_Trending/ho/hoarder创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价