Skip to content
bitzorcas
中EN

Guide

Database Maintenance

以独立 SqlSugar/SQL Server 运维工具执行全量、差异、日志备份、VERIFYONLY、受控恢复与单表流式导出。

Last updated

BitzOrcas.DatabaseMaintenance 复用 Framework 的 SqlSugarDatabaseBackupService 与 SqlSugarTableExportService,提供 SQL Server 全量/差异/日志备份、RESTORE VERIFYONLY、带安全门恢复,以及单表 CSV/JSON Lines 导出。它是高权限运维入口,不是普通开发 CLI。

操作与风险

选择一个模式

Backup

Verify

Restore

Export table

SQL Server BACKUP file

RESTORE VERIFYONLY

Pre-restore full snapshot

RESTORE WITH REPLACE, RECOVERY

Caret CSV / JSONL

Restore 会覆盖同名数据库且使用 WITH REPLACE,属于不可逆高风险操作。Verify 只验证备份集可被 SQL Server 读取,不等于完成恢复演练。Export 使用 SELECT *,可能包含全部 PII/Secret。

配置与最小权限

CLI mode 和参数由手写 parser 读取。连接串优先 --connection,否则 Configuration 读取 ConnectionStrings:Default;backup/export directory 与 database name 可来自 DatabaseBackup section。Provider 顺序为 appsettings、local、DBMAINT_ environment、命令行。

{
"ConnectionStrings": {
"Default": "Server=sql-ops;Database=BitzOrcas;User Id=bitz_ops;Password=Secr3t!StrongP@ss;TrustServerCertificate=True"
},
"DatabaseBackup": {
"BackupDirectory": "/var/opt/mssql/backup/bitzorcas",
"ExportDirectory": "/secure-export/bitzorcas",
"DatabaseName": "BitzOrcas"
}
}

配置保存在 gitignored appsettings.local.json。Backup/Restore 账号需要 SQL Server 对应权限;Export 尽量使用只读账号。不要为方便给日常应用连接串授予 restore 权限。

文件系统拓扑是硬约束

BACKUP DATABASE [<database>] TO DISK 路径由 SQL Server 服务进程解释,但工具随后使用本机 FileInfo/File.Exists 读取同一路径。因而 backup directory 必须同时对 SQL Server 与 CLI 进程可见,且路径字符串一致;远程 SQL Server + 开发机本地目录通常不满足。

容器、Kubernetes 或远程 SQL Server 应挂载共享受控卷,并先用非生产小库验证读写身份、UID/GID、SELinux 与路径。工具不会把 .bak 从数据库主机下载到 CLI 主机,也不会上传到对象存储。

全量备份

Terminal window
# 先在隔离环境验证路径与权限;默认 backup type 为 Full。
dotnet run --project src/Tooling/BitzOrcas.DatabaseMaintenance -- \
--backup-database \
--connection "$DB_MAINT_CONNECTION" \
--backup-dir /var/opt/mssql/backup/bitzorcas \
--database BitzOrcas \
--backup-type Full

Full 使用 BACKUP DATABASE [<database>] TO DISK = '<path>' WITH FORMAT, INIT, SKIP, STATS=10,文件名为 <database>_full_<UTC timestamp>.bak。INIT 初始化新生成的目标文件;timestamp 只有秒级,避免并发运行写同一名称。

成功输出文件名、大小与耗时。日志中的 Password/Pwd 会掩码,但运行日志和备份路径仍是敏感运维信息。

差异与日志备份

Terminal window
# 差异备份依赖有效 full base;工具不替你验证整条恢复链。
dotnet run --project src/Tooling/BitzOrcas.DatabaseMaintenance -- \
--backup-database --backup-type Differential \
--connection "$DB_MAINT_CONNECTION" --backup-dir "$BACKUP_DIR"
# Log 备份要求 FULL/BULK_LOGGED recovery model。
dotnet run --project src/Tooling/BitzOrcas.DatabaseMaintenance -- \
--backup-database --backup-type Log \
--connection "$DB_MAINT_CONNECTION" --backup-dir "$BACKUP_DIR"

数据库为 SIMPLE recovery 时,Log backup 返回成功但标记 Skipped=true,CLI 仍退出 0 并打印跳过原因。自动化必须解析/监控 skip,不能把 code 0 当作日志链持续健康。

验证备份

--backup-file 只能是备份目录内的纯文件名;包含 ..、/、\ 或路径成分会被拒绝。服务规范化 full path 并验证仍在 root 内。

Terminal window
# VERIFYONLY 不修改目标数据库,但仍需 SQL Server restore 权限和文件可见性。
dotnet run --project src/Tooling/BitzOrcas.DatabaseMaintenance -- \
--verify-backup \
--connection "$DB_MAINT_CONNECTION" \
--backup-dir "$BACKUP_DIR" \
--backup-file BitzOrcas_full_20260716_020000.bak

