加载中…
文档目录
数据库备份

简介

本章节面向DouPHP后台的“数据库备份”功能,说明其全量备份的实现原理、分卷导出机制、压缩打包策略、恢复流程、错误处理与审计日志。同时给出存储路径、命名规范、下载方式等运维要点,并明确当前版本对“增量备份”的支持情况与替代方案。

项目结构

备份能力由控制器、服务层、路由与视图共同实现:

  • 路由定义:声明 backup 相关接口(备份、导入、下载、删除、恢复列表)。
  • 控制器:接收请求参数,调用服务完成具体操作,统一返回消息与跳转。
  • 服务:实现表清单构建、SQL 分卷导出、ZIP 打包、导入执行、删除与流式下载、安全校验等。
  • 视图:展示可备份的表清单、备份设置(文件名、分卷大小)、恢复文件列表与操作入口。
graph TB
A["浏览器/管理员"] --> B["路由: admin/route/backup.php"]
B --> C["控制器: BackupController"]
C --> D["服务: BackupService"]
D --> E["数据库: DB::query / DB::fnExecute"]
D --> F["文件系统: storage/backup/*"]
D --> G["Zip 工具: Zip::create / Zip::extract"]

核心组件

  • 路由组:将 backup 模块下的 index/restore/backup/import/down/destroy 映射到控制器方法。
  • 控制器:提供备份首页、执行备份、恢复列表、导入 SQL、删除备份、下载备份等入口。
  • 服务:封装备份/恢复的核心逻辑,包括表清单、分卷导出、ZIP 打包、导入执行、删除与下载、安全校验。
  • 视图:展示表清单、备份选项、恢复文件列表与操作按钮。

架构总览

备份与恢复的整体交互如下:

sequenceDiagram
participant U as "管理员"
participant R as "路由"
participant C as "BackupController"
participant S as "BackupService"
participant DB as "数据库"
participant FS as "storage/backup"
participant Z as "Zip 工具"
U->>R : 访问备份页面
R->>C : GET /backup/index
C->>S : buildTableList(前缀)
S->>DB : SHOW TABLE STATUS LIKE '前缀%'
DB-->>S : 表清单
S-->>C : 表清单+总大小
C-->>U : 渲染备份表单
U->>R : POST /backup/backup (选择表、文件名、分卷大小)
R->>C : backup()
C->>S : runBackup(前缀, 请求参数)
S->>DB : 逐表导出结构与数据(LIMIT 分页)
DB-->>S : SQL片段
S->>FS : 写入分卷 .sql
alt 需要打包资源
S->>Z : create(zip, [sql..., images])
Z-->>S : 成功/失败
end
S-->>C : 结果(继续/完成)
C-->>U : 提示与跳转(续传或完成)

详细组件分析

备份控制器(BackupController)

  • 职责:组织页面变量、转发请求到服务、统一响应消息与跳转。
  • 关键流程:
    • 备份首页:获取表清单与总大小,生成默认文件名。
    • 执行备份:读取请求参数(act、tables、vol_size、filename、asset 等),调用服务执行分卷备份。
    • 恢复列表:列出 storage/backup 下的可用备份文件(含多分卷合并显示)。
    • 导入 SQL:按 volid 顺序执行分卷导入。
    • 删除备份:二次确认后删除主文件及同前缀分卷。
    • 下载备份:流式输出二进制内容供浏览器下载。

