CPT交付实施手册
展开步骤目录

网信办前厅两套 Store 部署与迁移手册

2026-10-24 数据库步骤更新: 本次两份备份已完成版本升级、达梦转换及隔离演练。数据库部分请改用本次交付说明与两套导入手册,按现场探测、完整SQL/LOB导入及对账执行,不重复运行下面旧版DTS路线或MySQL升级脚本。前厅应用制品需包含本次8文件兼容修复;后续环境及应用验收章节仍可参考。本页在线发布版本尚未同步此更新,以本地新手册为准。

旧服务器 → 新麒麟服务器|zhct / zhct2 → 达梦|新手分步操作版

范围已按用户于2026-10-21的明确说明修正:两套独立部署的 Store,第一套数据库为 zhct,第二套为 zhct2。本册只迁移这两套程序、两个业务库及它们实际使用的文件、任务和设备连接。

本版替代此前错误扩大范围的前厅手册。目标是:两套 Store 数据完整迁移、业务能继续使用、设备和任务正常、故障时能按条件回退。共享 Nginx、PHP 或 Redis 时,重启与配置修改必须核对同机其他系统的影响。

已核对原始资料并依据用户纠正收敛范围;尚未登录客户服务器执行安装或迁移。现场地址、端口、口令、发布包和升级 SQL 按第02—04步填写和领取,不能凭文档猜测。缺少制品时停在准备阶段,不让初学者临场编写升级或迁移SQL。

使用前|这次只迁移哪两套系统

项目 前厅第一套 前厅第二套
程序仓库 store store
新机程序目录(本册约定) /data/apps/front1/store /data/apps/front2/store
原 MySQL 业务库 zhct zhct2
正式达梦用户/同名模式(建议名) ZHCT_APP ZHCT2_APP
演练达梦用户/同名模式(本册约定) ZHCT_REH ZHCT2_REH
PHP 按本套冻结的Store发布包要求 按本套冻结的Store发布包要求
客户配置、文件、队列、任务、设备 第一套单独核对 第二套单独核对

达梦模式名是建议值,不表示现场已经创建;厂家已有正式命名时,全册及现场表统一替换。两套是独立部署,但不能由此推定有两台MySQL服务器:zhct和zhct2可能在同一实例,也可能在不同实例,先现场核实。

原Store路线使用PHP 7.3,本文安装示例采用 /usr/local/php。两套若使用同一验收版本,可共用这一套PHP运行环境;若实际版本不同,由应用负责人提供已验收的各自安装和驱动清单。不能因“两个系统”自动要求安装第二种PHP版本。

数据库对应关系只有:第一套Store → zhct → ZHCT_APP;第二套Store → zhct2 → ZHCT2_APP。 演练时分别连接ZHCT_REH、ZHCT2_REH。通用代码仓库里存在其他功能配置,不构成本项目启用那些服务或数据库的证据;如果实际请求仍要求范围外连接,交应用负责人核对客户功能开关和发布包,不能由实施人员额外建库凑配置。

操作规则|看懂位置、命令和结果再继续

四个工作位置

标记 你在哪里操作 主要工作
【电脑】 自己的办公电脑 SSH、传文件、浏览器、达梦图形工具
【旧机】 当前正在营业的服务器 盘点、备份、正式停写;保留旧代码和旧数据库
【新机】 准备接管业务的麒麟服务器 安装环境、部署应用、连接达梦
【临时 MySQL】 独立的演练/中转机器或隔离实例 恢复备份、执行版本升级、作为迁移源

达梦服务端已由厂家安装。本次不重新初始化达梦,不移动厂家数据文件,也不在正式新机直接运行旧 MySQL 一键安装脚本。

命令怎么用

  1. 每次先看“执行位置”。SSH 新开窗口后运行 hostname、whoami、pwd,确认机器和身份。
  2. 复制一小段执行,读结果,再做下一段。灰色框标为 sql 的内容在数据库工具里执行;ini/php 是文件内容,不往终端直接粘贴。
  3. CHANGE_ME 表示必须填写;/实际路径/ 表示现场路径。没有替换完不能执行。 shell 变量只在当前窗口有效,换窗口需重新设置。
  4. 文件名带 .example 的是模板,不是现场已验证配置。先另存到受控目录、填写并复核,不覆盖原文件。
  5. 执行一个命令后,可紧接着输入 echo $? 查看退出码,0 通常表示该命令成功;还要满足每步的业务检查。不要隔了其他命令再查退出码。
  6. 遇到 Permission denied、not found、ERROR、FAILED,停在当前步骤;保存时间和错误位置,交给对应负责人。不要靠反复执行、加 --force 或删除目录试错。
  7. 用 vi 文件名 编辑:按 i 修改,按 Esc,输入 :wq 回车保存;放弃本次编辑用 :q!。密码文件用私有编辑器填写,不把密码放命令行、截图或本登记表。

谁来做

实施人员负责按表操作和收集结果;应用负责人提供已验收的应用包、升级 SQL、任务清单;数据库管理员负责达梦目标创建、类型映射、异常数据处理和恢复;客户/网络管理员负责停机窗口、入口切换与业务签认。新手遇到“管理员处理”的步骤,照清单把材料交齐、拿回结果即可,不需要临时学习数据库开发。

顺序总览

阶段 步骤 放行条件
准备 01—06 参数、制品齐全,旧机备份可恢复
新机安装 07—11 Nginx、Store PHP、达梦驱动、必要中间件通过
演练 12—21 两库迁移、两套程序及设备业务完整验证
正式窗口 22—26 旧机停写、最终数据迁完、对账后接管
观察和交接 27—28 重启、备份恢复、就餐高峰及回退方案验证

配套文件:现场参数表、制品领取表、逐步验收表。先下载,另存到客户受控目录填写;填过地址和内部路径的版本不再上传公共文档站。

01|建立三个连接,并给窗口标清楚

执行位置:【电脑】。本步不改变服务器。

  1. 准备有 SSH 功能的终端、SFTP 文件传输工具和浏览器。Windows 可用现有终端/运维工具,macOS 可用“终端”;不要在客户机临时下载来路不明的工具。
  2. 向运维领取旧机、新机、临时 MySQL 的地址、SSH 端口、账号和登录方式,密码通过私有渠道领取。
  3. 分别创建会话并命名为“旧机—营业中”“新机—迁移目标”“临时机—可恢复副本”。
  4. 登录后逐个执行:
hostname
whoami
pwd
cat /etc/os-release
uname -m

SSH 命令形态为 ssh -p SSH端口 账号@服务器地址;第一次连接先与运维核对主机指纹,不凭提示直接接受。输入密码时不显示字符是正常现象。

  1. 在现场参数表记录 hostname、系统版本、架构和用途。新机应与发布包的架构匹配;x86_64 与 aarch64 包不能混用。
  2. 通过 SFTP 查看新机的 /data、/workspace 是否存在,先不拖放文件。

成功结果: 三个会话能登录,名称和 hostname 对得上。失败处理: 超时找网络管理员;认证失败核对账号、端口和登录方式;不通过扫描其他服务器找“能进去的一台”。

02|把两套 Store 的现场参数填齐

执行位置:【旧机】只读盘点;【电脑】填写现场表。

  1. 在浏览器分别打开两套旧系统,记录地址、单位/餐厅名称、登录角色及一条可区分的历史业务记录。含个人信息的记录只留客户受控目录。
  2. 在旧机查看各站点实际Nginx配置,找到两个Store程序根目录,确认对应的数据库分别是zhct、zhct2。
  3. 按下表分别填写,不复制第一套配置当第二套答案。
