Skip to content
bitzorcas
中EN

Guide

数据库初始化与迁移

锁安全 --init-schema、/host/schema 审阅脚本与 Host-Admin 漂移通知如何配合。

Last updated

BitzOrcas 把 Schema 收敛分成三条车道,发版时不要把它们捆成一次 InitTables:

车道何时自动做什么不做什么
A. --init-schema部署窗口建缺失表;给已有表补可空且无默认值的列改列、建已有表索引、卸整表索引
B. /host/schema 与 scripts/database/migrations/运维审阅窗口生成放宽长度、必填加列、建索引、改类型的受保护脚本发版瞬间自动执行
C. API Host operations-schema-drift-notify常驻 API 每 15 分钟只读嗅探残留漂移,给 host-admin 发站内信自动 ALTER、阻断启动

空库仍由编译期元数据驱动 SqlSugar CodeFirst。已有库的破坏性或 size-of-data 变更必须先执行 scripts/database/migrations/ 中尚未应用的顺序脚本,不能指望 --init-schema 改列长。

关键路径图

下图展示了生产环境数据库版本迁移与安全升级流水线:通过迁移锁与幂等校验确保多实例滚动发布时表结构安全变更。

Schema 变更意图

生成并审查

备份与扩展

部署兼容代码

观察后收缩

命令语义

命令行为
--init-schema业务表 + 当前审计分表 + CAP Outbox + 种子
--init-schema --no-seed业务表 + 审计分表 + CAP Outbox,不跑种子
--seed-demo等同完整 --init-schema,表达“恢复演示状态”
--seed-only初始化 CAP Outbox 后跑种子,业务表必须已存在
--reset-schema破坏性重建;Production/Staging 拒绝
AppHost BITZORCAS_ASPIRE_RESET_SCHEMA=true把 --reset-schema --force 交给一次性 schema-initializer。默认叠加 --no-seed;同时开 BITZORCAS_ASPIRE_SEED_DEMO=true 则叠加 --seed-demo。不能与 BITZORCAS_ASPIRE_RESET_DEMO_PASSWORDS 同时使用。Quartz 表不会被删除

systemd 发版模式(deploy.sh)见 部署形态选择:BITZORCAS_DEPLOY_DB_MODE=schema-only|platform-seed|full-seed。

AppHost persist 库整库重建

dotnet run --project src/Hosts/BitzOrcas.AppHost -- --reset-schema 不会 reset 库:-- 后面的参数进的是 Aspire AppHost 自己,进不了 schema-initializer。fast / persist 库要推倒重建,先停掉正在跑的 AppHost,再开显式开关:

Terminal window
# 删业务表、审计分表、CAP 表后重建,并重新播种演示账号。
BITZORCAS_ASPIRE_RESET_SCHEMA=true \
BITZORCAS_ASPIRE_SEED_DEMO=true \
dotnet run --project src/Hosts/BitzOrcas.AppHost --launch-profile fast
# 只要空表、不要演示账号时去掉 SEED_DEMO。
BITZORCAS_ASPIRE_RESET_SCHEMA=true \
dotnet run --project src/Hosts/BitzOrcas.AppHost --launch-profile fast

Dashboard 里 schema-initializer 应先打印破坏性警告,再跑 --reset-schema --force。成功后必须关掉 BITZORCAS_ASPIRE_RESET_SCHEMA 再日常启动。Production / Staging 的 AppHost 会直接退出。列长变更不要靠这条,走 /host/schema 或 scripts/database/migrations/。

只改演示密码、要保留业务数据时,用 BITZORCAS_ASPIRE_RESET_DEMO_PASSWORDS,不要开 RESET_SCHEMA。

推荐脚本:

Terminal window
scripts/database/init-schema.sh
scripts/database/seed-demo.sh

目标数据库必须由 DBA 预先创建,账号需要建表和建索引权限。

