Files
qinglong/docs/operations/ql3-local-sqlite-adoption.md

6.3 KiB
Raw Permalink Blame History

QingLong 2.x SQLite 接管到 3.0

本流程把已有 QingLong 2.x database.sqlite 以不覆盖 source 的方式接管为 3.0 adopted storage。它只处理单个 SQLite 主库; scripts、configs、logs 和其他 data directory 文件不在本流程内。

全部命令由最终运行 QingLong 的同一个 POSIX 用户执行。ql3-adoption 是一次性 CLI,不启动服务,也不会自动执行 cutover 或 Legacy rollback。

1. 空间与停机前检查

  • deploymentRoot 及输出父目录必须是当前 UID、canonical、非 symlink 的 0700 目录;
  • command file 必须是当前 UID、canonical、单链接 0600 文件;
  • source 必须是当前 UID 的 canonical 普通单链接文件,且 group/world 不可写;生产环境建议 0600
  • target、recovery、manifest、activation 必须尚不存在,并全部位于 deploymentRoot 内;
  • source、target、recovery、manifest、activation 五个路径必须互不相同;
  • 预留 recovery + target 两份数据库以及 SQLite 临时/sidecar 余量。不要以删除 recovery 的方式解决空间不足。

inspect 和 Online Backup 可以在 2.x 仍可读时执行,但最终 stage review 后到 activation/cutover 期间必须停止外部 writer,并保证 source 不再漂移。activation prepare 会尝试取得 source/target write fence;无法取得时失败关闭。

低配设备说明:四个阶段都是 one-shot 进程,没有后台 timer、监听端口或自动重试;schema inventory 最多 4096 项,manifest 最多 256 KiBSQLite backup 按页复制而不是把整个数据库载入 JS heap。制品审计的 import RSS 不是迁移峰值承诺,正式升级前仍需在目标 路由器/NAS 上测量可用空间、耗时、峰值 RSS 和断电恢复。

2. Inspect:生成待审核计划

{
  "schemaVersion": 1,
  "operation": "local-sqlite.adoption.inspect",
  "options": {
    "deploymentRoot": "/opt/qinglong3",
    "profile": "edge",
    "sourcePath": "/opt/qinglong/data/database.sqlite",
    "legacyTimezone": "Asia/Shanghai"
  }
}
chmod 0600 /secure/operator/ql3-sqlite-inspect.json
ql3-adoption run --command-file /secure/operator/ql3-sqlite-inspect.json

记录返回的 planDigest,审核 schema catalog、table names 与 task inventory。不要在审核后修改 source;若 source 变化,重新 inspect 不要沿用旧 digest。

3. Stage:生成 recovery、target 与 manifest

{
  "schemaVersion": 1,
  "operation": "local-sqlite.adoption.stage",
  "options": {
    "deploymentRoot": "/opt/qinglong3",
    "profile": "edge",
    "sourcePath": "/opt/qinglong/data/database.sqlite",
    "targetPath": "/opt/qinglong3/artifacts/qinglong3.sqlite",
    "recoveryPath": "/opt/qinglong3/artifacts/database.pre-ql3.sqlite",
    "manifestPath": "/opt/qinglong3/artifacts/qinglong3-adoption.json",
    "expectedPlanDigest": "REPLACE_WITH_INSPECT_PLAN_DIGEST",
    "legacyTimezone": "Asia/Shanghai"
  }
}
chmod 0600 /secure/operator/ql3-sqlite-stage.json
ql3-adoption run --command-file /secure/operator/ql3-sqlite-stage.json

stage 通过 SQLite Online Backup 创建独立 recovery 和 target,只在 target 上执行 3.0 migration,并以 0600 no-replace 文件发布 结果。source 不会被覆盖。任一输出已存在时不要删除后盲目重跑,应先把现有文件和命令结果作为一次未完成 ceremony 调查。

4. Verify:独立复验 staged 结果

{
  "schemaVersion": 1,
  "operation": "local-sqlite.adoption.verify",
  "options": {
    "deploymentRoot": "/opt/qinglong3",
    "profile": "edge",
    "targetPath": "/opt/qinglong3/artifacts/qinglong3.sqlite",
    "recoveryPath": "/opt/qinglong3/artifacts/database.pre-ql3.sqlite",
    "manifestPath": "/opt/qinglong3/artifacts/qinglong3-adoption.json"
  }
}
chmod 0600 /secure/operator/ql3-sqlite-verify.json
ql3-adoption run --command-file /secure/operator/ql3-sqlite-verify.json

记录返回的 manifestDigest。verify 只接受与 manifest 一致的 recovery/target、完整 migration 和通过的 adopted readiness。

5. Prepare activation:冻结三份物理事实

{
  "schemaVersion": 1,
  "operation": "local-sqlite.activation.prepare",
  "options": {
    "deploymentRoot": "/opt/qinglong3",
    "profile": "edge",
    "sourcePath": "/opt/qinglong/data/database.sqlite",
    "targetPath": "/opt/qinglong3/artifacts/qinglong3.sqlite",
    "recoveryPath": "/opt/qinglong3/artifacts/database.pre-ql3.sqlite",
    "manifestPath": "/opt/qinglong3/artifacts/qinglong3-adoption.json",
    "activationPath": "/opt/qinglong3/artifacts/qinglong3-activation.json",
    "expectedManifestDigest": "REPLACE_WITH_VERIFY_MANIFEST_DIGEST"
  }
}
chmod 0600 /secure/operator/ql3-sqlite-activation.json
ql3-adoption run --command-file /secure/operator/ql3-sqlite-activation.json

activation 分别记录 sourceSha256recoverySha256targetSha256。SQLite Online Backup 的 recovery 与 source 可以逻辑等价 但物理字节不同,因此不能比较两者哈希来判断 clean rollback。记录返回的 activationDigest,并把 exact activation path/digest 交给 adopted application 和后续 cutover 命令。

6. Cutover 与回退判定

完成 activation 后,继续执行 Edge/Standalone 部署准备 中的 legacy silence、target start/stop 和双阶段 rollback ceremony。不要仅凭 activation 启动两个 writer。

target stop 后的数据分类为:

  • rollback_candidatetarget/source 都保持 activation 时字节且双方 sidecar clear
  • reconciliation_required:target 已接受写入或存在 target sidecar;保留三份数据库,禁止自动启动 2.x;
  • manual_reviewsource 漂移、activation 或稳定文件身份无法证明;禁止猜测。

证据字段 sourceMatchesActivation 表示 source 与 activation 时的原 source 哈希相同,不表示 source 与 Online Backup recovery 文件 物理相同。rollback_candidate 也不是启动授权,仍须走双阶段 Legacy rollback。

7. 当前边界

本流程不迁移完整 2.x data directory,不做 target 写后的自动逆迁移,不连接 Cluster 控制面,也没有云端恢复服务。任何 reconciliation_required 必须保留现场并等待后续显式数据域工具;不要把 target 覆盖回 source。