分类 两套各自要填写 如何找
程序 绝对目录、版本、部署负责人 Nginx root、原部署记录、版本清单
数据库 主机、端口、MySQL版本、库名、表前缀 生效database.php及DBA只读查询
配置入口 env.php中的TP_ENV/BUSINESS、生效database.php 第17步加载规则
PHP 实际可执行路径、版本、ini、FPM服务/pool/listen、用户 php --ini、FPM配置、systemd
网站 HTTP/HTTPS、域名、端口、root、rewrite、证书 nginx -T及实际访问
文件 上传、附件、外置挂载、对象存储、日志 客户配置、Nginx alias及实际上传
Redis 地址、DB编号、前缀、队列与去重用途 客户配置及任务负责人
任务 Cron、Supervisor、Workerman、watchdog、运行用户、启停命令 crontab、服务配置和原部署记录
设备 消费机、打印、MQTT、回调、同步、白名单 客户实际启用清单

只读辅助命令:

ss -lntp
systemctl list-units --type=service --all
systemctl list-timers --all
crontab -l
crontab -u www -l
supervisorctl status

没有安装的组件记“不适用”,不为凑齐命令新增组件。检查所有实际任务用户,不仅root/www。Nginx配置和环境输出可能有内部地址或口令,只在客户受控目录查看。

成功结果: 两套Store与zhct/zhct2一一对应,文件、设备和全部写入任务有清单。失败处理: 缺项登记负责人补齐;不能猜第二套库名、目录和端口。

03|检查新机、磁盘和已安装达梦

执行位置:【新机】管理员;数据库信息由厂家/DBA核查。

findmnt -T /data
findmnt -T /workspace
df -h /data /workspace
df -i /data /workspace
free -h
timedatectl
command -v dnf yum apt-get
systemctl list-unit-files | grep -Ei 'DmService|DmAP'
  1. /data 放应用、在线附件和当前日志;/workspace 放离线介质及历史包。必须在厂家已用目录外规划本项目子目录。
  2. 容量按“程序+文件+演练与正式数据+索引+日志+备份临时占用+增长”计算。不能只比较旧 SQL 文件大小;建议保留至少 20% 空闲,由管理员给出实际容量结果。
  3. 新旧机时区和时间一致。麒麟不同版本的包管理器不同,依据上面的实际结果选择,不看到“麒麟”就直接执行 apt。
  4. 用达梦管理工具连接厂家指定实例,在 SQL 查询窗口执行以下只读查询,保存脱敏结果:
SELECT * FROM V$VERSION;
SELECT NAME FROM V$DATABASE;
SELECT INSTANCE_NAME, STATUS$ FROM V$INSTANCE;
SELECT PARA_NAME, PARA_VALUE
FROM V$DM_INI
WHERE PARA_NAME IN ('COMPATIBLE_MODE','MY_STRICT_TABLES',
                   'ORDER_BY_NULLS_FLAG','LENGTH_IN_CHAR','PORT_NUM');
  1. DBA 核实 build、端口、字符集、大小写规则、页大小、授权有效期、归档和备份可用空间。原报告记载 5236、UTF-8、32K、大小写不敏感及 MySQL 兼容模式;这些是历史记录,必须现场复核。
  2. 不能为了和文档一致重新初始化数据库;需要调整实例参数时由厂家另行评估及执行。

成功结果: 架构、空间、时间、有效授权和实例参数均满足冻结发布包要求。失败处理: 交 DBA/运维处理后复验;有 TCP 连接不等于数据库已验收。

04|领齐两个 Store 发布包和两库升级材料

执行位置:【电脑/制包机】;应用负责人交付,停机前完成。

建议受控介质结构如下。这是领取要求,不表示本文已附带这些安装包:

cac-front-kit/
  runtime/             Store所需PHP、扩展、达梦客户端及必要中间件
  os-rpms/             同版麒麟离线依赖
  front1/store/        第一套冻结发布目录
  front2/store/        第二套冻结发布目录
  sql/zhct/            预检、编号升级段、每段后验
  sql/zhct2/           预检、编号升级段、每段后验
  checks/              DTS任务、类型映射、对账及任务/路由清单
  MANIFEST.sha256
  1. 两套均为本客户验收过的Store达梦适配版,附提交号、SHA256、运行版本和功能回归结果。普通MySQL旧包不能只修改连接后当作适配版。
  2. 两套各带完整vendor、运行资源及实际启用的前端dist;至少核对发布版Store后台入口(原路线为public/dist/index.html),其他页面按本客户已启用清单,不新增其他仓库。
  3. 准备Store所需PHP精确版本、ABI、TS/NTS、CPU架构,以及对应DM/PDO_DM驱动、完整DPI动态库和扩展。两套版本相同无需重复装两种PHP。
  4. zhct、zhct2分别提供结构预检、编号升级SQL和后验。store/db/init/zywxb/zywxb.sql的原目标和基线须审查,不能原样执行两次;无需升级的库也要有“比对通过,无需升级”结论。
  5. 领取已演练的两个DTS任务、逐列类型映射、独立逐表/业务对账工具、两套客户配置与任务差异表。
  6. 离线依赖和源码缓存须在同版麒麟断网试装;安装器控制包不等于完整离线安装包。
  7. 发布介质不含真实密码、生产dump和授权文件;这些通过客户批准的私有渠道交接。

制包端生成校验清单:

cd /实际介质父目录/cac-front-kit
set -o pipefail
find runtime os-rpms front1 front2 sql checks -type f -print0 \
  | sort -z | xargs -0 sha256sum > MANIFEST.sha256

成功结果: 制品领取表必需项全部齐全且验收通过。失败处理: 缺包、缺SQL或适配未验收时继续准备,不通知客户开始停机。

05|备份旧机程序、配置、上传文件和任务

执行位置:【旧机】;避开高峰,先确认备份盘容量。

  1. 创建本次独立目录,以下日期时间由命令生成;把输出路径记入登记表。
umask 077
RUN_ID=$(date +%Y%m%d-%H%M%S)
BACKUP="/backup/cac-front/rehearsal-$RUN_ID"
install -d -m 700 "$BACKUP"
printf '%s\n' "$BACKUP"
df -h "$BACKUP"
  1. 对第 02 步登记的两个 Store 程序目录逐个打包。下面为单目录模板,填好后分别执行两次,输出包名不能重复:
APP_PARENT='CHANGE_ME_旧程序父目录'
APP_NAME='CHANGE_ME_该父目录下的程序目录名'
OUT_NAME='CHANGE_ME_唯一包名'
case "$APP_PARENT$APP_NAME$OUT_NAME" in *CHANGE_ME*) echo '先填实际目录和包名'; exit 1;; esac
test -n "$BACKUP" && test -d "$BACKUP" && test -d "$APP_PARENT/$APP_NAME" || exit 1
if tar --acls --xattrs -czpf "$BACKUP/$OUT_NAME.tar.gz.part" \
  -C "$APP_PARENT" "$APP_NAME"; then
  mv "$BACKUP/$OUT_NAME.tar.gz.part" "$BACKUP/$OUT_NAME.tar.gz"
  tar -tzf "$BACKUP/$OUT_NAME.tar.gz" >/dev/null || exit 1
else
  echo '打包失败,保留part检查;不要当作有效备份'; exit 1
fi

备份输出不能位于被打包目录内。在线文件变化可能使打包返回非零,需核对原因并重做;正式停写后还要再备份。

  1. 用同样方式备份实际 Nginx、PHP/FPM、Supervisor、任务脚本、证书和其他前厅配置目录。外置上传目录另打包,软链接指向的真实数据单独收集,不能只备份链接。
  2. 保存任务:crontab -l、各应用用户 crontab、Supervisor 指定 program 配置、systemd timers、Workerman 启停命令及 watchdog。现有任务为空时记“无”,不要把读取失败当成空。
  3. Redis 中的队列、去重标记、会话和缓存由负责人分类,明确保留方法;禁止运行 FLUSHALL/FLUSHDB。共享 Redis 不整体覆盖。
  4. 将备份复制到另一受控存储位置,核对 SHA256。备份含私密配置,访问权限限定为实施人员。

成功结果: 两套 Store 程序、文件、配置、任务全部可读且有异机副本。失败处理: 校验不一致重新传输;缺文件回到目录清单补备,不能用 Git 源码替代客户上传附件。

