文档目录
数据迁移

简介

本指南面向数据库管理员与运维工程师,系统化说明 DouPHP 的数据迁移策略、工具使用与执行流程。内容覆盖版本控制与增量升级、回滚机制、迁移脚本编写规范(SQL 标准格式、错误处理、事务管理)、执行流程(环境准备、备份、执行监控、结果验证)、复杂场景(结构变更、数据转换、数据清洗),以及自动化脚本与故障恢复策略。

更新 完全移除了upgrade/目录下的升级系统,包括版本迁移脚本、变更日志服务和升级界面。同时更新了支付对账抽奖服务的锁文件路径从storage/cache迁移到storage/state的说明。传统的模块级升级机制仍然保留,支持通过_update/action.php进行模块级别的升级操作。

项目结构

DouPHP 的数据迁移相关能力主要分布在以下位置:

传统模块级升级

  • 模块升级入口:每个模块的 _update/action.php 负责按版本条件加载并执行该模块的 SQL/PHP 升级脚本
  • 升级脚本:upgrade/data/sql/、upgrade/data/php/、upgrade/data/txt/ 分别存放SQL脚本、PHP逻辑和变更说明

智能存储目录结构

  • 运行时状态目录:storage/state/ 存放需要持久化的运行时状态文件
  • 临时载荷目录:storage/tmp/ 存放短生命周期的工作文件
  • 安装域目录:storage/install/ 管理安装相关的包、会话和记录
  • 缓存目录:storage/cache/ 存放可重建的缓存文件
graph TB
A["模块升级入口<br/>_update/action.php"] --> B["模块升级脚本<br/>data/upgrade.sql / upgrade.php"]
C["后台备份控制器<br/>BackupController"] --> D["备份服务<br/>BackupService"]
D --> E["存储目录<br/>storage/backup/*.sql/.zip"]
F["一次性迁移工具<br/>migrate_data_to_storage.php"] --> G["模块目录<br/>MODULE_PATH/<m>/data -> storage"]
H["智能存储修剪<br/>remove.php"] --> I["storage目录结构<br/>state/tmp/install/cache"]
J["支付对账锁<br/>PaymentReconciliationLottery"] --> K["state/payment_reconcile.lock"]
L["限流存储<br/>AbstractThrottleMiddleware"] --> M["state/throttle/"]
N["未安装拦截<br/>bootstrap.php"] --> O["三级判定链<br/>state → storage根 → data"]

图表来源

  • action.php(模块升级入口):31-51
  • PaymentReconciliationLottery.php:156-169
  • AbstractThrottleMiddleware.php:121-126
  • bootstrap.php:42-60

章节来源

  • action.php(模块升级入口):31-51

核心组件

传统模块级升级组件

  • 模块升级入口:根据客户端版本与最低要求版本对比,决定是否执行模块的 SQL/PHP 升级脚本,并在完成后清理缓存
  • 备份服务:实现分卷 SQL 导出、ZIP 打包(含 images)、多轮续传、导入、删除、流式下载;内置文件名白名单校验与安全解压规则
  • 一次性迁移工具:对 MODULE_PATH 下所有模块进行"仅保留 data"的顶层清理,并将 data 重命名为 storage;支持预览与执行两种模式,具备幂等性约束与错误统计

智能存储管理组件

  • 支付对账锁管理:PaymentReconciliationLottery将锁文件从cache/迁移到state/目录
  • 限流存储管理:AbstractThrottleMiddleware使用storage/state/throttle/目录存储限流计数器
  • 未安装拦截逻辑:bootstrap.php支持三级判定链(state → storage 根 → data)

章节来源

  • action.php(模块升级入口):31-51
  • PaymentReconciliationLottery.php:156-169
  • AbstractThrottleMiddleware.php:121-126
  • bootstrap.php:42-60

架构总览

下图展示从"模块升级入口"到"升级执行"再到"智能存储管理"的整体协作关系。