初始化顺序

  1. 从编译期 PersistenceModelRegistry 创建业务表与索引;
  2. 创建当前时间桶的审计分表;
  3. 通过 CAP IStorageInitializer 幂等创建 Outbox 表;
  4. 按 ISeedStep.Order 执行幂等 CSV seed。

常驻 Host 正常启动时仍由 CAP Provider 自动创建 Outbox 表;一次性命令不会启动 hosted service,因此 --init-schema 无论是否带 --no-seed 都会幂等初始化 CAP Outbox(保证仅建表路径也就绪)。未来审计分表在首次写入对应时间桶时按规则生成。

SQL Server 上 --init-schema 先做目录探测,再按锁安全计划执行:

探测结果发版行为
对象齐全且字符串列够宽毫秒级跳过
缺物理表只对不存在的表 InitTables,并给新表建声明索引
已有表缺可空、无默认值列ALTER TABLE [<table_name>] ADD [<column_name>] <data_type> NULL,LOCK_TIMEOUT 5000,超时失败退出
列更窄、缺索引、必填/带默认值加列、改类型不改库,打残留日志,退出码仍为 0
探测失败 / 非 SQL Server逐表存在性探测,仍遵守上表
BITZORCAS_SCHEMA_FULL_INIT=1仅 Development/Demo 可全量 CodeFirst,且不卸已有表索引;Production/Staging 忽略

已有数据库升级

上线新版本前:

备份
→ 盘点 scripts/database/migrations(破坏性 / 回填 / 列变宽)
→ 按文件名顺序由 DBA 执行未应用脚本
→ deploy.sh 跑 --init-schema --no-seed(只建缺表、补可空列)
→ 启动 API / JobHost
→ Host-Admin 若收到「Schema 漂移待实施」站内信,打开 /host/schema
→ 验证后再切流

deploy.sh 不会自动执行 scripts/database/migrations/。那是 DBA 清单,不是发版隐式步骤。

示例 1:日常发版只加了一张新表和一列可空字段

PO 新增 SysWidget,并在已有 SysUser 上增加可空 Region。生产执行:

Terminal window
BITZORCAS_DEPLOY_DB_MODE=schema-only \
sudo /www/scripts/deploy.sh /tmp/app.zip Production

--init-schema --no-seed 会 CREATE TABLE 新表(含新表索引),并对 SysUser 执行类似:

SET DEADLOCK_PRIORITY LOW;
SET LOCK_TIMEOUT 5000;
ALTER TABLE [dbo].[SysUser] ADD [Region] NVARCHAR(256) NULL;

这是 SQL Server 元数据操作,与行数无关;若 5 秒内拿不到 Schema Lock,命令失败退出,不会无限等。

示例 2:把 SysModule.RequiredPermission 从 100 放到 2000

这是有界加长,不会被 --init-schema 自动执行。种子若写入超过 100 字符,会得到 SQL 2628。正确顺序:

  1. 发版后 Host-Admin 打开 /host/schema,预览 WidenLength 审阅脚本。
  2. 或手跑幂等语句(目录小表,通常秒级):
-- 目录小表:先确认列仍偏窄,重复执行不会无条件改写。
IF COL_LENGTH('dbo.SysModule', 'RequiredPermission') IS NOT NULL
AND COL_LENGTH('dbo.SysModule', 'RequiredPermission') < 4000
BEGIN
-- 100 字符存不下权限码;init-schema 不会做这次 ALTER。
ALTER TABLE dbo.SysModule
ALTER COLUMN RequiredPermission nvarchar(2000) NULL;
END;
  1. 再跑 --seed-only 或带种子的演示初始化。

示例 3:已有大表缺一个声明索引

--init-schema 只记残留,不 CREATE INDEX。/host/schema 生成的审阅脚本在 SQL Server 上带:

CREATE INDEX [IX_Orders_Region] ON [sales].[Orders]([Region])
WITH (ONLINE = ON, MAXDOP = 1, RESUMABLE = ON);

企业版/开发版可在线建;标准版请删掉 WITH 子句,放到维护窗口。行数估计超过 10 万时脚本会主动中止。