备份服务(BackupService)

  • 表清单构建:查询 INFORMATION_SCHEMA 风格的表状态,统计数据长度与索引长度,计算总大小。
  • 分卷导出:
    • 以 LIMIT offset, size 的方式分页读取每表数据,拼接 INSERT 语句。
    • 当累计 SQL 文本达到分卷阈值时,落盘为分卷文件,并记录下一轮起始行偏移。
    • 支持“仅SQL”和“SQL+images资源”两种模式;后者在完成后打包为 ZIP。
  • 导入执行:
    • 若为 ZIP,先解压至站点根目录,再定位对应 SQL 文件。
    • 按 volid 顺序执行分卷 SQL,直至全部导入完成。
  • 删除与下载:
    • 删除时清理主文件与同前缀分卷,并记录审计日志。
    • 下载采用流式读取,避免大文件内存占用。
  • 安全校验:
    • 严格校验备份文件名,防止目录穿越与非法扩展名。
    • 解压 ZIP 时限定白名单条目(仅允许 storage/backup/*.sql 与 images/**),并拒绝危险扩展名。
flowchart TD
Start(["开始"]) --> CheckName["校验备份文件名合法性"]
CheckName --> |非法| Err["抛出异常并返回错误页"]
CheckName --> |合法| LoadTables["加载待备份表清单"]
LoadTables --> LoopTables{"遍历表"}
LoopTables --> Dump["导出表结构+数据(LIMIT分页)"]
Dump --> Accumulate{"累计SQL是否达到分卷阈值?"}
Accumulate --> |是| WriteVol["写入分卷.sql"]
Accumulate --> |否| NextRow["更新startfrom偏移"]
NextRow --> LoopTables
WriteVol --> LoopTables
LoopTables --> |完成| PostProcess{"是否打包资源?"}
PostProcess --> |是| ZipCreate["Zip::create(sqls, images)"]
PostProcess --> |否| Done["完成"]
ZipCreate --> Done

路由与视图

  • 路由:将 backup 模块的多个动作映射到控制器方法,支持 GET/ANY/DELETE。
  • 视图:
    • 备份页:展示表清单、勾选框、分卷大小输入框、文件名输入框,以及“备份”和“备份并打包资源”两个提交入口。
    • 恢复页:列出 storage/backup 下的备份文件(含多分卷数量提示)、文件大小、创建时间,并提供还原、下载、删除操作。

依赖关系分析

  • 控制器依赖服务:通过构造函数注入 BackupService。
  • 服务依赖:
    • 数据库:使用 DB 门面进行表清单查询、字符集设置、SQL 执行。
    • 文件系统:读写 storage/backup 目录,生成/删除分卷文件。
    • Zip 工具:打包 SQL 与 images 目录,或解压 ZIP 包。
    • 配置:读取站点前缀、版本等信息用于头部注释。
    • 审计:记录备份、恢复、删除操作的审计日志。
classDiagram
class BackupController {
+index()
+backup(request)
+restore()
+import(request)
+destroy(request)
+down(request)
}
class BackupService {
+buildTableList(prefix)
+runBackup(prefix, req)
+runImport(req)
+runDelete(req, post)
+streamDownload(req)
-sqlDumptable(table, vol_size, startfrom, currsize)
-globVolumeFiles(filename, ext)
-isBackupFile(filename)
}
class DB {
+query(sql)
+version()
+charset()
+fnExecute(sql)
}
class Zip {
+create(zipfile, filelist, root_path)
+extract(zipfile, root_path, allow_rules, denied_ext)
}
class FileHelper {
+extension(name)
+filename(name)
+buildFileListByTime(files)
}
class Audit {
+writeAdminLog(admin_id, action, status, msg, tag)
}
BackupController --> BackupService : "调用"
BackupService --> DB : "查询/执行"
BackupService --> Zip : "打包/解压"
BackupService --> FileHelper : "文件信息"
BackupService --> Audit : "写日志"

性能与容量规划

  • 分卷大小:默认 2048KB,可根据服务器 PHP 上传限制与磁盘空间调整。服务会参考 upload_max_filesize 做上限保护。
  • 内存占用:采用 LIMIT 分页读取数据,避免一次性加载整表。
  • I/O 压力:大表导出会产生多次 SELECT 与多次文件写入,建议在低峰期执行。
  • 打包体积:选择“包含资源”会额外打包 images 目录,显著增大 ZIP 体积,按需开启。
  • 并发控制:建议串行执行备份任务,避免与业务高峰冲突。

故障排查指南

  • 无法写入备份目录:检查 storage/backup 是否存在且可写。
  • 文件名不合法:确保文件名不含路径分隔符、盘符、空字节与“..”,扩展名必须为 sql 或 zip。
  • 导入失败:确认 ZIP 已正确解压,SQL 分卷完整并按序执行;关注 MySQL 严格模式下的零日期与 NULL 值处理。
  • 下载异常:检查 Content-Type 与 Content-Length 是否正确设置。
  • 审计日志:备份、恢复、删除操作均会写入管理后台审计日志,便于追踪。

结论

DouPHP 的数据库备份功能提供了稳定的全量备份能力,支持分卷导出与可选的资源打包,具备完善的恢复流程与安全校验。对于生产环境,建议结合外部调度器实现定时备份,并配合异地存储策略保障数据安全。当前版本未内置增量备份机制,可通过外部工具或数据库特性实现增量同步。

附录:定时备份与增量备份说明

定时备份(推荐做法)

  • 使用系统级任务调度(如 Linux cron)定期触发备份脚本或 HTTP 接口。
  • 示例思路:
    • 编写一个 CLI 脚本,调用框架入口并访问备份接口,或使用框架提供的命令行能力(如有)。
    • 在 cron 中设定周期(例如每日凌晨),并记录执行日志。
  • 注意事项:
    • 避开业务高峰期。
    • 合理设置超时与重试策略。
    • 备份完成后清理本地临时分卷文件(服务已完成自动清理)。

增量备份(当前版本说明)

  • 当前实现为全量备份:每次备份都会导出所选表的完整结构与数据。
  • 如需增量备份,可采用以下替代方案:
    • 使用数据库原生工具(如 mysqldump 的 binlog 或 xtrabackup)实现增量/差异备份。
    • 基于 binlog 解析变更事件,将增量变更应用到目标库。
    • 结合对象存储(如 OSS/S3)保存历史备份,保留策略按天/周/月归档。

备份文件命名规范与存储路径

  • 存储路径:storage/backup/
  • 命名规则:
    • 单卷:文件名.sql
    • 多卷:文件名_1.sql、文件名_2.sql……
    • 打包资源:文件名.zip(内含所有分卷 SQL 与 images 目录)
  • 默认文件名:以日期+时间形式生成,也可手动指定;支持 AUTO 前缀自动命名。

验证备份完整性与可恢复性

  • 完整性校验:
    • 检查 ZIP 包内是否包含预期数量的 SQL 分卷与 images 目录。
    • 校验 SQL 文件头部的版本信息与时间戳是否一致。
  • 可恢复性测试:
    • 在测试环境导入备份文件,验证表结构与数据是否完整。
    • 重点关注日期时间列的 NULL 与零日期处理是否符合预期。
  • 回滚预案:
    • 恢复前务必备份当前数据库。
    • 恢复后核对关键业务数据与关联附件。
添加日期:2026-10-05