DeepChat本地存储方案:better-sqlite3与数据持久化实践
2026-02-05 05:52:17作者:曹令琨Iris
方案背景与技术选型
DeepChat作为连接AI与个人数据的智能助手,采用better-sqlite3作为本地存储解决方案,通过src/main/presenter/sqlitePresenter/index.ts实现数据持久化。该方案基于SQLCipher加密扩展,提供事务支持、数据迁移和损坏恢复机制,确保用户对话历史、消息内容等核心数据的安全存储。
技术栈组成
- 核心库:better-sqlite3-multiple-ciphers(SQLCipher扩展版)
- 数据模型:Conversations/Messages/Attachments三表结构
- 安全特性:数据库文件加密、WAL模式、自动备份
- 维护机制:版本迁移、损坏恢复、事务支持
数据库架构设计
核心表结构
DeepChat采用模块化表设计,各表职责明确且通过外键关联:
erDiagram
CONVERSATIONS ||--o{ MESSAGES : contains
MESSAGES ||--o{ MESSAGE_ATTACHMENTS : has
ATTACHMENTS }|--|| MESSAGE_ATTACHMENTS : references
- Conversations表:存储对话元数据(标题、创建时间、设置)
- Messages表:存储消息内容(文本、角色、状态、序号)
- Attachments表:存储文件附件元数据
- MessageAttachments表:消息与附件的多对多关联
初始化流程
数据库连接建立过程包含错误处理与自动恢复机制,关键步骤如下:
// 核心初始化逻辑 [src/main/presenter/sqlitePresenter/index.ts#L32-L92]
constructor(dbPath: string, password?: string) {
this.dbPath = dbPath
try {
// 确保目录存在
const dbDir = path.dirname(dbPath)
if (!fs.existsSync(dbDir)) fs.mkdirSync(dbDir, { recursive: true })
// 初始化加密连接
this.db = new Database(dbPath)
this.db.pragma('journal_mode = WAL')
if (password) {
this.db.pragma(`cipher='sqlcipher'`)
this.db.pragma(`key='${password}'`)
}
// 表初始化与迁移
this.initTables()
this.initVersionTable()
this.migrate()
} catch (error) {
// 损坏恢复流程
this.backupDatabase()
this.cleanupDatabaseFiles()
// 重建数据库
this.db = new Database(dbPath)
// ...重新初始化
}
}
安全存储实现
加密机制
采用SQLCipher实现数据库透明加密,加密密钥通过配置系统安全管理:
// 加密配置 [src/main/presenter/sqlitePresenter/index.ts#L45-L48]
if (password) {
this.db.pragma(`cipher='sqlcipher'`)
this.db.pragma(`key='${password}'`)
}
数据备份策略
数据库损坏时自动创建时间戳备份,并清理损坏文件:
// 备份逻辑 [src/main/presenter/sqlitePresenter/index.ts#L98-L110]
private backupDatabase(): void {
const timestamp = new Date().toISOString().replace(/[:.]/g, '-')
const backupPath = `${this.dbPath}.${timestamp}.bak`
if (fs.existsSync(this.dbPath)) {
fs.copyFileSync(this.dbPath, backupPath)
console.log(`Database backed up to: ${backupPath}`)
}
}
数据操作接口
核心CRUD实现
SQLitePresenter封装了完整的数据操作API,以下为常用操作示例:
创建对话
// [src/main/presenter/sqlitePresenter/index.ts#L215-L220]
public async createConversation(
title: string,
settings: Partial<CONVERSATION_SETTINGS> = {}
): Promise<string> {
return this.conversationsTable.create(title, settings)
}
插入消息
// [src/main/presenter/sqlitePresenter/index.ts#L254-L278]
public async insertMessage(
conversationId: string,
content: string,
role: string,
parentId: string,
metadata: string = '{}',
orderSeq: number = 0,
tokenCount: number = 0,
status: string = 'pending',
isContextEdge: number = 0,
isVariant: number = 0
): Promise<string> {
return this.messagesTable.insert(/* 参数 */)
}
事务支持
通过better-sqlite3的事务API确保多操作原子性:
// [src/main/presenter/sqlitePresenter/index.ts#L330-L332]
public async runTransaction(operations: () => void): Promise<void> {
await this.db.transaction(operations)()
}
版本迁移与维护
增量迁移机制
系统通过版本表追踪 schema 变更,支持多表协同迁移:
// [src/main/presenter/sqlitePresenter/index.ts#L160-L207]
private migrate() {
const migrations = new Map<number, string[]>()
// 收集各表迁移脚本
tables.forEach((table) => {
for (let version = this.currentVersion + 1; version <= latestVersion; version++) {
const sql = table.getMigrationSQL?.(version)
if (sql) {
migrations.set(version, [...migrations.get(version) || [], sql])
}
}
})
// 按版本顺序执行迁移
const versions = Array.from(migrations.keys()).sort((a, b) => a - b)
for (const version of versions) {
this.db.transaction(() => {
migrationSQLs.forEach(sql => this.db.exec(sql))
this.db.prepare('INSERT INTO schema_versions VALUES (?, ?)')
.run(version, Date.now())
})()
}
}
表版本管理
每个表独立维护版本信息,通过getLatestVersion和getMigrationSQL接口提供迁移脚本:
// 版本管理示例 [src/main/presenter/sqlitePresenter/index.ts#L171-L174]
const latestVersion = tables.reduce((maxVersion, table) => {
const tableMaxVersion = table.getLatestVersion?.() || 0
return Math.max(maxVersion, tableMaxVersion)
}, 0)
性能优化策略
WAL模式
默认启用Write-Ahead Logging模式提升并发性能:
// [src/main/presenter/sqlitePresenter/index.ts#L43]
this.db.pragma('journal_mode = WAL')
WAL模式优势:
- 读操作不阻塞写操作
- 写操作只阻塞其他写操作
- 更小的I/O开销
索引设计
各表通过合理索引优化查询性能,例如Messages表的复合索引:
-- 示例索引设计(推测)
CREATE INDEX idx_messages_conversation_order ON messages(conversation_id, order_seq);
CREATE INDEX idx_messages_parent ON messages(parent_id);
实际应用场景
典型数据流向
以用户发送消息为例,完整数据存储流程:
sequenceDiagram
participant U as User
participant V as ViewModel
participant P as SQLitePresenter
participant M as MessagesTable
U->>V: 发送消息
V->>P: createConversation(标题)
P->>P: 生成conversation_id
V->>P: insertMessage(conversation_id, 内容, "user")
P->>M: insert(消息数据)
M-->>P: 返回message_id
P-->>V: 存储成功
数据恢复案例
当数据库文件损坏时,系统自动执行恢复流程:
1. 创建备份文件(如chat.db.2025-10-23T02-26-17.bak)
2. 删除损坏文件及WAL/SHM文件
3. 重建空数据库并初始化表结构
4. 记录错误日志便于问题排查
扩展与最佳实践
自定义SQL操作
如需执行复杂查询,可通过底层连接直接操作:
// 扩展示例
const customQuery = (conversationId: string) => {
return this.db.prepare(`
SELECT m.* FROM messages m
JOIN conversations c ON m.conversation_id = c.id
WHERE c.id = ? AND m.status = 'completed'
ORDER BY m.order_seq DESC LIMIT 1
`).get(conversationId)
}
备份策略建议
- 定期完整备份(如每日)
- 关键操作前触发增量备份
- 备份文件加密存储
- 定期测试恢复流程
总结
DeepChat的SQLite存储方案通过模块化设计、安全加密和性能优化,为AI助手提供了可靠的数据持久化基础。核心优势包括:
- 安全性:全程加密保护用户隐私数据
- 可靠性:完善的错误处理与自动恢复机制
- 扩展性:版本化迁移支持持续功能迭代
- 性能:WAL模式与索引优化保障操作流畅
完整实现代码参见src/main/presenter/sqlitePresenter/目录,包含表定义、迁移脚本和核心业务逻辑。
登录后查看全文
热门项目推荐
相关项目推荐
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust074- DDeepSeek-V4-ProDeepSeek-V4-Pro(总参数 1.6 万亿,激活 49B)面向复杂推理和高级编程任务,在代码竞赛、数学推理、Agent 工作流等场景表现优异,性能接近国际前沿闭源模型。Python00
MiniMax-M2.7MiniMax-M2.7 是我们首个深度参与自身进化过程的模型。M2.7 具备构建复杂智能体应用框架的能力,能够借助智能体团队、复杂技能以及动态工具搜索,完成高度精细的生产力任务。Python00
GLM-5.1GLM-5.1是智谱迄今最智能的旗舰模型,也是目前全球最强的开源模型。GLM-5.1大大提高了代码能力,在完成长程任务方面提升尤为显著。和此前分钟级交互的模型不同,它能够在一次任务中独立、持续工作超过8小时,期间自主规划、执行、自我进化,最终交付完整的工程级成果。Jinja00
Kimi-K2.6Kimi K2.6 是一款开源的原生多模态智能体模型,在长程编码、编码驱动设计、主动自主执行以及群体任务编排等实用能力方面实现了显著提升。Python00
Hy3-previewHy3 preview 是由腾讯混元团队研发的2950亿参数混合专家(Mixture-of-Experts, MoE)模型,包含210亿激活参数和38亿MTP层参数。Hy3 preview是在我们重构的基础设施上训练的首款模型,也是目前发布的性能最强的模型。该模型在复杂推理、指令遵循、上下文学习、代码生成及智能体任务等方面均实现了显著提升。Python00
项目优选
收起
暂无描述
Dockerfile
689
4.46 K
Ascend Extension for PyTorch
Python
543
668
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
955
928
Claude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed.
Get Started
Rust
414
74
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
407
323
昇腾LLM分布式训练框架
Python
146
172
本项目是CANN开源社区的核心管理仓库,包含社区的治理章程、治理组织、通用操作指引及流程规范等基础信息
650
232
旨在打造算法先进、性能卓越、高效敏捷、安全可靠的密码套件,通过轻量级、可剪裁的软件技术架构满足各行业不同场景的多样化要求,让密码技术应用更简单,同时探索后量子等先进算法创新实践,构建密码前沿技术底座!
C
1.08 K
564
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
1.59 K
925
TorchAir 支持用户基于PyTorch框架和torch_npu插件在昇腾NPU上使用图模式进行推理。
Python
642
292