sequenceDiagram
participant Module as "模块升级入口"
participant Script as "升级脚本"
participant Storage as "智能存储管理"
participant Payment as "支付对账锁"
participant Throttle as "限流存储"
participant Bootstrap as "未安装拦截"
Module->>Script : 检查版本并执行升级
Script->>Storage : 维护storage目录结构
Payment->>Storage : 管理state/payment_reconcile.lock
Throttle->>Storage : 管理state/throttle/目录
Bootstrap->>Storage : 三级判定安装状态

图表来源

  • action.php(模块升级入口):31-51
  • PaymentReconciliationLottery.php:156-169
  • AbstractThrottleMiddleware.php:121-126
  • bootstrap.php:42-60

详细组件分析

传统模块级升级(_update/action.php)

  • 版本判断:读取当前站点版本号后8位与模块要求的最低版本对比,满足条件才执行升级
  • 升级脚本加载:优先执行 data/upgrade.sql(自动替换表前缀),再执行 data/upgrade.php(复杂逻辑)
  • 后置处理:升级完成后清理缓存目录,确保新结构生效
flowchart TD
Start(["进入模块升级"]) --> ReadVer["读取客户端版本"]
ReadVer --> Check{"是否大于最低版本?"}
Check -- 否 --> End(["结束"])
Check -- 是 --> LoadSQL["加载并执行 upgrade.sql"]
LoadSQL --> LoadPHP["加载并执行 upgrade.php"]
LoadPHP --> ClearCache["清理缓存目录"]
ClearCache --> End

图表来源

  • action.php(模块升级入口):31-51

章节来源

  • action.php(模块升级入口):31-51

支付对账锁管理

支付对账锁文件从cache/迁移到state/:

  1. 锁文件位置:state/payment_reconcile.lock
  2. 锁机制:使用flock实现进程间互斥
  3. 零字节长驻:锁文件为0字节,锁态在内核内存中
  4. 自动重建:删除后会重新创建,但可能导致竞态条件
flowchart TD
Start(["支付对账触发"]) --> ResolveDir["解析锁目录"]
ResolveDir --> CheckState{"STORAGE_PATH存在?"}
CheckState -- 是 --> UseState["使用storage/state/"]
CheckState -- 否 --> UseTemp["使用sys_get_temp_dir()"]
UseState --> CreateLock["创建锁文件"]
UseTemp --> CreateLock
CreateLock --> AcquireLock["获取文件锁"]
AcquireLock --> ExecuteTask["执行对账任务"]
ExecuteTask --> ReleaseLock["释放锁"]
ReleaseLock --> End(["完成"])

图表来源

  • PaymentReconciliationLottery.php:156-169

章节来源

  • PaymentReconciliationLottery.php:156-169

限流存储管理

限流计数器存储在storage/state/throttle/目录:

  1. 存储路径:AbstractThrottleMiddleware默认使用storage/state/throttle/作为参数
  2. 配置覆盖:可通过security.throttle.store配置项自定义路径
  3. 文件命名:每个限流键对应一个JSON文件,文件名为md5(key).json
  4. 数据结构:{count: int, reset: timestamp}

章节来源

  • AbstractThrottleMiddleware.php:121-126

未安装拦截逻辑

bootstrap.php实现了三级判定链来检测安装状态:

  1. 优先级顺序:storage/state/install.lock → storage/install.lock → data/install.lock
  2. 安装页面保护:install目录下的请求不受拦截限制
  3. 自动跳转:未安装时自动跳转到安装页面
flowchart TD
Start(["应用启动"]) --> CheckState["检查storage/state/install.lock"]
CheckState -- 存在 --> InstallOK["已安装"]
CheckState -- 不存在 --> CheckRoot["检查storage/install.lock"]
CheckRoot -- 存在 --> InstallOK
CheckRoot -- 不存在 --> CheckData["检查data/install.lock"]
CheckData -- 存在 --> InstallOK
CheckData -- 不存在 --> CheckInstallPage{"是否在install页面?"}
CheckInstallPage -- 是 --> AllowAccess["允许访问"]
CheckInstallPage -- 否 --> Redirect["重定向到安装页面"]

图表来源

  • bootstrap.php:42-60

章节来源

  • bootstrap.php:42-60

