Files
deepseek-harness/packages/storage/storage-sqlite/README.zh.md
T

145 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
description: "SQLite 存储后端:面向在单个数据库文件中选择、配置或排查按行存储文档的 KV 存储的宿主与维护者。"
kind: "package-reference"
---
# @deepseek-ai/dsh-storage-sqlite
[English](README.md) | 中文
## 概述
`dsh-storage-sqlite` 是一个存储后端:把每个已路由单元托管在同一个 SQLite 数据库文件中,每条记录按行存储一份 JSON 文档,注册为后端 `sqlite`。单条记录更新替换一条数据行,这正是它适合高频定点写入的原因。当领域数据变动频繁、或部署偏好单一可查询数据库时选择它;当数据需要以纯文本文件形式可读时选择 JSON 后端。本后端只面向宿主侧:它不贡献提示词、工具或 schema,因此模型与 agent loop(智能体循环)永远不会看到它。
## 目录
- [使用本包](#use-this-package)
- [理解实现](#understand-the-implementation)
- [进一步探索](#further-exploration)
- [模型体验](#model-experience)
- [已知限制与延期工作](#known-limitations-and-deferred-work)
- [开发备注](#dev-note)
-----
<a id="use-this-package"></a>
## 使用本包
当组合把频繁更新的领域数据保存在一个数据库中时使用本包:把相关领域路由到此后端,每个单元即作为表物化在配置的数据库文件中。
### 何时选择
当写入频繁且为定点更新时选择它——每个键映射到一条数据行,因此更新记录无需重写整个单元。对接受的旧单元首次修改时,还会在同一事务中更新其版本元数据。当人类需要以纯文本文件查看或编辑已存数据时选择 JSON。同步的 `node:sqlite` 驱动会在每次写入调用期间阻塞 JavaScript 线程,包括该首次事务;高写入率时须纳入考量。
### 配置
两个字段:数据库路径与 journal mode。`:memory:` 打开一个进程内数据库,其内容随进程消失。
```yaml
- name: '@deepseek-ai/dsh-storage'
- name: '@deepseek-ai/dsh-storage-sqlite'
config:
path: /var/lib/dsh/data.db
- name: '@deepseek-ai/dsh-storage-domain'
config:
backend: sqlite
```
| 字段 | 默认值 | 含义 |
|---|---|---|
| `path` | 必填 | SQLite 数据库文件路径,或 `:memory:` |
| `journalMode` | `wal` | Journal mode:`wal`、`delete`、`truncate` 或 `persist` |
`wal` 适合本地磁盘;回滚日志模式(`delete`/`truncate`/`persist`)适合 WAL 共享内存文件不可用的文件系统,例如网络挂载。生成的[配置目录](../../../docs/config-catalog.zh.md#deepseek-aidsh-storage-sqlite)是每个受支持字段及其 JSDoc 的穷尽式真源。
### 可观察行为
缺失的目录与数据库文件会以仅所有者可访问的权限创建(`0o700`/`0o600`);已有数据库保持其既有模式。单元接受描述符的当前版本或 `compatibleVersions`,否则拒绝 `version-mismatch`。读取接受的旧单元时保留其版本戳;首次修改将数据与当前版本戳放在同一事务中提交。删除不存在的键或空批次时版本戳保持不变。未改动记录的值与其他单元保持不变;后端不转换应用值。盖有非当前物理布局版本的数据库会直接拒绝;领域兼容性不迁移数据库布局。Storage 检查使用 `StorageError` 代码;底层 SQLite 失败会向上传递,写入操作完成后即已持久化。
每个非空批量删除都使用一个事务,需要时在该事务内更新版本戳。事务失败时,只要 SQLite 成功回滚,数据与版本戳就保持原状,包括自动回滚的情况。`BEGIN` 失败会使整个批次保持未应用,允许在同一句柄上重试。如果回滚本身失败,后端会保留代码为 `unknown-state` 的 `StorageError`,其 cause 是包含两次失败的 `AggregateError`,并拒绝后续单元读写,以及正在等待或新发起的打开操作。此时事务结果未知。须关闭后端及其领域,再创建新后端检查已存状态,然后决定是否重试。混合记录与降级行为参阅[领域版本](../../../docs/subsystems/storage.zh.md#domain-versioning)。
-----
<a id="understand-the-implementation"></a>
## 理解实现
<details>
<summary>实现细节——点击展开</summary>
本后端是在单个 `node:sqlite` 连接之上的文档按行布局。按键写入复用预处理语句;版本升级会增加元数据更新与事务。
### 设计理念
- **每行一份文档。** 每个单元表都变成一张物理 STRICT 表 `u_<unit>_<table> (key TEXT PRIMARY KEY, value TEXT)`,其 `value` 列保存记录的 JSON 文本;全局单例存放在共享的 `unit_globals` 表中。一个键的更新会替换一条数据行;推进单元版本戳时还会更新其元数据。
- **原子写入。** 当前版本的单记录写入使用一条预处理语句。批量删除和对接受的旧单元首次修改共用一个事务助手;首次修改包含当前版本戳。成功回滚会保留数据与版本戳。写入顺序仍由调用方负责(领域层的写入链)。
- **名称在 DDL 之前校验。** 单元名与表名在进入 DDL 之前必须匹配 `UNIT_NAME_RE`,因此任何外部输入都不会被插值进 SQL 标识符。
- **版本分别检查。** 物理布局版本存放在 `PRAGMA user_version`(全新数据库最后盖戳),必须精确匹配。单元版本存放在 `units` 中,也接受拥有方声明的 `compatibleVersions`;记录转换由拥有方负责。
### 打开顺序
打开数据库时会以 `0o700` 创建父目录、以 `0o600` 独占创建缺失文件、应用 `PRAGMA foreign_keys = ON` 与 journal mode、检查 `user_version`、创建 `units` 与 `unit_globals` 元数据表,并在最后给全新数据库盖戳,让失败留下未盖戳的介质。
### 源码地图
| 文件 | 职责 |
|---|---|
| [`src/index.ts`](src/index.ts) | 插件入口:后端注册、`path`/`journalMode` 配置、单元表 |
| [`src/schema.ts`](src/schema.ts) | 打开顺序、物理布局版本、元数据表、记录表命名 |
| [`src/unit.ts`](src/unit.ts) | 一个已打开单元:预处理语句、JSON 值解析、关闭 |
</details>
-----
<a id="further-exploration"></a>
## 进一步探索
当本后端视角不够用时阅读以下页面:子系统参考是权威约定,兄弟后端展示了另一种介质。
- [存储子系统](../../../docs/subsystems/storage.zh.md)——后端约定、领域语义与生成的 API。
- [存储包映射](../README.zh.md)——家族的各包及其在仓库中的位置。
- [JSON 存储后端](../storage-json/README.zh.md)——面向小而可检查数据的人类可读介质。
- [领域 KV 存储 Agent Note](../../../.agents/notes/proposed/architecture/2026-07-24-domain-kv-storage-and-workspace.zh.md)——后端家族背后的设计与被推迟的会话后端迁移。
-----
<a id="model-experience"></a>
## 模型体验
### 已存领域记录
#### 模型看到什么
无。本后端不贡献提示词、工具或 schema;它在 `ctx.storage` 后面持久化非会话领域数据,只供宿主侧消费方使用。
#### Token 影响
实时请求 token 为零。
#### KV Cache 影响
无:本后端从不触碰实时请求前缀。
## 已知限制与延期工作
<a id="known-limitations-and-deferred-work"></a>
这些限制说明本后端何时不合适,或何时需要特别的运维注意。它们是当前包约束,不是任务积压。
- **同步驱动阻塞事件循环**——写入使用同步 `DatabaseSync` 调用;批量删除与对接受的旧单元首次修改会在 JavaScript 线程上持有事务。
- **没有忙等待或重试策略**——持有写锁的竞争连接会立即拒绝操作,而不是等待;领域层的写入链在单进程内串行化写入,跨进程协调不在范围内。
- **只打开当前的物理布局版本**——任何其他已标记的 `user_version` 都会被拒绝而不是迁移(预发布立场)。
- **版本检查保持单元级**——`per-record` 布局请求不会让本后端增加逐记录版本戳或 JSON 的缺失文档恢复策略。
- **打开顺序与查询提供方重复**——`openDatabase` 与 `session-query-sqlite` 都强制执行 SQLite 文件所有权约束,但两个包各自拥有不同的应用标识与 schema;没有共享介质辅助模块将二者耦合。
<a id="dev-note"></a>
### 开发备注
<details>
<summary>维护者的工作上下文——点击展开</summary>
无。
</details>