跨版本物理恢复必须确保innodb_file_per_table、innodb_page_size和explicit_defaults_for_timestamp三者配置一致,严禁拷贝旧版mysql等系统库目录,否则启动失败;不匹配时唯一可靠路径是逻辑备份迁移。

innodb_file_per_table 配置不一致直接导致表找不到
MySQL 启动时会校验每个 InnoDB 表的元数据与物理文件结构是否匹配。如果源库 innodb_file_per_table=OFF(如老版 5.6 或未显式配置的 5.7),所有用户表都存进共享表空间 ibdata1;而目标库(如 8.0 默认)是 ON,它只认独立的 .ibd 文件。
- 恢复后启动 mysqld,报错类似
Table 'mydb.users' doesn't exist in engine - 即使你把整个
ibdata1拷过去,新实例也无法解析其中嵌套的表定义 - 实操必须查源库:
SHOW VARIABLES LIKE 'innodb_file_per_table'; - 新实例配置文件中要显式写死
innodb_file_per_table = OFF(注意:8.0.30+ 已禁用共享表空间,不能用) - 更稳的做法:在兼容版本(如 5.7.40)里先物理还原,再用
mysqldump导出逻辑备份
innodb_page_size 不匹配会让 mysqld 直接退出
InnoDB 页面大小是底层存储的硬约束,不是配置项可协商。5.7 默认 16384(16K),但某些定制部署用了 4096(4K);8.0.28+ 支持 65536(64K),但完全不向下兼容。
- 一旦不一致,启动瞬间报错:
InnoDB: Error: page size mismatch,进程终止 - 查源库:
SELECT @@innodb_page_size; - 目标实例的
my.cnf必须在[mysqld]段显式声明:innodb_page_size = 16384(不能依赖默认值) - 如果源是 4K,别试物理恢复——只能走
mysqldump或mydumper
mysql 系统库不能直接拷贝
8.0 的 mysql 库结构和权限模型相比 5.7 有根本性变化:字段增减(如 authentication_string 替代 password)、新表引入(role_edges、default_roles)、user.frm 格式不兼容。
- 直接复制整个
/var/lib/mysql/mysql/目录,启动必报:Unknown table 'mysql.role_edges'或Incorrect information in file: './mysql/user.frm' - 物理恢复时只保留业务库目录(如
myapp/)、ibdata1、ib<em>logfile*</em>、undo* - 绝对不要碰
mysql/、performance_schema/、sys/ - 首次启动加参数:
--skip-grant-tables --shared-memory,再手动运行:mysqld --upgrade
explicit_defaults_for_timestamp 会影响时间字段行为
这个参数控制 TIMESTAMP 字段的隐式默认值。5.6 默认 OFF,意味着没写 NOT NULL 的 TIMESTAMP 会自动加 DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;5.7+ 默认 ON,行为完全不同。
- 物理恢复后建表或插入可能触发
Invalid default value for 'xxx' - 源库查:
SELECT @@explicit_defaults_for_timestamp; - 目标实例配置中需保持一致,例如都设为
explicit_defaults_for_timestamp = OFF - 但注意:8.0 强制要求该参数为
ON,所以跨大版本时这条路基本堵死,只能逻辑中转
跨平台和跨大版本的物理恢复,本质是在对抗 InnoDB 的二进制契约——它不承诺向后兼容,也不抽象路径、权限、字节序、页格式这些底层细节。哪怕只是从 CentOS 7 恢复到 Ubuntu 22.04,都可能因 ext4 元数据差异失败。真正能绕开这些坑的,只有逻辑备份这一条路。