依赖关系分析

  • 模块升级入口:依赖配置中心获取版本信息,依赖数据库层执行 SQL,依赖文件系统清理缓存
  • 支付对账锁:依赖flock文件和STORAGE_PATH常量
  • 限流存储:依赖AbstractThrottleMiddleware类和storage/state/throttle/目录
  • 未安装拦截:依赖bootstrap.php中的STORAGE_PATH常量和三级判定逻辑
graph LR
A["模块升级入口"] --> B["数据库层"]
A --> C["配置中心"]
A --> D["文件系统"]
E["支付对账锁"] --> F["flock"]
E --> G["STORAGE_PATH"]
H["限流存储"] --> I["AbstractThrottleMiddleware"]
H --> J["state/throttle/"]
K["未安装拦截"] --> L["bootstrap.php"]
K --> M["STORAGE_PATH"]

图表来源

  • action.php(模块升级入口):31-51
  • PaymentReconciliationLottery.php:156-169
  • AbstractThrottleMiddleware.php:121-126
  • bootstrap.php:42-60

章节来源

  • action.php(模块升级入口):31-51
  • PaymentReconciliationLottery.php:156-169
  • AbstractThrottleMiddleware.php:121-126
  • bootstrap.php:42-60

性能考虑

  • 模块升级优化:仅在满足版本条件时执行升级脚本,避免不必要的I/O操作
  • 锁文件优化:payment_reconcile.lock使用内核级flock,避免用户态文件竞争
  • 限流存储优化:AbstractThrottleMiddleware使用文件锁确保并发安全,机会式清理避免频繁IO操作
  • 未安装拦截优化:三级判定链快速检测安装状态,减少文件系统查询次数

故障处理与恢复指南

模块升级故障处理

  • 前置检查:确认模块的_minimum_version_number设置正确
  • 脚本权限:确保data/upgrade.sql和data/upgrade.php具有正确的读写权限
  • 缓存清理:升级失败后手动清理cache目录,确保新结构生效
  • 版本兼容性:检查客户端版本与模块最低版本要求的兼容性

支付对账锁故障处理

  • 锁文件位置:确认锁文件位于storage/state/payment_reconcile.lock
  • 锁冲突解决:如果发生锁冲突,重启服务或手动删除锁文件
  • 目录权限:确保storage/state/目录具有正确的写权限
  • 异常处理:任何异常都会被捕获,不影响主请求流程

限流存储故障处理

  • 存储路径:检查storage/state/throttle/目录是否存在且可写
  • 配置文件:如使用自定义路径,确认security.throttle.store配置正确
  • 文件清理:定期清理过期的限流文件,避免目录无限增长

未安装拦截故障处理

  • 安装状态检测:确认storage/state/install.lock文件存在
  • 权限问题:确保storage/state/目录具有正确的读写权限
  • 安装页面访问:确认install目录下的请求不被拦截

章节来源

  • action.php(模块升级入口):31-51
  • PaymentReconciliationLottery.php:156-169
  • AbstractThrottleMiddleware.php:121-126
  • bootstrap.php:42-60

结论

DouPHP 的数据迁移体系由"传统模块级升级 + 智能存储管理"构成,保持了简洁性和可靠性。虽然完全移除了upgrade/目录下的升级系统,但传统的_update/action.php机制仍然有效,支持模块级别的升级需求。通过严格的文件名校验、锁机制和三级判定逻辑,提供了可靠的迁移与状态管理能力。

更新 完全移除了upgrade/目录下的升级系统,简化了整体架构。同时更新了支付对账抽奖服务的锁文件路径从storage/cache迁移到storage/state,提升了系统的稳定性和可维护性。传统的模块级升级机制继续发挥作用,确保了现有功能的向后兼容性。

附录:迁移脚本编写规范与最佳实践

传统模块级升级规范(_update/action.php)

  • 版本控制:在模块 _update/action.php 中维护 minimum_version_number,确保只在满足条件时执行升级
  • 脚本组织:升级脚本放置于模块 data/ 目录下:upgrade.sql(DDL/DML)与 upgrade.php(复杂逻辑)
  • 前缀处理:SQL 脚本应使用表前缀占位符,由入口统一替换,避免硬编码

