用SHOW CREATE TABLE导出结构再diff比对,避免依赖information_schema字段差异;pt-table-sync同步前须禁用--alter和--sync-to-master;优先选Python脚本归一化比对CREATE TABLE而非mysqldiff;注意8.0 MDL锁导致ALTER变慢及客户端连接池兼容问题。

MySQL升级后发现information_schema字段变了,怎么查表结构差异?
MySQL 5.7 升级到 8.0 后,information_schema.TABLES 和 COLUMNS 的字段定义有变动(比如新增 IS_UPDATABLE、GENERATION_EXPRESSION),直接用旧脚本比对会报列不存在或类型不匹配。
别硬改 SQL 去适配两个版本的 schema,先统一用 SHOW CREATE TABLE 输出文本再对比——它稳定、跨版本兼容、不依赖 information_schema 的内部结构。
- 在旧库和新库分别执行:
mysqldump --no-data --skip-triggers --skip-routines --skip-events db_name table_name > table_def.sql - 用
diff或 VS Code 的“比较文件”功能比对两个table_def.sql - 重点关注
ENGINE=、ROW_FORMAT=、CHARSET=、COLLATE=和生成列/函数索引等 8.0 新增语法是否被意外删减
用 pt-table-sync 同步结构前必须关掉哪些隐式行为?
pt-table-sync 默认只同步数据,但加了 --sync-to-master 或误配 --alter 参数时,它可能偷偷执行 ALTER TABLE ——而 MySQL 8.0 对某些操作加了更严的权限校验(比如修改 sql_mode 或启用 innodb_strict_mode 时,VARCHAR 长度超限会直接报错,不再静默截断)。
- 务必显式指定
--no-check-slave和--no-foreign-key-checks,否则从库上可能因外键约束失败中断 - 禁用自动
ALTER:确认命令里没出现--alter,也不要用--sync-to-master模式处理结构差异 - 如果真要改结构,先用
pt-online-schema-change单独跑,再用pt-table-sync补数据
对比工具选 mysqldiff 还是自写 Python 脚本?
mysqldiff(来自 MySQL Utilities)已停止维护,MySQL 8.0.22+ 安装后常报 AttributeError: 'tuple' object has no attribute 'split',本质是它还按 5.6 的协议解析握手包。
不如用轻量可控的方式:Python + mysql-connector-python 查两库的 CREATE TABLE,正则提取关键段落(字段定义、索引、约束),再逐行归一化后比对。
- 归一化要点:忽略空格/换行顺序、把
`col`统一为col、将INT(11)简化为INT、合并多行KEY为单行 - 避免用
json.dumps直接比对字段列表——MySQL 8.0 的column_comment可能含换行符,JSON 序列化会出错 - 示例关键逻辑:
re.sub(r'\s+', ' ', create_sql).strip()再分段匹配^CREATE TABLE.*?$$
执行 ALTER TABLE 同步时,为什么 8.0 上锁时间突然变长?
MySQL 8.0 默认开启 innodb_file_per_table=ON 和更强的元数据锁(MDL)策略,一个看似简单的 ADD COLUMN 在大表上可能卡住 DML,不是因为磁盘 IO,而是等待 MDL_SHARED_WRITE 锁释放。
- 上线前先查阻塞源:
SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_TYPE = 'TABLE'; - 避免在业务高峰执行,尤其不要在从库上用
ALGORITHM=INPLACE(8.0 对某些 inplace 操作仍需短暂排他锁) - 如果只是补字段默认值,优先用
ADD COLUMN ... DEFAULT 'x' STORED(虚拟列)过渡,等低峰再转成实列
实际操作中,最易被跳过的一步是:升级后没清空客户端连接池里的旧连接。这些连接仍以 5.7 协议通信,遇到 8.0 新字段(如 PRIVILEGE_CHECKS_USER)会静默忽略,导致结构比对漏掉权限相关差异。