底层执行 RESTORE VERIFYONLY FROM DISK = '<path>' WITH STATS=10。验证通过 code 0;SQL 异常会转换成 IsValid=false,CLI code 2。VERIFYONLY 不验证 RTO、应用 smoke、登录/权限、后续差异/日志链或业务数据正确性。

恢复安全门

Restore 需要 --confirm RESTORE 精确匹配。工具先对当前数据库执行 full pre-restore backup,再用指定文件执行 RESTORE DATABASE [<database>] FROM DISK = '<path>' WITH REPLACE, RECOVERY, STATS=10。

Terminal window
# 仅在隔离恢复目标执行;命令本身没有 dry-run。
# file 只能是目录内纯文件名;database 必须再次确认不是生产库。
dotnet run --project src/Tooling/BitzOrcas.DatabaseMaintenance -- \
--restore-database \
--connection "$ISOLATED_RESTORE_CONNECTION" \
--backup-dir "$BACKUP_DIR" \
--backup-file BitzOrcas_full_20260716_020000.bak \
--database BitzOrcas_RestoreDrill \
--confirm RESTORE

如果 pre-restore snapshot 成功而 restore 失败,snapshot 会保留,CLI code 2。操作员必须记录部分状态,不能假设数据库未受任何影响。

恢复演练

  1. 把完整 backup chain 复制/挂载到隔离 SQL Server。
  2. 运行 VERIFYONLY。
  3. 使用新数据库名或专用实例恢复,避免生产名称误连。
  4. 记录开始/结束、文件大小、SQL Server 版本、RTO。
  5. 执行 schema drift、seed、登录、核心 API、JobHost 与消息 smoke。
  6. 对关键表计数/校验和与源快照比较。
  7. 验证账号、权限、加密 key、外部连接和 broker 不会指向生产。
  8. 记录恢复失败和 pre-restore snapshot 的回滚步骤。

只有完成真实 restore + application validation,才能证明备份可用。

单表导出

Terminal window
# CSV 实际使用 ^ 分隔;JSON 选项输出 .jsonl,每行一个对象。
dotnet run --project src/Tooling/BitzOrcas.DatabaseMaintenance -- \
--export-table \
--connection "$READONLY_EXPORT_CONNECTION" \
--export-dir "$SECURE_EXPORT_DIR" \
--table SysPermission \
--format json

表名白名单要求字母/下划线开头、仅字母数字下划线、1–128 字符,并拒绝分号、斜杠、反斜杠和 ..。工具再通过 INFORMATION_SCHEMA.TABLES 验证存在性。

当前只支持无 schema 前缀表名,查询固定 SELECT * FROM [table],不支持列选择、WHERE、tenant filter、脱敏或行数上限。它会流式读取避免整表入内存,但磁盘、网络和数据库扫描成本仍可能很大。

CSV 与 JSONL 语义

CSV 使用 ^ 分隔、header、一行一记录;换行替换为空格,null 输出空串,DateTime/DateTimeOffset 使用 O 格式。当前 formatter 不对字段中的 ^ 做引用/转义,因此含该字符的数据可能破坏列结构。

JSON 输出扩展名 .jsonl,每行一个对象,保留 null 与基础 SQL 值。两种格式都没有字段级脱敏或加密;导出目录必须权限隔离、加密存储并有到期清理。

Terminal window
# 检查权限、文件类型和行数;不要把样本数据输出到公共 CI 日志。
find "$SECURE_EXPORT_DIR" -maxdepth 1 -type f -ls
wc -l "$SECURE_EXPORT_DIR"/*

退出码

Code含义
0操作成功,或 SIMPLE recovery 下 Log backup 被跳过
1缺 mode/connection/file/table、无效 type/format
2备份/恢复/验证/导出业务失败,或确认 token 拒绝
3Ctrl+C 取消;检查部分文件/恢复状态
99未处理致命异常

取消备份/导出可能留下不完整文件;当前 CLI 不自动删除。使用者应按运行 ID 标记并隔离失败制品。

安全与运维清单

  • 工具 Commit、SQL Server 实例、database name 与目录均二次确认;
  • Backup/Restore 与 Export 使用不同最小权限身份;
  • SQL Server 与 CLI 共享同一受控 backup path;
  • 每个 backup 记录 hash、size、type、base/chain 与异地副本;
  • VERIFYONLY 后仍完成真实恢复演练与应用 smoke;
  • Restore 已隔离连接、确认拓扑并准备失败回滚;
  • Export 表经过数据 owner 批准,PII/Secret 有脱敏或禁止导出;
  • ^ 字符、schema 名、超大表等限制已预检;
  • code 0 的 skipped Log backup 有独立告警;
  • 失败/取消产生的部分文件不会进入保留链。

另见

100%

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