SQL标准格式

  • 事务包裹:使用事务包裹关键 DML,确保原子性;失败时回滚
  • 兼容性处理:对日期时间列的空值与零日期进行兼容处理,避免严格模式下导入失败
  • 批量操作:批量插入时注意分卷与内存占用,避免超时与 OOM
  • 索引优化:先删除旧索引,再添加新索引,避免锁竞争

智能存储目录管理规范

  • 目录职责分离:
    • state/:存放需要持久化的运行时状态文件
    • tmp/:存放短生命周期的临时文件
    • install/:管理安装相关的包、会话和记录
    • cache/:存放可重建的缓存文件
  • 文件迁移规则:
    • 从storage根迁移到state/:install.lock、quick.start.dou、payment_reconcile.lock
    • 从cache/迁移到tmp/:admin_dirrelocate{token}.php等临时文件
    • 从storage/installed/迁移到storage/install/records/:*.installed.php

支付对账锁管理规范

  • 锁文件位置:state/payment_reconcile.lock
  • 锁机制:使用flock实现进程间互斥,避免竞态条件
  • 零字节长驻:锁文件为0字节,锁态在内核内存中
  • 自动重建:删除后会重新创建,但可能导致竞态条件

限流存储管理规范

  • 存储路径:AbstractThrottleMiddleware使用storage/state/throttle/目录
  • 配置覆盖:可通过security.throttle.store配置项自定义路径
  • 文件命名:每个限流键对应md5(key).json文件
  • 数据结构:{count: int, reset: timestamp}

未安装拦截管理规范

  • 三级判定链:storage/state/install.lock → storage/install.lock → data/install.lock
  • 安装页面保护:install目录下的请求不受拦截限制
  • 自动跳转:未安装时自动跳转到安装页面

错误处理

  • 异常捕获:捕获异常并记录日志;对不可恢复错误给出明确提示与回滚指引
  • 文件操作:对文件操作(读写、解压)进行存在性与权限检查,失败时中止并告警
  • 网络容错:外部API调用失败不应阻塞主流程,应提供降级方案

事务管理

  • 显式事务:对跨表更新、关联数据迁移使用显式事务;提交前进行一致性校验
  • 长事务优化:长事务需评估锁竞争与锁等待,必要时拆分为小批次
  • 回滚策略:确保所有事务都有明确的回滚路径

执行流程

  • 环境准备:确认数据库连接、字符集、时区与磁盘空间
  • 备份策略:执行全量或增量备份,必要时打包 images
  • 执行监控:观察分卷进度、错误日志与审计日志
  • 结果验证:核对关键表行数、索引、外键与业务指标

复杂场景处理

  • 数据结构变更:先新增字段/表,再逐步迁移数据,最后删除旧字段/表
  • 数据转换:在 PHP 侧进行清洗与映射,分批写入目标表,避免一次性加载
  • 数据清洗:建立清洗规则与校验清单,对异常数据进行隔离与修复
  • 零日期处理:使用专门的函数清洗历史零日期数据,确保与新版本的严格模式兼容

工具与自动化

  • 模块升级:继续使用_update/action.php进行模块级升级
  • 备份恢复:使用 BackupService 提供的接口进行备份/导入/下载/删除,结合 CI/CD 实现自动化
  • 存储修剪:使用 remove.php 工具进行智能存储目录清理,支持预览和执行模式
  • 锁文件管理:监控state/payment_reconcile.lock的状态,处理可能的竞态条件
  • 限流存储管理:定期检查storage/state/throttle/目录,清理异常的JSON文件

故障恢复

  • 升级失败:一旦升级失败,立即从最近备份恢复;若 ZIP 包包含 images,一并还原
  • 代码回退:对无法恢复的问题,定位日志并回退代码与脚本,重新演练
  • 版本回滚:通过备份恢复到升级前的状态,确保业务连续性
  • 存储结构修复:使用remove.php工具重新整理storage目录结构
  • 锁文件冲突解决:重启服务或手动删除payment_reconcile.lock后重建

章节来源

  • action.php(模块升级入口):31-51
  • PaymentReconciliationLottery.php:156-169
  • AbstractThrottleMiddleware.php:121-126
  • bootstrap.php:42-60
添加日期:2026-10-05