06|备份两个 MySQL 库,并确认能恢复

执行位置:【旧机】备份;恢复证明在第 12 步完成。

先由 DBA 核对两库是在同一个 MySQL 实例还是多个实例,以及是否存在 MyISAM 等非事务表。原手册前厅以 MySQL 5.6 为基线,以现场版本为准。

  1. 创建私有连接文件(下例管理员使用 /root/cac-front-source.cnf),用编辑器填真实值:
[client]
host=CHANGE_ME_旧MySQL地址
port=CHANGE_ME_旧MySQL端口
user=CHANGE_ME_备份账号
password=CHANGE_ME_私有密码
chmod 600 /root/cac-front-source.cnf
  1. 选择与源版本匹配的客户端,先只读确认连接到了旧库,以下路径必须替换:
MYSQL_BIN='CHANGE_ME_MySQL客户端bin目录'
case "$MYSQL_BIN" in *CHANGE_ME*) echo '先填客户端目录'; exit 1;; esac
"$MYSQL_BIN/mysql" --defaults-extra-file=/root/cac-front-source.cnf \
  -e 'SELECT @@hostname,@@port,VERSION(); SHOW DATABASES;'
  1. 如果两个库名确实为下列名称,且都在同一实例,执行一次导出以保持同一事务快照。正式备份时将 BACKUP 换为最终备份的新目录:
test -n "$BACKUP" && test -d "$BACKUP" || exit 1
if "$MYSQL_BIN/mysqldump" --defaults-extra-file=/root/cac-front-source.cnf \
  --single-transaction --quick --routines --events --triggers \
  --hex-blob --default-character-set=utf8mb4 \
  --databases zhct zhct2 \
  > "$BACKUP/front.sql.part" 2> "$BACKUP/front.err"; then
  test -s "$BACKUP/front.sql.part" || exit 1
  mv "$BACKUP/front.sql.part" "$BACKUP/front.sql"
else
  echo '导出失败,查看front.err,不使用part文件'; exit 1
fi
cd "$BACKUP" || exit 1
sha256sum front.sql > front.sql.sha256
sha256sum -c front.sql.sha256

若zhct、zhct2分属不同MySQL实例: 不执行上面合并两库的命令。分别创建两个私有cnf并核验主机/端口;第一份沿用上面的if导出结构,但--databases只写zhct,输出改为front1.sql.part/front1.sql/front1.err;第二份使用第二实例cnf,--databases只写zhct2,输出改为front2.sql.part/front2.sql/front2.err。各自成功后生成SHA256。恢复时逐份选择匹配的临时实例,第12步的FRONT_DUMP/RESTORE_LOG也分别设置,不能覆盖上一份日志。两实例正式导出必须都在共同停写后完成。

  1. 查看 front.err,处理全部错误和影响完整性的警告。使用 MySQL 8 或启用 GTID 时,DBA 按对应版本决定 --set-gtid-purged=OFF 等参数,不把 MySQL 8 专属选项直接加到 5.6。
  2. 非事务表不能只靠 --single-transaction 保证一致;由 DBA 安排停写/锁表。在线备份期间不执行 DDL。跨实例在正式阶段用统一停写获得共同截止口径。
  3. 传输 front.sql、front.sql.sha256 到隔离临时机;进入同目录再运行 sha256sum -c front.sql.sha256。

成功结果: 导出退出码 0、文件非空、日志可解释、异机哈希一致;第 12 步恢复成功后才算“备份可用”。失败处理: 保留 .part 与错误日志,解决后在新目录重新备份。

07|上传介质并建立新机目录

执行位置:【新机】管理员。

  1. 用 SFTP 将第 04 步介质目录上传为 /workspace/cac-front-kit;确认不是误传到了旧机。
  2. 校验介质:
cd /workspace/cac-front-kit || exit 1
sha256sum -c MANIFEST.sha256

所有条目应为 OK,命令退出码必须为 0。出现缺文件或 FAILED,重新传输,不继续安装。

  1. 查看以下目录是否已存在。已有正式内容时先核对归属,不向其中直接解压覆盖。新规划空目录可执行:
install -d -m 755 /data/apps/front1/store
install -d -m 755 /data/apps/front2/store
install -d -m 755 /data/app-logs/front1 /data/app-logs/front2
install -d -m 700 /data/migration/cac-front/evidence
install -d -m 700 /data/migration/cac-front/private
  1. 用 id www 确认 PHP/Nginx 运行用户;若 LNMP 尚未安装,待第 08 步安装器创建后再检查。不要对整个 /data 改 owner。
  2. 代码由发布账号维护;上传、日志、缓存目录才给对应运行用户写权限。保留 SELinux 等现有安全策略,不能用 chmod -R 777 解决权限问题。

成功结果: 介质校验全部通过,目录与数据库厂家目录分离。失败处理: 空间不足先调整容量;目录已有未知数据先查归属。

08|安装或核验 Store 所需的 Nginx 和 PHP

执行位置:【新机】管理员;共享服务变更安排窗口。

8.1 先看已有环境

本册示例为原Store路线PHP 7.3与LNMP,必须与冻结发布包一致。若已有宝塔或其他管理方式,采用现场路径,不重复安装另一套Nginx。

PHP_ROOT=/usr/local/php
NGINX=/usr/local/nginx/sbin/nginx
"$PHP_ROOT/bin/php" -v
"$NGINX" -v

两套Store若使用同一PHP版本,以上环境可共用;各自网站root、客户配置、文件与任务仍独立。系统php -v不能替代指定绝对路径的检查。

8.2 缺失才安装

  1. 运维核对麒麟版本、架构和包管理器,使用通过同环境试装的离线介质。
  2. 原LNMP 2.2控制包lnmp2.2-from-git-20260706.tar.gz的SHA256为9cdc130f859bfca6cbd138950128fda358b88fb1ebadad4f937ebc4560fe990b;仅这个约25MB包并不保证离线安装,要同时领取源码缓存和系统依赖。
  3. 确认为yum系统且目录仅含本次依赖时,执行:
