---
title: "数据库"
description: "元数据（meta）库存放无法从文件派生的状态：默认 SQLite，面向团队可通过 META_DB_URL 切换 Postgres。"
---

# 数据库

在 Notarium 中，笔记就是文件，搜索索引和图谱都由它们重建。但有一部分状态**无法从文件派生**：这部分由一个独立的元数据（meta）库保存。默认情况下，它是数据根目录下的一个 SQLite 文件——`<DATA_DIR>/meta.db`；只有当你要指向外部 Postgres 时，才需要用到 `META_DB_URL` 变量。

## 元数据库存放什么

| 数据 | 为什么不来自文件 |
|---|---|
| 笔记标识符 | `notarium-id` ↔ 路径的注册表：移动/重命名之后依然保留。 |
| 版本历史 | 修订日志（版本快照、某次修改的来源）由应用本身维护，而不是 git。 |
| 用户与访问权限 | 账户、角色、成员资格、令牌。 |
| 重命名历史 | 空间和项目旧 slug 的别名——让此前的地址仍然能解析到位。 |

这些都无法仅凭 `.md` 文件重建——所以元数据库必须始终纳入你的[备份](/docs/self-hosting/backup/)。这个库里也有一份空间的注册表，但它是派生的：空间的身份标识存放在其根目录下的标记文件里，扫描即可恢复（[File-first](/docs/concepts/file-first/)）。引擎的派生索引（位于 `<DATA_DIR>/engine`）即使丢失，也会在下次启动时直接从文件重建。

关于版本本身及其来源，参见[概念：版本管理](/docs/concepts/versioning/)。

## 数据库结构与迁移

元数据库的数据库结构由应用自己维护：迁移在**启动时**应用，没有专门的命令。库里自带一份迁移记录表，记录着已经应用过哪些迁移——构建正是据此判断自己面对的是什么。

启动只接受三种状态：

- **空库**——建立基础数据库结构，并在同一个事务里写入迁移记录表条目；
- **迁移记录表恰好是预期序列前缀的库**——先核对版本、名称和校验和，再补上缺失的那一段；
- **非空却没有迁移记录表的库**——启动**直接失败（fail closed）**，且发生在任何数据库结构变更和应用查询之前。

最后这条是刻意为之。构建不会去猜一个自己不认识的数据库是什么版本，也不会擅自补写迁移记录：那会悄无声息地损坏数据。如果你手上正是这样一个库（比如某个早于基础数据库结构的实例），请先按它自己版本的常规流程升级并检查，然后再让它跨过这道边界。

> [!important] 回滚就是从备份恢复
> Notarium 的数据回滚机制是一份经过校验的归档，而不是反向 SQL 迁移。请在升级**之前**做好备份并校验：[备份与恢复](/docs/self-hosting/backup/)。

## SQLite（默认）

零配置：默认情况下元数据库就是 `sqlite:<DATA_DIR>/meta.db`，也就是 `/data` 数据卷上的一个文件。无需单独的服务，也没有任何东西要配置。对于个人实例和**单个**容器上的小团队，这已经足够。

## Postgres（面向团队与共享状态）

若要把状态移到容器之外——为了共享存储、容错或维护——请指向 Postgres：

```bash
# .env
META_DB_URL=postgres://user:pass@db:5432/notarium
```

当状态必须独立于容器生命周期存在时，你就需要 Postgres。此时笔记本身仍然是 `<DATA_DIR>/spaces` 下的文件——只有无法从它们派生的部分才进入数据库。

> [!important] `password` 模式依赖元数据库
> 在 `AUTH_MODE=password` 模式下，元数据库用于存放账户和令牌——而它默认就已存在（数据根目录下的 SQLite）。你不必单独设置 `META_DB_URL`；只有在迁移到 Postgres 时才需要指定它。只有 `AUTH_MODE=none` 才能在没有元数据库的情况下工作。参见[身份认证](/docs/self-hosting/authentication/)。

> [!note] 单实例
> 把状态移入 Postgres 本身并不会启用横向扩展：Notarium 以单实例运行，不支持在负载均衡器后运行多个实例（参见[生产环境](/docs/self-hosting/production/)）。
