一、故障现象

新增 Percona XtraDB Cluster 8.0 节点,按照 MySQL5.7 旧流程操作,数据库启动直接崩溃,日志抛出两类致命错误:

  1. 启动报错:Failed to find valid data directoryData Dictionary initialization failed,mysqld 直接终止;

  2. 执行mysqld --initialize初始化命令报错:--initialize specified but the data directory has files in it,初始化流程中断。

二、故障根因分析

1. 版本机制差异(核心原因)

MySQL5.7 与 MySQL8.0 初始化逻辑完全重构:

  • MySQL5.7:空数据目录启动时,服务内部自动完成初始化,目录提前放入 SSL 证书不影响流程;

  • MySQL8.0:架构升级事务型统一数据字典,取消启动自动初始化,必须手动执行--initialize;且初始化要求数据目录完全空白,存在任意文件(SSL pem 证书)都会初始化失败。

2. 操作流程错误

沿用 5.7 运维习惯,操作顺序颠倒:

  1. 先将集群 SSL 证书拷贝至数据目录;

  2. 再执行数据库初始化命令; 目录存在证书文件,触发 8.0 初始化目录校验规则,初始化直接失败。

三、完整故障处理步骤

⚠️生产环境禁止直接rm -rf删除数据目录,优先备份重命名,确认业务恢复正常后再清理备份,防止误删无法回滚。

占位符说明:

  • {MYSQL_DATA_ROOT}:MySQL 数据根目录

  • {MYSQL_BIN_PATH}:MySQL bin 程序目录

  • {MYSQL_RUN_USER}:MySQL 运行操作系统用户

  1. 备份原有数据目录(替代直接 rm 删除) 将原有 mysql 目录重命名备份,再新建空的数据目录,保证初始化要求的空白目录:
# 备份旧目录,时间戳标记,便于回滚
mv {MYSQL_DATA_ROOT}/mysql {MYSQL_DATA_ROOT}/mysql_bak_$(date +%Y%m%d_%H%M%S)
# 创建全新空目录
mkdir -p {MYSQL_DATA_ROOT}/mysql
# 修正目录归属权限
chown -R {MYSQL_RUN_USER}:{MYSQL_RUN_USER} {MYSQL_DATA_ROOT}/mysql
chmod 700 {MYSQL_DATA_ROOT}/mysql
  1. 执行数据库初始化 切换运行用户执行初始化,生成事务型数据字典、系统库及临时 root 密码:
su - {MYSQL_RUN_USER} -c "{MYSQL_BIN_PATH}/mysqld --initialize --datadir={MYSQL_DATA_ROOT}/mysql"
  1. 拷贝集群 SSL 证书 初始化完成后,再从正常集群节点同步 SSL 证书至数据目录,并修正文件权限:
scp root@正常节点IP:{MYSQL_DATA_ROOT}/mysql/*.pem {MYSQL_DATA_ROOT}/mysql/
chown {MYSQL_RUN_USER}:{MYSQL_RUN_USER} {MYSQL_DATA_ROOT}/mysql/*.pem
chmod 600 {MYSQL_DATA_ROOT}/mysql/*.pem
  1. 清理集群冲突文件 删除初始化自动生成的auto.cnf,避免节点 UUID 冲突导致无法加入集群:
rm -f {MYSQL_DATA_ROOT}/mysql/auto.cnf
rm -f {MYSQL_DATA_ROOT}/mysql/grastate.dat
  1. 启动数据库服务 启动 mysqld,查看运行日志,等待节点自动执行 SST 全量同步,完成集群接入:
systemctl start mysqld
tail -f {MYSQL_DATA_ROOT}/mysql/mysqld.log

节点业务运行稳定、集群状态为SYNCED确认无误后,再择机删除mysql_bak_xxxx备份目录释放磁盘空间。

四、经验总结 & 运维规范

1. 核心运维规范(PXC8.0 新增节点标准流程)

  1. 备份旧数据目录,新建空白数据目录,禁止直接 rm 删除;

  2. 执行mysqld --initialize手动初始化;

  3. 初始化完成后再放入 SSL、密钥等文件;

  4. 删除auto.cnf避免集群 UUID 冲突;

  5. 启动服务等待 SST 同步。

2. 版本差异重点提醒

  1. 禁止将 MySQL5.7 运维流程套用至 MySQL8.0;

  2. 8.0 取消启动自动初始化,空目录直接启动会崩溃;

  3. 8.0 初始化阶段强校验目录,存在任何文件都会初始化失败。

3. 后续优化点

  1. 整理 PXC5.7、PXC8.0 两套标准化部署文档,区分版本操作差异;

  2. 新增节点部署脚本内置目录备份、新建空目录、初始化、证书同步、冲突文件清理逻辑,规避人为操作顺序错误;

  3. 故障排查优先查看 mysql 临时日志,精准定位数据目录、初始化相关报错;

  4. 所有涉及数据目录清理操作,优先重命名备份,不直接执行 rm 暴力删除。

五、初始化后恢复旧数据标准方案(PXC8.0 专属)

1. 核心结论:8.0 初始化后不能直接全盘拷贝旧数据

MySQL8.0 与 5.7 数据字典结构不兼容、事务 ID、redo/undo 格式不互通:

  • 直接把旧数据 ibdata1、ibd、redo 拷进初始化后的新目录 → 直接启动崩溃、数据字典损坏、SST 卡死

  • 8.0 初始化生成的系统库、数据字典,与旧物理文件版本不匹配,无法混用

2. 想要保留旧数据的正确两种方式(生产可用)

方案 A:正规物理备份恢复(推荐、零丢数据、集群兼容)

不使用初始化后空目录顶替,而是用 xtrabackup 完整备份 + prepare 恢复旧节点全量数据,是 PXC8.0 官方标准扩容方式:

  1. 在正常节点做全量 xtrabackup 备份

  2. 备份端执行 prepare 一致性回放

  3. 故障节点备份原有目录,清空目录,直接放入备份数据

  4. 删除 auto.cnf、grastate.dat、sst_in_progress

  5. 补全 SSL 证书、修正权限后启动,自动 IST/SST 接入集群

优点:数据完整、位点连续、集群不裂脑、无版本兼容问题。

方案 B:初始化后逻辑导入数据(小数据量适用)

  1. 先正常执行 8.0 标准初始化流程(生成合法 8.0 数据字典)

  2. 启动数据库、重置临时密码、集群正常入网 SYNCED

  3. 通过 mysqldump /mydumper 把旧数据逻辑导出

  4. 导入当前新节点,由 8.0 引擎自动适配数据字典

3. 绝对禁止的错误操作(本次踩坑延伸)

  • ❌ 8.0 初始化完成后,覆盖替换 ibdata1、redo log、undo log、系统库文件

  • ❌ 跨版本直接物理拷贝数据目录(5.7 数据不能直接盖 8.0)

  • ❌ 保留旧 grastate.dat、旧 auto.cnf 强行启动

4. 最简记忆规则(PXC8.0)

要新节点纯净入网:先初始化 → 补证书 → 启动 SST 拉集群最新数据 要保留历史旧数据:不用初始化空跑,直接 xtrabackup 物理恢复

  1. 部署前全局替换占位符为现场真实值:

    1. {MYSQL_DATA_ROOT}

    2. {MYSQL_BIN_PATH}

    3. {MYSQL_RUN_USER}