yum --disablerepo='*' install /workspace/cac-front-kit/os-rpms/*.rpm
  1. 在全新安装目录先用tar -tzf 包路径看顶层结构,再解压,进入实际包含install.sh的目录。
  2. 执行bash install.sh lnmp,数据库菜单选 0,不装MySQL服务端;PHP选冻结的Store版本,原路线为7.3.33。其他菜单按制品单,不临时改版本。
  3. 安装失败保存日志交运维处理;不替换系统glibc、不使用--nodeps硬装、不为了两个站点执行多版本PHP安装。

8.3 核验环境

"$PHP_ROOT/bin/php" --ini
"$PHP_ROOT/bin/php" -m
"$PHP_ROOT/sbin/php-fpm" -t
systemctl list-unit-files | grep -Ei 'nginx|php.*fpm'

至少核对PDO、curl、mbstring、openssl、fileinfo、bcmath、gd、zip、redis及实际启用扩展。记录PHP精确版本、ini、FPM服务名、pool、监听和运行用户。缺扩展按该版本phpize/php-config编译,不复制其他PHP版本的.so。

成功结果: Store所需环境和扩展齐全,FPM配置测试通过。失败处理: 补齐依赖后复验,未通过不部署应用。

09|安装与 Store PHP 匹配的达梦驱动

执行位置:【新机】管理员;安装客户端驱动,不重装达梦。

  1. 厂家按当前DM build、CPU架构、PHP精确版本、ABI和TS/NTS提供驱动与DPI依赖。原PHP7.3 NTS常见文件为libphp73_dm.so与php73_pdo_dm.so;以本次实物和版本要求为准。
  2. 建立独立客户端目录:
install -d -m 755 /opt/dm-client/lib /opt/dm-client/php73
  1. 用SFTP或经审核的复制命令将完整客户端动态库放入/opt/dm-client/lib,将匹配的两个扩展放入/opt/dm-client/php73。保持软链接及其目标完整,文件可读,不复制授权文件或数据库数据文件。已存在目录先核对归属和版本,不能覆盖其他应用依赖。
  2. 核验版本和依赖:
/usr/local/php/bin/php -i | grep -E 'PHP API|PHP Extension Build|Thread Safety'
file /opt/dm-client/php73/*.so
for f in /opt/dm-client/php73/*.so; do
  LD_LIBRARY_PATH=/opt/dm-client/lib ldd "$f"
done
  1. 所有ldd输出不得出现not found。如冻结PHP版本不是7.3,以上目录及扩展使用负责人提供的对应版本,不把驱动改名。
  2. 用php --ini和php-fpm -i分别确定CLI/FPM加载的ini;每份实际文件先备份再编辑,追加:
extension=/opt/dm-client/php73/libphp73_dm.so
extension=/opt/dm-client/php73/php73_pdo_dm.so

已有加载项不重复,PDO已内置时不添加不存在的pdo.so。CLI与FPM生效ini不同则分别配置;两套Store若使用不同PHP运行时,由负责人按各自版本重复驱动核验。

成功结果: 驱动匹配、依赖齐全、实际ini配置正确。失败处理: 架构/ABI不匹配向厂家换驱动,不强装或改名。

10|配置中文编码、FPM和后台任务环境

执行位置:【新机】管理员。

  1. 创建专用/etc/zhct-dm-client/dm_svc.conf,已有文件先备份并核对用途,再合并:
TIME_ZONE=(480)
LANGUAGE=(CN)
CHAR_CODE=(PG_UTF8)

这不是数据库服务端dm.ini。目录可读可穿越,文件建议0644。

  1. 使用systemctl cat 实际PHP服务名确认服务,再执行systemctl edit 实际PHP服务名加入:
[Service]
Environment="LD_LIBRARY_PATH=/opt/dm-client/lib"
Environment="DM_SVC_PATH=/etc/zhct-dm-client"

已有动态库目录保留必要内容再追加。非systemd管理时按现有方式配置,不另建重复服务。

  1. 在实际FPM pool配置中加入,已有同项不重复:
env[DM_SVC_PATH] = /etc/zhct-dm-client
  1. /usr/local/php/sbin/php-fpm -t通过后执行systemctl daemon-reload,按登记表重启实际PHP服务,检查状态active。共用FPM会影响两个站点及其他共用业务,必须安排窗口。
  2. CLI检查:
export LD_LIBRARY_PATH=/opt/dm-client/lib
export DM_SVC_PATH=/etc/zhct-dm-client
/usr/local/php/bin/php -r 'var_export(PDO::getAvailableDrivers());'

结果应有dm。其他必要动态库路径也须保留。

  1. Cron、Supervisor、Workerman分别设置明确PHP路径和上述环境,不能依赖SSH临时export。任务形态:
env LD_LIBRARY_PATH=/opt/dm-client/lib DM_SVC_PATH=/etc/zhct-dm-client /usr/local/php/bin/php /data/apps/front1/store/think 已核验的任务命令

第二套工作目录改为/data/apps/front2/store。此处只准备任务配置,正式任务暂不启动。第19步仍须用真实网页验证驱动与中文;CLI成功不代表FPM成功,不公开phpinfo。

成功结果: CLI有dm驱动、FPM正常、两套任务环境明确。失败处理: 依次查动态库、ini、服务环境、FPM pool和真实请求。

11|准备 Redis、任务管理和设备通信环境

执行位置:【新机】管理员和应用负责人。

  1. 根据第 02 步确定 Redis 是远端复用还是本机迁移。远端复用时核验允许新机访问;本机缺失才用同版受控包安装。
  2. 保留认证、DB 编号、命名空间和访问来源限制。演练不能指向旧生产队列;使用专用演练 Redis 或经确认的隔离 DB/前缀。只改前缀可能漏掉代码内固定键,必须核验所有访问路径。
  3. 区分“可以重建的缓存”“会话”“尚未执行的队列”“交易去重状态”。后两类由应用负责人确定停写后的保留及恢复方法;不能统一丢弃,也不能无差别整实例恢复到共享 Redis。
  4. Supervisor/Workerman/系统定时任务先放入不自动加载的待启用位置。每条记录:系统归属、用户、工作目录、绝对 PHP 路径、环境、日志、停止命令、启动命令、是否有 watchdog。
  5. MQTT、打印或其他设备通道仅在前厅确实依赖时迁移。完整保留认证、ACL、TLS、Topic、Client ID、持久会话和实际监听;两套客户端 ID 不得重复。没有可靠演练开关时网络隔离,避免演练系统发真实指令。
  6. 预先验证新机到达梦、Redis、内部依赖的连通性;应用直连端口、数据库端口不因排障全网放开。

成功结果: 所需依赖可用,正式消费者和调度任务未提前启动;两套隔离清楚。失败处理: 找不到任务停启方式就先补任务表,不能进入正式窗口。

12|在隔离 MySQL 恢复演练备份

执行位置:【临时 MySQL】;严禁在旧正式 MySQL 操作。

  1. 运维提供与源 MySQL 主版本匹配的专用实例,网络上不能连接真实设备和支付通道。确认实例内没有其他业务数据。
  2. 创建私有 stage.cnf,格式同第 06 步,但主机、端口、账号全部指向临时实例,权限 0600。不要复制旧机连接后忘改地址。
  3. 用临时客户端执行 SELECT @@hostname,@@port,VERSION();,与登记表核对。
  4. 管理员在该临时实例执行 SET GLOBAL event_scheduler=OFF;,确认不会自动运行从备份带来的事件。禁用复制链路,不启动应用。
  5. 校验备份哈希后设置路径并导入:
STAGE_MYSQL='CHANGE_ME_临时mysql客户端绝对路径'
STAGE_CNF='CHANGE_ME_临时实例cnf绝对路径'
FRONT_DUMP='CHANGE_ME_本次front.sql绝对路径'
RESTORE_LOG='CHANGE_ME_本次恢复日志绝对路径'
case "$STAGE_MYSQL$STAGE_CNF$FRONT_DUMP$RESTORE_LOG" in *CHANGE_ME*) echo '先填写临时目标和文件路径'; exit 1;; esac
if "$STAGE_MYSQL" --defaults-extra-file="$STAGE_CNF" \
  < "$FRONT_DUMP" > "$RESTORE_LOG" 2>&1; then
  echo '客户端返回成功,继续核对日志、两库和对象'
else
  echo '恢复失败,保留日志和目标当前状态'; exit 1
fi
  1. 在临时库查看两库、表、视图、例程、触发器和事件清单;记录逐表精确 COUNT(*)。不能用 InnoDB 的估算 TABLE_ROWS 代替。
  2. 由负责人确认恢复结果,填写恢复开始/结束时间和日志路径。

成功结果: 两库恢复完成、错误已清零、对象和行数有基线。失败处理: dump 中 CREATE DATABASE/USE 仍会生效,命令末尾指定库名不能防误导;导入中断先查已完成范围,不用 --force 跳过。

13|在临时 MySQL 做两库版本升级

执行位置:【临时 MySQL】;应用负责人审核后实施。

  1. 对照冻结的应用版本,确认两个目录各自的 precheck/编号升级段/postcheck 和 SHA256。
  2. 打开每个 SQL 文件,核对 USE、DATABASE() 断言、跨库引用与表前缀。即使命令指定 zhct2,脚本内部的 USE zhct 仍可能把目标切回第一套。
  3. 先执行预检。如果预检结构不符合脚本要求,停止;不跳过预检硬跑。
  4. 按编号一次执行一段,输出独立日志。下面只表示调用方式,文件路径必须是第 04 步领到的已审查 SQL:
临时mysql客户端 --defaults-extra-file=临时cnf --show-warnings --binary-mode=1 目标库 < 已审核的编号SQL文件 > 本段日志 2>&1
  1. 每段立即检查退出码和日志,再执行该段后验;只有后验通过才能进入下一段。
  2. 有 DELIMITER 的脚本使用 mysql 客户端整份文件执行,不在图形工具里误选一行执行。
  3. 记录下表,一库一行:
库 升级前版本/结构 升级包哈希 完成段号 后验 结论
zhct 现场填写 现场填写 现场填写 现场填写 升级通过/无需升级/停止
zhct2 现场填写 现场填写 现场填写 现场填写 同上
  1. 升级后重新导出快照和精确行数基线。后续达梦对账以升级后临时库为准,菜单、权限、字典、参数等升级新增项单独说明。

成功结果: 两库全部有明确升级结论。失败处理: MySQL DDL 可能已经自动提交;保存成功段号,由负责人判断续跑还是恢复干净副本,不把整份脚本重新执行一遍。

14|让 DBA 建立两个演练达梦目标

执行位置:【新机达梦管理工具】;DBA执行,新手核对记录。

  1. 将zhct与zhct2的源版本、容量、升级后结构、应用版本、增长量和厂家参数交DBA。
  2. 本册演练目标分别为ZHCT_REH与ZHCT2_REH,每个目标有独立用户、同名模式及适当表空间;正式目标不混用。现场已定其他名称时统一替换。
  3. DBA先查已有用户、模式和表空间归属,未知对象不删除、不覆盖。通常创建用户时已有同名默认模式,不重复创建。
  4. DBA按容量规划和实例现状创建目标,提供权限核验结果;业务账号不授DBA、不导入SYSDBA/MAIN,不获取另一套无关权限。
  5. 分别用两个业务账号登录,执行:
SELECT USER;
SELECT TABLE_NAME FROM USER_TABLES ORDER BY TABLE_NAME;
  1. 核对当前身份和对象清单,新目标为空或只有已批准对象。检查默认业务/索引表空间、容量及登录权限;明文密码私下交接,不写参数表。

成功结果: 两个演练目标已确认身份、归属、容量和权限。失败处理: 交DBA处理,不改用超级账号绕过。

15|用 DTS 把两个库逐个迁到达梦

执行位置:【电脑/受控迁移机】达梦 DTS 图形工具。

本册选 DTS 作为新手主路线。正式时使用相同版本、驱动、类型映射和已通过的任务配置;若项目已冻结其他迁移程序,则必须配有其专用执行手册和独立验收,不能临时混用两种工具。

15.1 先迁第一套 Store 库

  1. 打开厂家交付的“达梦数据迁移工具/DTS”。如果没有图形界面,在经批准的运维电脑运行匹配客户端,确认能连接两端。
  2. 创建或打开本项目迁移工程,建立新任务,例如 rehearsal-zhct-to-ZHCT_REH。不同 DTS 版本按钮名称可能略有差别,以“新建迁移/迁移任务”及向导提示识别;不要照着其他项目截图填地址。
  3. 选择 MySQL 到 DM 的迁移方向。源是第 13 步升级完成的临时 MySQL,目标是厂家达梦。
  4. 源连接填写临时地址、端口、源账号、源库 zhct;选择与源版本匹配的 JDBC 驱动。点测试连接,确认成功。
  5. 目标连接填写达梦地址、端口、用户 ZHCT_REH 和其私有密码,测试连接。确认目标模式就是 ZHCT_REH,不是默认 MAIN 或其他库上次留下的模式。
  6. 源对象选择本库批准的全部表及需要迁移的视图、触发器、例程等;不要勾选 MySQL 系统库。保存对象清单与预检报告。
  7. 在类型映射和迁移选项页加载本次已审查映射;逐项复核字符长度、金额精度、主键、自增、默认值和大字段。迁移负责人必须处理所有“不兼容/需人工转换”项。
  8. 确认目标没有未知表,不选择“覆盖已有对象”来消除报错。需要重做时先让 DBA 判定目标是否可重建。
  9. 根据冻结任务执行结构、数据、索引/约束及特殊对象迁移。保留历史显式 ID,按源下一次取号语义核验自增;迁移中不开放应用写入。
  10. 打开迁移结果及失败明细,保存报告。只出现“任务结束”不表示成功,必须核对成功、失败和跳过对象数及每表记录数。
  11. 有一项失败即停本库,先处理原因并记录准确重试范围;不要整任务再次追加造成重复数据。

15.2 再建立第二套任务

次序 源临时库 演练目标账号及模式 完成后记录
1 zhct ZHCT_REH 对象数、行数、失败数、日志、耗时
2 zhct2 ZHCT2_REH 同上

每建一个任务都重新读源库与目标用户,不仅修改任务名称。应用账号中的口令不嵌入共享工程或公开截图;DTS 工程文件按敏感配置保管。

15.3 这些映射必须有处理结论

类型/特性 要核实什么
中文 VARCHAR/TEXT 字符与字节语义、实际最长 UTF-8 数据是否能装下
BIGINT/unsigned/DECIMAL 最大 ID、金额原精度;迁移中不能先转 float 再格式化
JSON/CLOB/BLOB 空值、最大字节长度、内容摘要及真实长数据
日期时间 零日期处理、时区、小数秒、默认值和 ON UPDATE
自增/主键 原 ID 保留,下一次新增不会撞历史 ID,应用能拿到新 ID
视图/触发器/事件/过程 SQL 转换及等价行为;不能因工具不支持静默漏迁
外键/唯一/索引 建立成功、处于启用状态,引用当前正确模式

成功结果: 两项迁移均无未处理失败或未解释跳过,完整报告已保存。失败处理: 映射、DDL、历史异常值由数据库/应用负责人修复并重演;不能直接把 MySQL dump 喂给达梦执行。

16|独立对账:两库都通过才能部署验收

执行位置:【迁移核验机/数据库工具】;只读核验。

不要只看 DTS 的绿色结果。用第 04 步提供的独立对账工具,分别连接升级后临时 MySQL 和达梦目标,输出每库一份报告。

  1. 比较每个业务表的精确行数。检查示例是 SELECT COUNT(*) FROM 已确认表名;,达梦用对应模式中的同一业务表。大表扫描放在演练或迁移窗口,避开旧库营业高峰。
  2. 比较表、列、类型、默认值、主键、唯一约束、外键、索引、视图和必须保留的例程,辅助对象单独列出。
  3. 按客户实际启用功能核对人员、部门、卡号、余额、补贴、充值、消费、退款、订单、菜品和配方;汇总 SQL 必须由负责人依据真实表结构提供,不拿其他客户的字段名硬套。
  4. 抽查中文、历史空值、最大 ID、最大小数位金额、最长文本/JSON、图片路径。金额在数据库一致后,还要经过实际 PHP/API读取比较,防驱动取值精度变化。
  5. 对 BLOB/CLOB 等比较空值数、最大字节数和约定摘要/完整内容校验;只有总行数相同不够。
  6. 记录每个差异:源值、目标值、原因、是否为批准的升级转换、处理人。敏感明细留现场;不以“差不多”放行。
  7. DBA 根据批准对象范围收集统计信息,复测代表性查询性能。

成功结果: 两库零未解释差异;批准的升级转换有记录;迁移与独立对账报告都存在。失败处理: 不开业务写入,定位映射或导入错误后按已批准范围重做并重新对账。

17|部署第一套 Store 并配置 zhct 的演练目标

执行位置:【新机】;仅连接ZHCT_REH演练模式。

17.1 复制冻结代码

确认目标是第07步的空目录,已有内容先查归属和备份,不覆盖。复制介质中已组装的第一套Store:

rsync -a --exclude='.git/' --exclude='runtime/' --exclude='env.php' \
  --exclude='application/config/prod/' \
  /workspace/cac-front-kit/front1/store/ /data/apps/front1/store/

按发布清单补其他客户私密配置排除项,不用--delete。此命令排除了客户配置,下一步必须恢复和合并,不能只复制代码就启动。

17.2 找到真正生效的配置

  1. 从第一套旧机备份恢复env.php,保留本客户TP_ENV和BUSINESS,按冻结发布版要求核验。
  2. Store通常由application/database.php根据两值加载application/config/<TP_ENV>/<BUSINESS>/database.php。BUSINESS为空或占位时路径不同,以冻结版真实加载规则为准。
  3. 打开实际生效的database.php,与发布版模板合并,保留表前缀、业务参数和新增必需键;不能直接覆盖丢失客户配置。
  4. 在原PHP配置数组内修改以下连接字段,不另起第二个return。示例为第一套演练:
'type'     => \app\cores\database\Dm::class,
'hostname' => 'CHANGE_ME_DM_HOST',
'hostport' => '5236',
'database' => 'ZHCT_REH',
'username' => 'ZHCT_REH',
'password' => 'CHANGE_ME_PRIVATE_PASSWORD',
'prefix'   => 'ydy_',

5236为原报告端口、ydy_为常见表前缀,均须现场确认。密码特殊字符按PHP字符串规则处理,不在命令行暴露。

  1. 本项目只使用第一套的zhct业务库;不要根据通用代码添加范围外连接。发布版若试图连接额外库,暂停启动并交应用负责人检查本客户功能开关、调用路径或错误制品。
  2. 核对第一套独立Redis设置、文件URL、租户/餐厅、设备和其他实际启用参数,演练不能指向正式队列或设备。

17.3 恢复文件并验收配置

  1. 从第一套备份恢复其客户配置、上传和附件,不能使用第二套文件。代码与旧客户配置的合并以发布清单为准。
  2. 配置限制为部署账号和运行用户可读,例如合适owner/group配合0640;父目录须可穿越。只给列入清单的runtime、上传、日志目录写权限。
  3. 使用同一个Store PHP执行php -l 实际database.php和php -l 实际env.php,必须提示无语法错误。
  4. 检查public/index.php、public/dist/index.html、vendor/autoload.php和本客户其他必需资源,全部与发布清单一致。
  5. 仅按冻结版本说明处理新部署缓存,不删除客户业务文件。CLI实际加载环境在第18步另验。

成功结果: 第一套Store程序、依赖、配置和文件完整,目标是ZHCT_REH。失败处理: 缺包补发布制品,驱动错误回09—10步,范围外连接由应用负责人纠正,不能额外建库。

18|部署第二套 Store,并核对两套任务配置

执行位置:【新机】;第二套连接ZHCT2_REH演练模式。

18.1 复制第二套代码

目标同样须是已确认的空目录:

rsync -a --exclude='.git/' --exclude='runtime/' --exclude='env.php' \
  --exclude='application/config/prod/' \
  /workspace/cac-front-kit/front2/store/ /data/apps/front2/store/

18.2 按差异表填写第二套

从第二套旧机备份恢复客户配置和文件,重复第17步的合并、语法与依赖检查。

核对项 第一套 第二套
代码目录 /data/apps/front1/store /data/apps/front2/store
源MySQL库 zhct zhct2
演练模式/用户 ZHCT_REH ZHCT2_REH
正式模式/用户(之后切换) ZHCT_APP ZHCT2_APP
TP_ENV/BUSINESS/生效database.php 第一套自己的值 第二套自己的值
Redis DB/前缀/队列 第一套隔离设置 第二套隔离设置
文件/runtime/日志 第一套目录 第二套目录
域名/端口/证书/设备/租户 第一套登记值 第二套登记值

不能复制第一套客户配置后只改一个数据库名。密码、文件、设备和餐厅配置必须来自各自受控备份。

18.3 两套后台任务都要单独检查

  1. 读取任务表中每条命令及其入口文件,核对实际加载的env.php和database.php;不要以网页成功替代CLI验收。
  2. 每条任务用明确工作目录、绝对PHP路径、运行用户、DM环境和独立日志。第二套命令不能仍cd到front1。
  3. 先保持消费者、Cron和watchdog禁用,仅在隔离演练窗口按清单启用必要测试任务。
  4. 通过任务日志和实际数据库会话确认测试任务分别连接ZHCT_REH与ZHCT2_REH。

成功结果: 第二套配置独立,两套任务各连本套演练库。失败处理: 出现第一套记录或工作目录,先停止任务并纠正配置,不改数据掩盖串库。

19|配置两个 Store 站点并验证真实请求

执行位置:【新机】管理员;客户端位于受限演练网络。

19.1 核对两条网站路由

用户入口 Nginx root PHP 演练数据库目标
第一套Store /data/apps/front1/store/public 本套已验收Store运行环境 ZHCT_REH
第二套Store /data/apps/front2/store/public 本套已验收Store运行环境 ZHCT2_REH

两个独立站点可以共用同一版本FPM,也可以按现场使用独立pool;不因为两个站点就新增另一种PHP版本。

19.2 迁移旧Store站点配置

  1. 用实际Nginx的-T查看主配置、include目录、站点、rewrite和fastcgi配置,保存受控备份及证书。
  2. 复制两个旧Store站点为新机待用配置,各自改root、日志路径和已确认的FPM socket/端口。保留原ThinkPHP rewrite/PATH_INFO、实际静态页面路径、上传alias和HTTPS。
  3. 域名、端口、证书按参数表核对,先用ss -lntp确认没有冲突。若同IP同端口承载两站点,server_name必须可区分;若按不同端口访问,分别登记。
  4. 保留本客户已有且确认需要的其他路由,不加入来源于其他项目的代理或独立服务。
  5. root只到public,隐藏配置和备份文件不能下载;演练入口限制运维网段,仍保持设备及外联隔离。
  6. 测试配置:
NGINX=/usr/local/nginx/sbin/nginx
"$NGINX" -t

看到语法及配置测试成功才执行:

"$NGINX" -s reload

未启动服务时由运维按实际服务管理方式启动,不重复拉起第二个Nginx主进程。

19.3 两套分别做网页和数据库验证

  1. 浏览器打开第一套临时地址,看登录页、JS/CSS;登录后查看第02步登记的历史识别记录。
  2. 打开第二套,重复检查,确认单位、餐厅和数据属于第二套。
  3. F12→Network查看真实业务请求的路径、Content-Type、业务码与返回数据;HTML 200不能替代业务接口成功。
  4. 使用临时域名或经批准的本机hosts指向新机,HTTPS仍使用正确证书和域名,不忽略证书错误判通过。
  5. 由应用负责人通过受限诊断或DBA会话证明两套Store分别访问ZHCT_REH和ZHCT2_REH,并由预期PHP处理;日志不输出口令。
  6. 验证中文、金额/ID和图片;检查隐藏配置URL不能下载。仅记录状态和脱敏结论,不展示真实配置。

成功结果: 两套站点、真实业务请求和数据库归属正确。失败处理: 502查FPM/socket/权限,404查root/rewrite,数据串套查生效database.php与租户;改Nginx后始终先-t再reload。

20|迁移文件并检查图片、下载和队列隔离

执行位置:【新旧机】受控文件传输;此时仍为演练副本。

  1. 按文件清单逐条对应“旧路径 → 新路径 → 使用它的系统”。区分本地目录、软链接、挂载、OSS/MinIO;数据库有 URL 不等于本地已有文件。
  2. 同步单个目录时先 dry-run,认真看输出的目标路径;下面需要替换实际路径和账号:
rsync -an --itemize-changes /旧机某套实际上传目录/ 迁移账号@新机:/该套新上传目录/
rsync -a --itemize-changes /旧机某套实际上传目录/ 迁移账号@新机:/该套新上传目录/

只有第一行核对无误再运行第二行。尾部 / 表示同步目录内容,不能误多套一层。非默认 SSH 端口由运维加正确的 -e 'ssh -p 端口';禁止 --delete。

  1. 对静态演练副本做文件数量、字节数及内容哈希核对;大目录可使用清单批量核验。正式停写后再按同一方法做最终同步与校验。
  2. 检查运行用户能读旧图片、写新上传,且 Web 服务器按既有策略阻止上传目录执行脚本。
  3. 抽查至少历史图片、新上传、附件下载和导出各一项;进入第二套重复,不能只验第一套。
  4. Redis 队列使用专用演练目标,旧生产队列消费量不因演练改变。测试消息、打印和支付只进入受控测试通道。

成功结果: 两套文件清单一致、实际可读写、互不串目录;演练不会消耗正式任务。失败处理: 先查路径、owner/group、挂载和 URL,再查 Nginx;不要直接全盘放开权限。

21|做完整演练,并决定能否约正式窗口

执行位置:【新机演练系统】;实施、业务代表、应用负责人、DBA一起验收。

两套分别执行,下列不适用项写明原因,不能空着当通过:

场景 操作 应看到的结果
登录权限 普通角色、管理角色分别登录 菜单与数据范围正确,不越权
人员与卡务 查询历史人员;用测试人员验证启用的操作 人员、部门、卡号和账户对应
菜品配方 查询旧菜品;测试新增、编辑、保存后重开 配方、单位、营养计算与基线一致
排菜订餐 测试排菜、订餐、取消及截止规则 已启用页面显示与数据库一致
资金业务 隔离测试账户验证启用的充值、补贴、消费、退款 单据、余额、流水对账;失败不半扣款
报表和导出 相同条件查数据、执行异步导出并下载 明细/汇总与基线相符,队列完成
文件 查看旧图、上传测试图、下载附件 文件内容可用且归属正确
设备和打印 指定测试设备完整跑一次流程 接口、回执、打印正确,无重复处理
失败恢复 按批准用例模拟重复请求/依赖故障 事务、幂等和重试符合已验收规则
两套隔离 A/B各读写自己的测试标识 对方系统数据、文件、任务不改变
时间与精度 大 ID、金额小数、中文、跨日时间 数据库和 PHP/API 返回一致

写测试只作用于专用演练模式、测试设备和测试外联通道,不对真实账户扣款。记录原请求、结果、对应数据库变化及日志,敏感信息留现场。

测量备份、传输、临时恢复、两库升级、DTS、对账、文件同步、业务验收的实际耗时;加上现场余量和回退时间,形成正式窗口。确定最晚回退决策时间,不要到营业前才决定。

成功结果: 两套演练全部通过,问题已复验关闭,备份能恢复,任务启停和回退步骤有记录。失败处理: 继续演练;任何资金、串库、精度、文件缺失、核心业务错误未解决,不能进入正式停写。

22|正式窗口开始:先停旧机所有写入

执行位置:【旧机及设备管理端】;必须在已确认停机窗口内。

  1. 客户确认停机通知、恢复时间、联系人及回退决策点;记录停写开始时间。
  2. 先停会自动拉起旧任务的 watchdog/自动恢复调度,再关闭两套前厅的用户写入口。
  3. 按任务表逐个暂停前厅 Cron、Supervisor、Workerman、队列消费及外部同步;只停止本项目登记的任务,不执行整机范围的“全部停止”。
  4. 停止或隔离设备直连、第三方回调、MQTT 消费和绕过网页的写入端点。只关网页首页不够。
  5. 等待在途交易结束,核对未完成订单、重试和锁;设备离线缓存需登记保存位置、补传方式、唯一交易号规则。
  6. DBA 对比两个时间点的关键交易更新时间/计数及会话活动,证明没有继续写入;确认只读访问也不会触发签到、日志表等隐性业务写入。
  7. 记录共同截止时间 T0;两库、文件、待处理队列和设备数据均按此停写范围处理。

成功结果: 旧前厅两套没有新写入、在途交易有结果、设备补传有安排;旧代码与旧数据库结构仍保留。失败处理: 发现写入即定位来源,重新确认 T0;不要一边营业一边做“最终全量”。

23|制作最终数据库、文件和状态备份

执行位置:【旧机】;保持停写。

  1. 新建最终目录,与演练备份分离:
umask 077
RUN_ID=$(date +%Y%m%d-%H%M%S)
BACKUP="/backup/cac-front/final-$RUN_ID"
install -d -m 700 "$BACKUP"
printf '%s\n' "$BACKUP"
  1. 重复第 06 步导出两库,确保变量与配置仍指向旧机;检查退出码、日志、文件大小和 SHA256。
  2. 重复第 05 步保存最终程序配置、任务状态和外置文件清单。按负责人方案保留未完成队列、去重与设备离线状态。
  3. 对第 20 步每个目录先 dry-run,再执行最终同步;禁止 --delete。如果目标残留演练文件,只按已登记演练清单隔离,不能删未知文件。
  4. 最终文件目录应与演练业务文件分开,或经过演练清单清理核验,避免测试上传和临时导出混入生产。
  5. 将最终备份传到临时机/新机受控位置,接收端校验全部哈希;保留异机副本。

成功结果: 最终备份对应同一 T0,两库、文件和需保留状态齐全。失败处理: 旧机继续停写,重新备份或传输;不得继续使用几天前的演练快照。

24|用最终备份重做两库迁移并切正式连接

执行位置:【临时MySQL】和【新机达梦】;尚不开放正式业务。

  1. 准备干净临时MySQL实例,按第12步恢复最终备份的zhct、zhct2,不向演练库追加。
  2. 按第13步执行同一冻结版本升级,逐段后验,得到两库最终升级后基线。
  3. DBA核对正式目标ZHCT_APP、ZHCT2_APP或已批准的实际名称,检查归属、容量、权限和空目标状态。未知同名对象不自动覆盖。
  4. 把演练通过的两个DTS任务另存为正式任务,逐项核对源为最终临时库、目标为正确正式模式、映射和选项不变。
  5. 按第15—16步完成迁移及独立对账,所有差异闭环后才改程序。
  6. 修改两个实际生效的Store database.php:
部署 主连接database/username 对应源库
第一套Store ZHCT_APP zhct
第二套Store ZHCT2_APP zhct2

同时核对DM驱动type、主机、端口、密码和原表前缀,保留其他业务配置,不新增范围外连接。

  1. 核对正式Redis、文件、URL、餐厅、密钥、设备和任务;演练数据、队列和上传不能带入正式。
  2. 按冻结版本说明清新部署缓存,重启新机相关FPM和长驻进程刷新配置/连接池;共享服务按窗口,正式后台任务此时仍禁用。
  3. 从限定运维入口做只读业务检查,由DBA/应用负责人确认网页和CLI任务都指向本套正式模式;应用日志等写入也需留痕。

成功结果: 两库及文件对账通过,两套Store的网页/CLI实际访问正式目标;未广泛开放写入。失败处理: 保持旧机停写,按最晚决策时间修复或执行第28步回退。

25|切换用户入口、回调与设备地址

执行位置:【客户网络管理端】与【新旧机】。

  1. 按演练前已选定的方案执行:修改域名/代理/NAT,或旧机释放业务 IP 后由新机接管。禁止两机同时占用同一 IP。 保留旧机独立管理通道。
  2. 网络管理员按业务、设备、运维来源放行已登记端口;达梦和 Redis 不对全部来源开放,原有宽规则需一并审查。
  3. HTTPS 检查证书、域名、链、私钥权限和时间;回调检查来源白名单和新出口地址。
  4. 逐个修改或确认消费设备、打印、MQTT、H5二维码、文件域名、第三方回调、前端编译 API URL;不仅验证浏览器能打开。
  5. 从业务终端访问两套实际地址,在新机访问日志确认请求到达;旧机业务入口不再接受写入。仅看 DNS 查询结果不足以证明客户端已切换。
  6. 先开放指定测试人员/测试设备,小范围执行第 26 步验收,合格后再开放其余入口。

成功结果: 两套真实访问落到新机,旧机保持停写,设备及回调地址一致。失败处理: 若尚无正式新增业务,可按第 28 步回退;有新增数据先保全并对账,不能直接切回丢记录。

26|逐项恢复任务并完成正式业务闭环

执行位置:【新机、指定设备和客户业务终端】。

按“依赖可用 → 新Store应用 → 小范围业务 → 设备 → 队列/定时任务 → watchdog”的顺序恢复。应用流程必须依赖队列时,在小范围验收阶段只启用已确认必要的那一项,不能一次启用全部。

  1. 每启用一条新机任务前,核实旧机对应任务已停,检查绝对 PHP 路径、运行用户、工作目录、DM 环境及正式模式。
  2. 核对 CLI 实际连接,不以网页登录成功替代定时任务验收。
  3. 处理设备离线补传时记录交易唯一号、原时间、重试次数、最终流水;验证重复上报不会重复扣费/记账。
  4. 第一套完成一个客户批准的真实闭环:例如排菜→订餐→消费/核销→报表,按实际启用功能选择。第二套独立重复。
  5. 涉及真实充值、消费或退款,使用客户批准的账户、方式和金额,并核对资金与流水;不能以演练截图代替正式验证。
  6. 检查图片、报表下载、异步导出、打印及设备回执;对账迁移前 T0 基线与切换后新增数据。
  7. 记录两个系统各自的首次成功交易时间 T1、交易号受控记录位置、业务签认人;如失败立即停止继续放量。

成功结果: 两套各有真实闭环及对账证明,任务无双跑、队列正常、设备无重复交易。失败处理: 先冻结故障业务及新增写入、保全证据,再决定修复或回退。

27|检查开机恢复、备份和一个完整就餐高峰

执行位置:【新机】;重启测试优先在正式开放前的演练窗口完成。

  1. 检查达梦、Nginx、经确认的 Store PHP、必要 Redis、Supervisor/Workerman 及其他前厅依赖的自启配置,服务名以登记表为准。不要为核验自启在营业中突然重启整机。
  2. 在批准窗口重启验证,重新登录后检查 systemctl status 实际服务名、ss -lntp、两套访问入口和实际数据库连接;特别注意 /run 临时目录、socket 权限与客户端环境。
  3. 逐项验证 Cron/长驻任务只启动一次,旧路径和演练模式不会被 watchdog 拉起。
  4. DBA 建立正式达梦备份、归档保留与异机副本方案,记录成功任务和恢复验证;应用文件、客户配置与证书也要有备份。
  5. 验证单模式恢复和实例恢复的适用范围,避免为恢复一个业务模式覆盖同实例其他系统。由 DBA 在隔离副本演练恢复。
  6. 设置日志轮转、磁盘及备份失败告警;记录 CPU、内存、磁盘、IO、慢 SQL、应用错误、队列积压和设备失败率。
  7. 观察至少一个完整就餐高峰及后台任务周期,按实际业务频率延长;不能以迁移后五分钟无报错作为最终验收。

成功结果: 重启可恢复、备份可恢复、就餐高峰业务与对账正常。失败处理: 保留旧机,修复并复验;暂不安排旧机下线。

28|遇到问题怎么回退,完成后交什么

执行位置:【新旧机、网络管理端、DBA】;由现场负责人统一指挥。

28.1 触发条件

在约定窗口内遇到核心业务不可用、两库对账不一致、金额/ID精度错误、串套、持续队列积压或设备严重失败,且无法在最晚决策时间前解决,即进入回退决策。

28.2 新机尚无正式新增业务

  1. 停新机前厅用户写入、设备、队列、定时任务和 watchdog;确认不再产生新记录。
  2. 保存新机日志、配置版本及迁移证据。
  3. 网络管理员恢复原入口/设备地址。IP 接管场景先让新机释放业务 IP,再让旧机接回;保留管理通道。
  4. 确认旧机仍是迁移前原代码、原 MySQL 和原文件配置,未被升级 SQL 改过。
  5. 依次恢复旧机前厅后端、指定设备、队列/定时任务、watchdog,确保新机对应项已停。
  6. 两套分别验证业务闭环和截止时点数据,再通知恢复。

28.3 新机已经产生正式新增业务

  1. 先停止新机新增写入和处理任务,记录差异时间窗 T0—当前。
  2. DBA保全达梦、上传文件、队列、去重状态、设备补传状态、外部支付与日志。
  3. 对新增、修改、删除、余额变动、退款及外部副作用逐项对账。本册不提供通用反向 SQL,不能简单把达梦新表导回旧 MySQL 了事。
  4. 按演练过且经客户批准的数据补回/业务补录方案处理,复核唯一号、金额及幂等;无可用方案时保持停写,优先受控修复新机,不丢弃真实交易强行切回。
  5. 数据处理完成后由现场负责人决定入口恢复方式,重新验收两套系统。

28.4 交接清单

交付两套访问入口、两库映射、两套Store数据库连接核对结果、发布版本及哈希、环境/驱动版本、配置路径、服务/任务启停表、文件目录、设备地址表、迁移与对账报告、演练与正式验收、备份恢复记录、故障排查表、回退负责人和旧机保留期限。口令和授权文件走私有渠道。

成功结果: 客户确认业务、数据和运维交接;旧机到约定保留期结束且验收签认后再下线。手册完成不等于客户迁移已经完成。

附录 A|新手故障排查速查表

现象 先查什么 禁止的处理
SSH超时 地址/端口/网络/主机状态 随意连其他服务器
校验FAILED 介质版本、重新传坏文件 忽略校验继续装
PHP版本不对 登记的绝对路径与冻结版本 随意改系统软链接
could not find driver 当前PHP的ini和PDO驱动 用其他PHP成功代替
Unable to start DM module ABI/架构、ldd、LD_LIBRARY_PATH 改名强装驱动
CLI正常网页失败 FPM ini/pool/服务环境 公网放phpinfo
中文乱码/JSON失败 DM_SVC_PATH、PG_UTF8和真实请求 批量改库编码
第二套出现第一套记录 第二套env.php、database.php、租户、任务目录 直接改业务数据掩盖串套
运行时要求额外数据库/服务 本客户功能开关、实际调用、冻结发布包 按通用仓库猜测额外建库部署
502 对应FPM、socket、权限 全盘777
页面白屏/接口返回HTML root、rewrite、资源路径、真实响应类型 把HTTP200当通过
图片404 文件清单、挂载、alias、权限 只改数据库URL
Cron/导出失败 工作目录、PHP、CLI配置、DM环境、队列 再起一份未知任务
DTS截断 最大UTF-8字节数、类型映射 截短客户数据
DTS主键冲突 目标演练残留、重复追加 删除未知对象
金额/大ID错误 数据库原值与PHP返回精度 从float反推原值
重复扣款/打印 新旧任务双跑、补传幂等 未对账继续放量
重启无法恢复 服务自启、/run、用户、环境 营业中反复重启试错

附录 B|现场关键参数与三个表格

  • 现场参数表:两套Store、zhct/zhct2、演练/正式模式、PHP、站点、文件、任务、设备及停机安排。
  • 制品领取表:两个Store包、PHP/驱动依赖、两库SQL、两个DTS任务及核验工具。
  • 逐步验收表:28步的时间、执行人、结果、证据和复核人。

建议先下载到客户受控目录再填写。密码不写表内;填过内部地址和路径的表格不上传公共站点。两库可能共用MySQL实例,也可能分属不同实例,必须登记清楚;不同实例正式备份靠共同停写截止时间取得一致口径。

附录 C|本版依据与验证边界

  • 本项目范围以用户2026-10-21明确确认的“两套独立部署的store,数据库一个zhct、一个zhct2”为准,优先于此前综合手册和通用仓库功能推断。
  • Store配置路径参考实际加载规则;PHP7.3为原路线示例,正式版本必须按冻结发布包核验。
  • 达梦官方MySQL迁移流程用于迁移和对象/数据验证原则。
  • 达梦官方PHP驱动说明用于版本匹配、动态库和中文配置语义。

本版验证仅覆盖文档范围、示例一致性、命令语法和HTML。现场安装、实际最终备份恢复、正式两库迁移、真实交易和备份恢复演练均尚未执行,以现场逐步验收表为准。