禁止「先 DROP 全部声明索引再 CREATE」。若必须替换某个索引:先用新名字 ONLINE 建 → 校验 → 再 DROP 旧索引。

发版后 Host-Admin 通知

真正嗅探跑在 API Host 的 SchemaDriftNotifyHostedService(Catalog 名 operations-schema-drift-notify),默认每 15 分钟一次。它使用与 /host/schema 同一套全量实体目录和 host-admin 收件端口。

JobHost 仍登记同名 Quartz 适配器,以满足 Catalog 完整绑定;但 JobHost 没有全量模型目录和 Authorization 收件端口,执行时会 fail-soft 跳过,避免半套模型报假干净。不要为了这份通知去扩大 JobHost CompositionInclude。

  • 无漂移:保持静默。
  • 有残留:向 TenantId=0 的 host-admin 角色成员发聚合站内信,链接 /host/schema。
  • 失败 fail-soft,不影响 API 和 JobHost 健康。
  • 可用 Operations:SchemaDriftNotify:Enabled=false 或 BackgroundJobs:operations-schema-drift-notify:Enabled=false 关闭。
  • 也可随时打开 /host/schema 或运行:
Terminal window
dotnet run --project src/Tooling/BitzOrcas.SchemaMaintenance -- --check-schema

种子数据

CSV seed 使用 Storageable upsert,可重复执行但不会自动删除 CSV 中已移除的旧行。删除和归档必须是显式迁移或运维动作。

退出码

码含义
0成功
1初始化异常
2生产持久化 adapter 未启用,常见于连接串/RabbitMQ 配置不全
3至少一个种子步骤失败
130用户中断

另见

当前自动化边界

仓库的 scripts/database/migrations/*.sql 是按文件名排序的人工迁移集。当前没有通用 migration ledger 或 runner 自动记录某个环境已执行文件、Checksum、操作者和时间。发布系统必须在外部受控流程中维护这份证据,不能仅凭“脚本目录存在”判断数据库已升级。

22 个现有脚本主要保护统一聚合、owner rows、审计时间类型和平台持久化变更;相关 Architecture tests 只证明关键脚本仍存在,不证明它已在目标数据库执行。

安全的 expand/contract

  1. Expand:新增可空列/新表/兼容索引,不删除旧形态。
  2. Deploy:新旧副本都能读写兼容 schema。
  3. Backfill:按租户和稳定主键分批,记录进度与失败。
  4. Switch:读路径切到新形态,观察慢查询与差异。
  5. Contract:观察期后才删除旧列、旧索引或兼容代码。
-- ① 示例迁移应自检对象存在性,重复执行不会无条件破坏数据。
IF COL_LENGTH('dbo.SandboxNote', 'NormalizedName') IS NULL
BEGIN
ALTER TABLE dbo.SandboxNote ADD NormalizedName nvarchar(200) NULL;
END;
-- ② 回填与 NOT NULL 收缩分成不同发布批次,先验证所有租户无空值。

这段 SQL 只演示 expand 形状,不对应当前待执行脚本。真实迁移必须包含 provider、schema、锁表影响、回滚/前向修复和数据验证。

发布前后核对

  • 备份文件完成 VERIFYONLY,并有最近真实恢复演练;
  • 未应用脚本按名称、Checksum、审批与目标环境登记;
  • 长事务、锁、索引空间和复制/AG 影响经过评估;
  • API/JobHost 混合版本能运行在 expand schema;
  • 回填按租户可暂停、可续跑、可审计;
  • 切流后核对行数、不变量、Outbox、作业和关键查询;
  • contract 变更直到观察期结束才执行。

规划缺口

平台需要补充带 Checksum 的 migration ledger、受控 runner、dry-run/plan、并发锁与发布报告。完成前,这些职责属于部署流水线和 DBA,不应在说明书中宣称框架自动完成。

100%

滚轮或按钮缩放 · 放大后拖动画面 · 双击切换 100% / 200%