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/目录,包含表定义、迁移脚本和核心业务逻辑。
登录后查看全文
热门项目推荐
相关项目推荐
GLM-5智谱 AI 正式发布 GLM-5,旨在应对复杂系统工程和长时域智能体任务。Jinja00
GLM-5-w4a8GLM-5-w4a8基于混合专家架构,专为复杂系统工程与长周期智能体任务设计。支持单/多节点部署,适配Atlas 800T A3,采用w4a8量化技术,结合vLLM推理优化,高效平衡性能与精度,助力智能应用开发Jinja00
jiuwenclawJiuwenClaw 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。Python0194- QQwen3.5-397B-A17BQwen3.5 实现了重大飞跃,整合了多模态学习、架构效率、强化学习规模以及全球可访问性等方面的突破性进展,旨在为开发者和企业赋予前所未有的能力与效率。Jinja00
AtomGit城市坐标计划AtomGit 城市坐标计划开启!让开源有坐标,让城市有星火。致力于与城市合伙人共同构建并长期运营一个健康、活跃的本地开发者生态。01
awesome-zig一个关于 Zig 优秀库及资源的协作列表。Makefile00
热门内容推荐
最新内容推荐
pi-mono自定义工具开发实战指南:从入门到精通3个实时风控价值:Flink CDC+ClickHouse在金融反欺诈的实时监测指南Docling 实用指南:从核心功能到配置实践自动化票务处理系统在高并发抢票场景中的技术实现:从手动抢购痛点到智能化解决方案OpenCore Legacy Patcher显卡驱动适配指南:让老Mac焕发新生7个维度掌握Avalonia:跨平台UI框架从入门到架构师Warp框架安装部署解决方案:从环境诊断到容器化实战指南突破移动瓶颈:kkFileView的5层适配架构与全场景实战指南革新智能交互:xiaozhi-esp32如何实现百元级AI对话机器人如何打造专属AI服务器?本地部署大模型的全流程实战指南
项目优选
收起
deepin linux kernel
C
27
12
OpenHarmony documentation | OpenHarmony开发者文档
Dockerfile
602
4.04 K
🔥LeetCode solutions in any programming language | 多种编程语言实现 LeetCode、《剑指 Offer(第 2 版)》、《程序员面试金典(第 6 版)》题解
Java
69
21
Ascend Extension for PyTorch
Python
442
531
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
112
170
🎉 (RuoYi)官方仓库 基于SpringBoot,Spring Security,JWT,Vue3 & Vite、Element Plus 的前后端分离权限管理系统
Vue
1.46 K
825
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
922
770
暂无简介
Dart
847
204
React Native鸿蒙化仓库
JavaScript
321
375
openGauss kernel ~ openGauss is an open source relational database management system
C++
174
249