一、目录
·InnoDB 内部结构检查
·数据库对象定义检查
·存储引擎检查
·表空间检查
·系统变量检查
·认证插件检查
·问题级别说明
·附录
·参考资料
三、1.1 旧时间类型格式(oldTemporalCheck)
错误信息:Usage of old temporal type。
错误级别:ERROR。
四、错误原因
MySQL 5.5及更早版本使用了一种旧的时间类型磁盘存储格式。这种格式在 MySQL 8.0中已不再支持,必须在升级前转换为新格式。
五、技术背景
| 问题点 | 说明 |
| 影响的数据类型 | TIME,DATETIME,TIMESTAMP |
| 旧格式特征 | 列类型显示包含 "5.5 binary format" |
| 为何不兼容 | MySQL 8.0完全移除了对旧时间格式的支持 |
六、检测方法
SELECT table_schema, table_name, column_name, column_type FROM information_schema.columns WHERE column_type LIKE '%5.5 binary format%';
七、解决方案
— 对检测到的每张表执行重建ALTER TABLE 数据库名.表名 FORCE;
八、1.2 Schema 不一致检查(schemaInconsistencyCheck)
错误信息:Schema inconsistencies resulting from file removal or corruption。
错误级别:ERROR。
九、错误原因
表的数据文件(.ibd)或元数据文件(.frm)被意外删除或损坏,导致 InnoDB 数据字典与 MySQL 元数据不一致。
十、技术背景
| 问题点 | 说明 |
| 常见原因 | 手动删除数据文件、磁盘故障、文件系统错误 |
| 表现形式 | 表存在于 InnoDB 数据字典但不在 information_schema.tables 中 |
| 升级影响 | MySQL 8.0的新数据字典无法正确迁移这些不一致的表 |
十一、检测方法
— 查找存在于 InnoDB 但不在 TABLES 表中的记录SELECT t.NAME as table_nameFROM information_schema.innodb_sys_tables tLEFT JOIN information_schema.tables it ON CONCAT(it.TABLE_SCHEMA, '/', it.TABLE_NAME) = t.NAMEWHERE it.TABLE_NAME IS NULL AND t.NAME NOT LIKE 'SYS_%' AND t.NAME NOT LIKE 'mysql/%';
十二、解决方案
1. 检查错误日志:
grep -i "corrupt\\|missing\\|error" /var/log/mysql/error.log
2. 检查数据目录:
ls -la /var/lib/mysql/数据库名/
3. 修复方案(根据情况选择):
— 如果表确实不需要,清理 InnoDB 数据字典– 需要创建同名空表后删除CREATE TABLE 数据库名.表名 (id INT) ENGINE=InnoDB;DROP TABLE 数据库名.表名;– 如果需要恢复数据,尝试从备份恢复
十三、1.3 旧几何类型检查(oldGeometryCheck)
错误信息:Spatial data columns created in MySQL 5.6。
错误级别:ERROR(不适用于 8.0.24+)。
十四、错误原因
在 MySQL 5.6中创建的空间数据列使用了旧的存储格式,8.0.24之前的 MySQL 8.0版本不支持直接升级这些表。
十五、技术背景
| 问题点 | 说明 |
| 影响的数据类型 | POINT,GEOMETRY,POLYGON,LINESTRING,MULTIPOINT,MULTILINESTRING,MULTIPOLYGON,GEOMETRYCOLLECTION |
| 版本限制 | 8.0.24之前的版本无法升级这些表 |
| 推荐方案 | 直接升级到8.0.24或更新的版本 |
十六、解决方案
方案一:直接升级到 MySQL 8.0.24+(推荐)
社区版本和云数据库 MySQL 内核版本的对应关系可参见 TXSQL 引擎内核版本更新动态,升级云数据库 MySQL 内核版本的操作请参见 升级内核小版本。
方案二:升级前重建受影响的表
— 查找受影响的表SELECT table_schema, table_name, column_name, data_typeFROM information_schema.columnsWHERE data_type IN ('point', 'geometry', 'polygon', 'linestring', 'multipoint', 'multilinestring', 'multipolygon', 'geometrycollection');– 重建表ALTER TABLE 数据库名.表名 FORCE;
十七、1.4 Instant DDL 不兼容(CHECK TABLE FOR UPGRADE)
错误信息:has done instant ddl, cannot upgrade to 8.0。
错误级别:ERROR。
十八、错误原因
这个错误是因为你的 MySQL 5.7数据库中有些表执行过 Instant DDL 操作(主要是 INSTANT ADD COLUMN 秒级加列功能),而这种操作产生的元数据格式与 MySQL 8.0不兼容。
十九、技术背景
| 问题点 | 说明 |
| Instant DDL 是什么 | 一种快速加列功能,只修改表的元数据而不重写表数据,可以秒级完成加列操作 |
| 为何不兼容 | MySQL 5.7(部分云厂商版本)和 MySQL 8.0的 Instant DDL 实现方式不同,数据字典格式存在差异 |
| MySQL 8.0 的变化 | MySQL 8.0重新设计了数据字典结构,引入了 row_version 等新机制,无法正确解析 MySQL 5.7遗留的 Instant DDL 元数据 |
20、解决方案
升级前需要重建受影响的表,消除 Instant DDL 的元数据:
— 1. 检查哪些表执行过 Instant DDLSELECT b.name from information_schema.INNODB_SYS_INSTANT_COLS a join information_schema.INNODB_SYS_TABLES b on a.table_id=b.table_id;– 2. 检查哪些表执行过 modify columnSELECT b.name from information_schema.INNODB_SYS_INSTANT_MODIFIED_COLS a join information_schema.INNODB_SYS_TABLES b on a.table_id=b.table_id;– 3. 对这些表执行重建(二选一)– 方法一:OPTIMIZE TABLE 数据库名.表名;– 方法二:ALTER TABLE 数据库名.表名 ENGINE=InnoDB;
重建完成后,表的数据会被重写为标准格式,Instant DDL 的元数据被清除,再次执行升级检查即可通过。
21、1.5 CHECK TABLE FOR UPGRADE 检查(checkTableOutput)
错误信息:Issues reported by 'check table x for upgrade' command。
错误级别:动态(ERROR/WARNING/NOTICE)。
22、错误原因
MySQL Shell 会对所有非系统表执行 CHECK TABLE … FOR UPGRADE 命令,该命令会检测表的各种潜在问题。
23、解决方案
— 手动执行检查CHECK TABLE 数据库名.表名 FOR UPGRADE;– 根据返回的具体错误信息进行修复– 通常的修复方法:REPAIR TABLE 数据库名.表名;– 或ALTER TABLE 数据库名.表名 FORCE;
25、2.1 存储过程/函数语法检查(routinesSyntaxCheck)
错误信息:MySQL 8.0 syntax check for routine-like objects。
错误级别:ERROR。
26、错误原因
存储过程、函数、触发器或事件的定义包含 MySQL 8.0 不兼容的语法,最常见的原因是使用了与新保留关键字冲突的标识符。
27、技术背景
| 问题点 | 说明 |
| 检查对象 | 存储过程、函数、触发器、事件 |
| 常见原因 | 使用了新版本的保留关键字作为标识符 |
| 检测方式 | 使用 MySQL 8.0语法解析器验证定义 |
28、解决方案
— 1. 查看存储过程/函数定义SHOW CREATE PROCEDURE 数据库名.过程名;SHOW CREATE FUNCTION 数据库名.函数名;– 2. 为冲突的标识符添加反引号– 修改前CREATE PROCEDURE test()BEGIN SELECT rank FROM users; — rank 是 MySQL 8.0的保留字END;– 修改后CREATE PROCEDURE test()BEGIN SELECT `rank` FROM users;END;– 3. 重新创建存储过程DROP PROCEDURE IF EXISTS 数据库名.过程名;CREATE PROCEDURE 数据库名.过程名 …
29、2.2 保留关键字冲突检查(reservedKeywordsCheck)
错误信息:Usage of db objects with names conflicting with new reserved keywords。
错误级别:WARNING。
30、错误原因
数据库对象(Schema、表、列、触发器、视图、存储过程、事件)的名称与 MySQL 8.0新增的保留关键字冲突。
31、技术背景
MySQL 8.0各版本新增的保留关键字:
| 版本 | 新增保留关键字 |
| 8.0.11 | ADMIN,CUBE,CUME_DIST,DENSE_RANK,EMPTY,EXCEPT,FIRST_VALUE,FUNCTION,GROUPING,GROUPS,JSON_TABLE,LAG,LAST_VALUE,LEAD,NTH_VALUE,NTILE,OF,OVER,PERCENT_RANK,PERSIST,PERSIST_ONLY,RANK,RECURSIVE,ROW,ROWS,ROW_NUMBER,SYSTEM,WINDOW |
| 8.0.14 | LATERAL |
| 8.0.17 | ARRAY,MEMBER |
| 8.0.31 | FULL,INTERSECT |
32、解决方案
— 1. 查找使用保留关键字的对象SELECT table_schema, table_name, column_nameFROM information_schema.columnsWHERE column_name IN ('RANK', 'ROWS', 'GROUPS', 'FUNCTION', 'SYSTEM', …);– 2. 修改应用程序 SQL,为这些标识符添加反引号– 修改前SELECT rank, rows FROM my_table;– 修改后SELECT `rank`, `rows` FROM my_table;– 3. 或者重命名对象(如果可行)ALTER TABLE my_table CHANGE rank ranking INT;
33、2.3 UTF8MB3 字符集检查(utf8mb3Check)
错误信息:Usage of utf8mb3 charset。
错误级别:WARNING。
34、错误原因
数据库或表使用了 utf8(即 utf8mb3)字符集。在 MySQL 8.0中,utf8mb3 已被弃用,建议使用 utf8mb4。
35、技术背景
| 问题点 | 说明 |
| utf8mb3 限制 | 最多只能存储3字节的 UTF-8 字符 |
| utf8mb4 优势 | 支持完整的 Unicode,包括 emoji 表情符号 |
| MySQL 8.0的变化 | utf8 别名将在未来版本指向 utf8mb4 |
36、解决方案
— 1. 查找使用 utf8/utf8mb3 的对象SELECT table_schema, table_name, column_name, character_set_nameFROM information_schema.columnsWHERE character_set_name IN ('utf8', 'utf8mb3') and table_schema not in ('information_schema','mysql','performance_schema','sys');– 2. 转换数据库字符集ALTER DATABASE 数据库名 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;– 3. 转换表字符集ALTER TABLE 数据库名.表名 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;– 4. 批量转换脚本SELECT CONCAT('ALTER TABLE `', table_schema, '`.`', table_name, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;')FROM information_schema.tablesWHERE table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys') AND table_collation LIKE 'utf8_%';
37、2.4 MySQL Schema 表名冲突检查(mysqlSchemaCheck)
错误信息:Table names in the mysql schema conflicting with new tables in 8.0。
错误级别:ERROR。
38、错误原因
mysql 系统数据库中存在与 MySQL 8.0新增系统表同名的用户表。
39、技术背景
MySQL 8.0新增的系统表名:
catalogs, character_sets, collations, column_type_elements, columns, dd_properties, events, foreign_key_column_usage, foreign_keys, index_column_usage, index_partitions, index_stats, indexes, parameter_type_elements, parameters, routines, schemata, st_spatial_reference_systems, table_partition_values, table_partitions, table_stats, tables, tablespace_files, tablespaces, triggers, view_routine_usage, view_table_usage, component, default_roles, global_grants, innodb_ddl_log, innodb_dynamic_metadata, password_history, role_edges
40、解决方案
— 1. 查找冲突的表SELECT table_name FROM information_schema.tables WHERE table_schema = 'mysql' AND table_name IN ('catalogs', 'character_sets', 'collations', …);– 2. 重命名冲突的表RENAME TABLE mysql.冲突表名 TO mysql.冲突表名_backup;– 或移动到其他数据库RENAME TABLE mysql.冲突表名 TO other_db.表名;
41、2.5 外键约束名长度检查(foreignKeyLengthCheck)
错误信息:Foreign key constraint names longer than 64 characters。
错误级别:ERROR。
42、错误原因
外键约束名称超过64个字符。MySQL 8.0严格限制约束名长度不能超过64字符。
43、解决方案
— 1. 查找超长约束名SELECT i.TABLE_SCHEMA, i.TABLE_NAME, i.CONSTRAINT_NAME, LENGTH(i.CONSTRAINT_NAME) as name_lengthFROM information_schema.TABLE_CONSTRAINTS iWHERE i.CONSTRAINT_TYPE = 'FOREIGN KEY' AND LENGTH(i.CONSTRAINT_NAME) > 64;– 2. 重建外键约束– 先删除旧约束ALTER TABLE 数据库名.表名 DROP FOREIGN KEY 旧约束名;– 再创建新约束(使用较短的名称)ALTER TABLE 数据库名.表名 ADD CONSTRAINT 新约束名 FOREIGN KEY (列名) REFERENCES 引用表(引用列);
44、2.6 MAXDB SQL 模式检查(maxdbFlagCheck)
错误信息:Usage of obsolete MAXDB sql_mode flag。
错误级别:WARNING。
45、错误原因
存储过程、事件或触发器中持久化了已废弃的 MAXDB sql_mode 选项。
46、技术背景
| 问题点 | 说明 |
| MAXDB 模式作用 | 使 DATETIME 行为类似 TIMESTAMP |
| 升级影响 | MySQL 8.0会自动清除此模式,可能影响1970年前或2037年后的日期处理 |
47、解决方案
— 1. 查找使用 MAXDB 模式的对象SELECT ROUTINE_SCHEMA, ROUTINE_NAME, SQL_MODEFROM information_schema.ROUTINESWHERE SQL_MODE LIKE '%MAXDB%';– 2. 重新创建存储过程,移除 MAXDB 模式– 导出存储过程定义SHOW CREATE PROCEDURE 数据库名.过程名;– 修改 SQL_MODE,移除 MAXDB– 重新创建存储过程
48、2.7 过时 SQL 模式标志检查(sqlModeFlagCheck)
错误信息:Usage of obsolete sql_mode flags。
错误级别:NOTICE。
49、错误原因
对象中使用了已在 MySQL 8.0中移除的 sql_mode 标志。
50、技术背景
已移除的 sql_mode 标志:
·DB2
·MSSQL
·MYSQL323
·MYSQL40
·NO_AUTO_CREATE_USER
·NO_FIELD_OPTIONS
·NO_KEY_OPTIONS
·NO_TABLE_OPTIONS
·ORACLE
·POSTGRESQL
51、解决方案
— 1. 查找使用过时模式的对象SELECT ROUTINE_SCHEMA, ROUTINE_NAME, SQL_MODEFROM information_schema.ROUTINESWHERE SQL_MODE REGEXP 'DB2|MSSQL|MYSQL323|MYSQL40|NO_AUTO_CREATE_USER|ORACLE|POSTGRESQL';– 2. 重新创建对象,移除过时的 sql_mode 标志
52、2.8 ENUM/SET 元素长度检查(enumSetElementLengthCheck)
错误信息:ENUM/SET column definitions containing elements longer than 255 characters。
错误级别:ERROR。
53、错误原因
ENUM 或 SET 类型的列包含超过255字符的元素值。
54、解决方案
— 1. 查找超长元素SELECT table_schema, table_name, column_name, data_type, character_maximum_lengthFROM information_schema.columnsWHERE data_type IN ('enum', 'set') AND character_maximum_length > 255 and table_schema not in ('information_schema','mysql','performance_schema','sys');– 2. 修改列定义,缩短元素值ALTER TABLE 数据库名.表名 MODIFY COLUMN 列名 ENUM('短值1', '短值2', …);
55、2.9 已移除函数检查(removedFunctionsCheck)
错误信息:Usage of removed functions。
错误级别:ERROR。
56、错误原因
视图、存储过程/函数、生成列、触发器或事件中使用了 MySQL 8.0已移除的函数。
57、技术背景
已移除的函数及替代方案:
| 已移除函数 | 替代方案 |
| ENCODE() | AES_ENCRYPT() |
| DECODE() | AES_DECRYPT() |
| ENCRYPT() | SHA2() |
| DES_ENCRYPT() | AES_ENCRYPT() |
| DES_DECRYPT() | AES_DECRYPT() |
| PASSWORD() | 无直接替代,使用应用层加密 |
| AREA() | ST_AREA() |
| ASBINARY() | ST_ASBINARY() |
| ASTEXT() | ST_ASTEXT() |
| BUFFER() | ST_BUFFER() |
| CENTROID() | ST_CENTROID() |
| CONTAINS() | MBRCONTAINS() 或 ST_CONTAINS() |
| CROSSES() | ST_CROSSES() |
| DIMENSION() | ST_DIMENSION() |
| DISJOINT() | MBRDISJOINT() 或 ST_DISJOINT() |
| DISTANCE() | ST_DISTANCE() |
| ENDPOINT() | ST_ENDPOINT() |
| ENVELOPE() | ST_ENVELOPE() |
| EQUALS() | MBREQUALS() 或 ST_EQUALS() |
| EXTERIORRING() | ST_EXTERIORRING() |
| GEOMCOLLFROMTEXT() | ST_GEOMCOLLFROMTEXT() |
| GEOMCOLLFROMWKB() | ST_GEOMCOLLFROMWKB() |
| GEOMETRYCOLLECTION() | ST_GEOMETRYCOLLECTION() |
| GEOMETRYN() | ST_GEOMETRYN() |
| GEOMETRYTYPE() | ST_GEOMETRYTYPE() |
| GEOMFROMTEXT() | ST_GEOMFROMTEXT() |
| GEOMFROMWKB() | ST_GEOMFROMWKB() |
| GLENGTH() | ST_LENGTH() |
| INTERIORRINGN() | ST_INTERIORRINGN() |
| INTERSECTS() | MBRINTERSECTS() 或 ST_INTERSECTS() |
| ISCLOSED() | ST_ISCLOSED() |
| ISEMPTY() | ST_ISEMPTY() |
| ISSIMPLE() | ST_ISSIMPLE() |
| LINEFROMTEXT() | ST_LINEFROMTEXT() |
| LINEFROMWKB() | ST_LINEFROMWKB() |
| LINESTRING() | ST_LINESTRING() |
| MLINEFROMTEXT() | ST_MLINEFROMTEXT() |
| MLINEFROMWKB() | ST_MLINEFROMWKB() |
| MPOINTFROMTEXT() | ST_MPOINTFROMTEXT() |
| MPOINTFROMWKB() | ST_MPOINTFROMWKB() |
| MPOLYFROMTEXT() | ST_MPOLYFROMTEXT() |
| MPOLYFROMWKB() | ST_MPOLYFROMWKB() |
| MULTILINESTRING() | ST_MULTILINESTRING() |
| MULTIPOINT() | ST_MULTIPOINT() |
| MULTIPOLYGON() | ST_MULTIPOLYGON() |
| NUMGEOMETRIES() | ST_NUMGEOMETRIES() |
| NUMINTERIORRINGS() | ST_NUMINTERIORRINGS() |
| NUMPOINTS() | ST_NUMPOINTS() |
| OVERLAPS() | MBROVERLAPS() 或 ST_OVERLAPS() |
| POINTFROMTEXT() | ST_POINTFROMTEXT() |
| POINTFROMWKB() | ST_POINTFROMWKB() |
| POINTN() | ST_POINTN() |
| POLYFROMTEXT() | ST_POLYFROMTEXT() |
| POLYFROMWKB() | ST_POLYFROMWKB() |
| POLYGON() | ST_POLYGON() |
| SRID() | ST_SRID() |
| STARTPOINT() | ST_STARTPOINT() |
| TOUCHES() | ST_TOUCHES() |
| WITHIN() | MBRWITHIN() 或 ST_WITHIN() |
| X() | ST_X() |
| Y() | ST_Y() |
58、解决方案
— 1. 查找使用已移除函数的视图SELECT table_schema, table_name, view_definitionFROM information_schema.viewsWHERE view_definition REGEXP 'ENCODE|DECODE|ENCRYPT|PASSWORD|\\\\bAREA\\\\b|\\\\bASBINARY\\\\b' and table_schema not in ('information_schema','mysql','performance_schema','sys');– 2. 修改视图定义,使用替代函数CREATE OR REPLACE VIEW 视图名 ASSELECT ST_AREA(geom_column) AS area — 替换 AREA()FROM 表名;– 3. 类似地修改存储过程、触发器等
59、2.10 GROUP BY ASC/DESC 语法检查(groupByAscCheck)
错误信息:Usage of removed GROUP BY ASC/DESC syntax。
错误级别:ERROR。
60、错误原因
视图、存储过程/函数、触发器或事件中使用了已移除的 GROUP BY … ASC/DESC 语法。
61、技术背景
| 问题点 | 说明 |
| 旧语法 | GROUP BY column ASC 或 GROUP BY column DESC |
| MySQL 8.0变化 | GROUP BY 不再支持 ASC/DESC 修饰符 |
| 正确做法 | 排序应使用 ORDER BY 子句 |
62、解决方案
— 修改前(错误)SELECT category, COUNT(*) FROM products GROUP BY category DESC;– 修改后(正确)SELECT category, COUNT(*) FROM products GROUP BY category ORDER BY category DESC;
63、2.11 零日期检查(zeroDatesCheck)
错误信息:Zero Date, Datetime, and Timestamp values。
错误级别:WARNING。
64、错误原因
数据库中存在零日期值(如 0000-00-00),或者 sql_mode 未包含 NO_ZERO_DATE 和 NO_ZERO_IN_DATE。
65、技术背景
| 问题点 | 说明 |
| 默认行为变化 | MySQL 8.0默认不允许零日期值 |
| 影响范围 | 列默认值、现有数据 |
| sql_mode 变化 | NO_ZERO_DATE 和 NO_ZERO_IN_DATE 默认启用 |
66、解决方案
— 1. 查找使用零日期默认值的列SELECT table_schema, table_name, column_name, column_defaultFROM information_schema.columnsWHERE column_default LIKE '0000-00-00%' and table_schema not in ('information_schema','mysql','performance_schema','sys');– 2. 查找包含零日期的数据SELECT COUNT(*) FROM 表名 WHERE date_column = '0000-00-00';– 3. 更新零日期为有效值UPDATE 表名 SET date_column = '1970-01-01' WHERE date_column = '0000-00-00';– 4. 修改列默认值ALTER TABLE 表名 ALTER COLUMN date_column SET DEFAULT '1970-01-01';– 或ALTER TABLE 表名 ALTER COLUMN date_column SET DEFAULT CURRENT_TIMESTAMP;
67、2.12 FTS 表名检查(ftsTablenameCheck)
错误信息:Table names containing 'FTS'。
错误级别:ERROR(不适用于 8.0.18+ 或 Windows)。
68、错误原因
表名包含 'FTS' 字符串(区分大小写)。这与 InnoDB 全文索引的内部表命名冲突。
69、解决方案
— 1. 查找包含 FTS 的表名SELECT table_schema, table_name FROM information_schema.tables WHERE table_name LIKE BINARY '%FTS%';– 2. 升级前临时重命名(将任一字母改为小写)RENAME TABLE myFTStable TO myFtStable;– 3. 升级完成后可改回原名RENAME TABLE myFtStable TO myFTStable;
70、2.13 生成列函数语义变化检查(changedFunctionsInGeneratedColumnsCheck)
错误信息:Indexes on functions with changed semantics。
错误级别:WARNING。
71、错误原因
生成列上有索引,且这些生成列使用了语义已改变的函数(例如 CAST、CONVERT)。
72、技术背景
| 问题点 | 说明 |
| 影响函数 | CAST,CONVERT |
| 潜在问题 | 可能导致复制问题和索引损坏 |
| 适用版本 | 升级到8.0.28+时需注意 |
73、解决方案
— 1. 查找受影响的生成列SELECT table_schema, table_name, column_name, generation_expressionFROM information_schema.columnsWHERE generation_expression IS NOT NULL AND generation_expression REGEXP 'CAST|CONVERT' and table_schema not in ('information_schema','mysql','performance_schema','sys');– 2. 重建索引ALTER TABLE 表名 DROP INDEX 索引名;ALTER TABLE 表名 ADD INDEX 索引名 (生成列名);
74、2.14 无效 MySQL 5.7名称检查((mysqlInvalid57NamesCheck)
错误信息:Check for invalid table names and schema names used in 5.7。
错误级别:ERROR。
75、错误原因
存在以 #mysql50# 开头的 Schema 或表名,这是 MySQL 5.0 遗留的命名格式。
76、解决方案
— 1. 使用 mysqlcheck 工具修复mysqlcheck –check-upgrade –all-databasesmysqlcheck –fix-db-names –fix-table-names –all-databases– 2. 或使用 SQL 命令ALTER DATABASE `#mysql50#旧名称` UPGRADE DATA DIRECTORY NAME;
77、2.15 孤立存储过程检查(mysqlOrphanedRoutinesCheck)
错误信息:Check for orphaned routines in 5.7。
错误级别:ERROR。
78、错误原因
存储过程或函数引用的 Schema 已不存在,成为"孤立"状态。
79、解决方案
— 1. 查找孤立的存储过程SELECT ROUTINE_SCHEMA, ROUTINE_NAME, 'is orphaned' FROM information_schema.routines WHERE NOT EXISTS ( SELECT SCHEMA_NAME FROM information_schema.schemata WHERE ROUTINE_SCHEMA = SCHEMA_NAME);– 2. 删除孤立的存储过程DROP PROCEDURE IF EXISTS 不存在的 schema.过程名;DROP FUNCTION IF EXISTS 不存在的 schema.函数名;
80、2.16 美元符号名称检查(mysqlDollarSignNameCheck)
错误信息:Check for deprecated usage of single dollar signs in object names。
错误级别:WARNING。
81、错误原因
对象名称以美元符号 $ 开头但不以 $ 结尾,这是已弃用的用法。
82、解决方案
— 修改对象名称,使其以 $ 结尾– 例如:$example 改为 $example$ 或 exampleRENAME TABLE `$mytable` TO `$mytable$`;– 或RENAME TABLE `$mytable` TO `mytable`;
83、2.17 索引过大检查(mysqlIndexTooLargeCheck)
错误信息:Check for indexes that are too large to work on higher versions of MySQL Server than 5.7。
错误级别:ERROR。
84、错误原因
在旧版本 MySQL(5.7.34 之前)中创建的索引过大。对于 compact 或 redundant 行格式的表,索引列不应超过767字节。
85、解决方案
— 1. 查找过大的索引SELECT table_schema, table_name, index_name, GROUP_CONCAT(column_name) as columnsFROM information_schema.statisticsWHERE table_schema NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')GROUP BY table_schema, table_name, index_nameHAVING SUM(sub_part) > 767 OR (SUM(sub_part) IS NULL AND COUNT(*) > 1);– 2. 删除过大的索引ALTER TABLE 表名 DROP INDEX 索引名;– 3. 考虑使用前缀索引或更改行格式ALTER TABLE 表名 ROW_FORMAT=DYNAMIC;ALTER TABLE 表名 ADD INDEX 索引名 (列名(191));
86、2.18 空点表语法检查(mysqlEmptyDotTableSyntaxCheck)
错误信息:Check for deprecated '.<table>' syntax used in routines。
错误级别:ERROR。
87、错误原因
存储过程、事件或触发器中使用了已弃用的 .<table> 语法(省略数据库名,只有点和表名)。
88、解决方案
— 修改存储过程,使用完整的 database.table 语法– 修改前SELECT * FROM .mytable;– 修改后SELECT * FROM mydb.mytable;
89、2.19 无效引擎外键检查(mysqlInvalidEngineForeignKeyCheck)
错误信息:Check for columns that have foreign keys pointing to tables from a different database engine。
错误级别:ERROR。
90、错误原因
外键指向使用不同存储引擎的表。这通常是在 FOREIGN_KEY_CHECKS=0 时的错误操作导致的。
91、解决方案
— 1. 查找无效的外键SELECT fk.TABLE_SCHEMA, fk.TABLE_NAME, fk.CONSTRAINT_NAME, fk.REFERENCED_TABLE_SCHEMA, fk.REFERENCED_TABLE_NAME, t1.ENGINE as source_engine, t2.ENGINE as target_engineFROM information_schema.KEY_COLUMN_USAGE fkJOIN information_schema.TABLES t1 ON fk.TABLE_SCHEMA = t1.TABLE_SCHEMA AND fk.TABLE_NAME = t1.TABLE_NAMEJOIN information_schema.TABLES t2 ON fk.REFERENCED_TABLE_SCHEMA = t2.TABLE_SCHEMA AND fk.REFERENCED_TABLE_NAME = t2.TABLE_NAMEWHERE fk.REFERENCED_TABLE_NAME IS NOT NULL AND t1.ENGINE != t2.ENGINE;– 2. 删除无效的外键ALTER TABLE 表名 DROP FOREIGN KEY 约束名;– 3. 或统一存储引擎后重建外键ALTER TABLE 表名 ENGINE=InnoDB;
93、3.1 非原生分区检查(nonNativePartitioningCheck)
错误信息:Partitioned tables using engines with non native partitioning。
错误级别:ERROR。
94、错误原因
分区表使用了不支持原生分区的存储引擎。MySQL 8.0中只有 InnoDB 和 NDB 支持原生分区。
95、技术背景
| 问题点 | 说明 |
| 支持原生分区的引擎 | InnoDB,NDB/NDBCLUSTER |
| 不支持的引擎 | MyISAM,ARCHIVE,CSV 等 |
| MySQL 8.0变化 | 移除了通用分区处理程序 |
96、解决方案
— 1. 查找使用非原生分区的表SELECT table_schema, table_name, engineFROM information_schema.tablesWHERE create_options LIKE '%partitioned%' AND UPPER(engine) NOT IN ('INNODB', 'NDB', 'NDBCLUSTER');– 2. 转换为 InnoDBALTER TABLE 数据库名.表名 ENGINE=InnoDB;– 3. 或移除分区ALTER TABLE 数据库名.表名 REMOVE PARTITIONING;
97、3.2 引擎混淆检查(engineMixupCheck)
错误信息:Tables recognized by InnoDB that belong to a different engine。
错误级别:ERROR。
98、错误原因
表被 InnoDB 引擎识别(存在 .ibd 文件),但 SQL 层认为它属于不同的引擎(如 MyISAM)。这通常是手动删除 InnoDB 表文件后创建同名 MyISAM 表导致的。
99、解决方案
— 复杂情况,需要多步骤处理:– 1. 重命名当前表RENAME TABLE 问题表 TO 问题表_temp;– 2. 创建虚拟 InnoDB 表(使用相同结构)CREATE TABLE 问题表 (id INT) ENGINE=InnoDB;– 3. 删除虚拟表(清理 InnoDB 数据字典)DROP TABLE 问题表;– 4. 将临时表改回原名RENAME TABLE 问题表_temp TO 问题表;
101、4.1 循环目录引用检查(circularDirectoryCheck)
错误信息:Circular directory references in tablespace data file paths。
错误级别:ERROR。
102、错误原因
表空间数据文件路径包含循环目录引用(例如 /../)。MySQL 8.0.17 起不再允许这种路径。
103、解决方案
— 1. 查找包含循环引用的表空间SELECT FILE_NAME FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'TABLESPACE' AND FILE_NAME LIKE '%/../%'– 2. 移动数据文件到正常路径– 需要停止 MySQL,手动移动文件,然后更新数据字典– 或重建表ALTER TABLE 表名 ENGINE=InnoDB;
105、5.1 已移除系统日志变量检查(removedSysLogVars)
错误信息:Removed system variables for error logging to the system log configuration。
错误级别:ERROR。
106、错误原因
配置文件中使用了已移除的系统日志相关变量。
107、技术背景
| 已移除变量 | 替代变量 |
| log_syslog_facility | syseventlog.facility |
| log_syslog_include_pid | syseventlog.include_pid |
| log_syslog_tag | syseventlog.tag |
| log_syslog | 无直接替代,使用 log_sink_syseventlog 组件 |
108、解决方案
修改 my.cnf 配置文件:
# 修改前[mysqld]log_syslog=1log_syslog_facility=daemonlog_syslog_tag=mysql# 修改后[mysqld]# 加载系统日志组件log_error_services='log_filter_internal; log_sink_internal; log_sink_syseventlog'# 使用新变量名syseventlog.facility=daemonsyseventlog.tag=mysql
109、5.2 已移除系统变量检查(removedSysVars)
错误信息:Removed system variables。
错误级别:ERROR。
110、错误原因
配置文件中使用了已在 MySQL 8.0中移除的系统变量。
111、技术背景
已移除变量及替代方案(部分):
| 已移除变量 | 替代方案 |
| date_format | 无 |
| datetime_format | 无 |
| have_crypt | 无 |
| ignore_builtin_innodb | 无 |
| ignore_db_dirs | 无 |
| innodb_checksums | innodb_checksum_algorithm |
| innodb_file_format | 无(MySQL 8.0只支持 Barracuda) |
| innodb_file_format_check | 无 |
| innodb_file_format_max | 无 |
| innodb_large_prefix | 无(MySQL 8.0默认启用) |
| innodb_locks_unsafe_for_binlog | 无 |
| innodb_stats_sample_pages | innodb_stats_transient_sample_pages |
| innodb_support_xa | 无(MySQL 8.0始终启用) |
| innodb_undo_logs | innodb_rollback_segments |
| log_warnings | log_error_verbosity |
| max_tmp_tables | 无 |
| metadata_locks_cache_size | 无 |
| metadata_locks_hash_instances | 无 |
| old_passwords | 无 |
| query_cache_limit | 无(查询缓存已移除) |
| query_cache_min_res_unit | 无 |
| query_cache_size | 无 |
| query_cache_type | 无 |
| query_cache_wlock_invalidate | 无 |
| secure_auth | 无(MySQL 8.0始终启用) |
| sync_frm | 无 |
| tx_isolation | transaction_isolation |
| tx_read_only | transaction_read_only |
112、解决方案
修改 my.cnf 配置文件,移除或替换已移除的变量:
# 修改前[mysqld]query_cache_size=64Mquery_cache_type=1innodb_file_format=Barracudatx_isolation=READ-COMMITTEDlog_warnings=2# 修改后[mysqld]# 移除 query_cache 相关配置(查询缓存已移除)# 移除 innodb_file_format(8.0 只支持 Barracuda)transaction_isolation=READ-COMMITTEDlog_error_verbosity=2
113、5.3 系统变量新默认值检查(sysVarsNewDefaults)
错误信息:System variables with new default values。
错误级别:WARNING。
114、错误原因
某些系统变量在 MySQL 8.0中有了新的默认值,如果应用程序依赖旧的默认值,可能会出现问题。
115、技术背景
重要的默认值变化:
| 变量 | MySQL 5.7 默认值 | MySQL 8.0 默认值 | 影响 |
| character_set_server | latin1 | utf8mb4 | 新建表的默认字符集 |
| collation_server | latin1_swedish_ci | utf8mb4_0900_ai_ci | 新建表的默认排序规则 |
| explicit_defaults_for_timestamp | OFF | ON | TIMESTAMP 列行为 |
| max_allowed_packet | 4MB | 64MB | 单个数据包大小限制 |
| event_scheduler | OFF | ON | 事件调度器是否启动 |
| log_bin | OFF | ON | 是否启用二进制日志 |
| innodb_autoinc_lock_mode | 1 | 2 | 自增锁模式 |
| innodb_flush_neighbors | 1 | 0 | 刷新相邻页 |
| innodb_max_dirty_pages_pct_lwm | 0 | 10 | 脏页低水位 |
| innodb_undo_tablespaces | 0 | 2 | Undo 表空间数量 |
| innodb_undo_log_truncate | OFF | ON | 是否截断 Undo 日志 |
| back_log | -1 | 151 | 连接队列大小 |
| max_error_count | 64 | 1024 | 最大错误数 |
| optimizer_trace_max_mem_size | 16KB | 1MB | 优化器跟踪内存 |
116、解决方案
如果依赖旧的默认值,在 my.cnf 中显式设置:
[mysqld]# 保持 MySQL 5.7的字符集行为character_set_server=latin1collation_server=latin1_swedish_ci# 保持 MySQL 5.7的 TIMESTAMP 行为explicit_defaults_for_timestamp=OFF# 保持 MySQL 5.7的自增锁模式(如果有基于语句的复制)innodb_autoinc_lock_mode=1# 如果不需要二进制日志skip-log-bin
118、6.1 默认认证插件检查(defaultAuthenticationPlugin)
错误信息:New default authentication plugin considerations。
错误级别:WARNING(手动检查)。
119、错误原因
MySQL 8.0的默认认证插件从 mysql_native_password 改为 caching_sha2_password,可能导致旧客户端连接问题。
120、技术背景
| 问题点 | 说明 |
| 新默认插件 | caching_sha2_password |
| 旧默认插件 | mysql_native_password |
| 安全性 | caching_sha2_password 提供更强的密码哈希 |
| 兼容性 | 旧客户端/驱动可能不支持新插件 |
121、解决方案
方案一:升级客户端驱动到支持 caching_sha2_password 的版本。
方案二:临时使用旧认证插件。
# my.cnf[mysqld]default_authentication_plugin=mysql_native_password
方案三:为特定用户使用旧插件。
— 创建使用旧插件的用户CREATE USER 'user'@'host' IDENTIFIED WITH mysql_native_password BY 'password';– 或修改现有用户ALTER USER 'user'@'host' IDENTIFIED WITH mysql_native_password BY 'password';
122、七、问题级别说明
| 级别 | 说明 | 处理要求 |
| ERROR | 严重问题,必须在升级前解决 | 升级会失败或导致数据不可用 |
| WARNING | 潜在问题,建议解决 | 可能影响升级后的功能或性能 |
| NOTICE | 提示信息 | 不影响升级,但值得关注 |
123、附录:快速检查脚本
— 综合预检查脚本– 运行此脚本可快速发现大部分升级问题– 1. 检查旧时间格式SELECT '旧时间格式' as check_type, table_schema, table_name, column_nameFROM information_schema.columns WHERE column_type LIKE '%5.5 binary format%' and table_schema not in ('information_schema','mysql','performance_schema','sys');– 2. 检查 utf8mb3 字符集SELECT 'UTF8MB3字符集' as check_type, table_schema, table_name, column_nameFROM information_schema.columnsWHERE character_set_name IN ('utf8', 'utf8mb3') and table_schema not in ('information_schema','mysql','performance_schema','sys')LIMIT 20;– 3. 检查零日期默认值SELECT '零日期默认值' as check_type, table_schema, table_name, column_nameFROM information_schema.columnsWHERE column_default LIKE '0000-00-00%' and table_schema not in ('information_schema','mysql','performance_schema','sys')LIMIT 20;– 4. 检查非 InnoDB 分区表SELECT '非原生分区' as check_type, table_schema, table_name, engineFROM information_schema.tablesWHERE create_options LIKE '%partitioned%' AND UPPER(engine) NOT IN ('INNODB', 'NDB', 'NDBCLUSTER') and table_schema not in ('information_schema','mysql','performance_schema','sys');– 5. 检查外键约束名长度SELECT '外键名过长' as check_type, SUBSTRING_INDEX(id, '/', 1) as db_name, SUBSTRING_INDEX(id, '/', -1) as table_name, LENGTH(SUBSTRING_INDEX(id, '/', -1)) as name_lengthFROM information_schema.innodb_sys_foreignWHERE LENGTH(SUBSTRING_INDEX(id, '/', -1)) > 64;– 6. 检查哪些表执行过 Instant DDLSELECT b.name from information_schema.INNODB_SYS_INSTANT_COLS a join information_schema.INNODB_SYS_TABLES b on a.table_id=b.table_id;– 7. 检查哪些表执行过 modify columnSELECT b.name from information_schema.INNODB_SYS_INSTANT_MODIFIED_COLS a join information_schema.INNODB_SYS_TABLES b on a.table_id=b.table_id;– 8. 检查孤立存储过程SELECT '孤立存储过程' as check_type, ROUTINE_SCHEMA, ROUTINE_NAMEFROM information_schema.routines WHERE NOT EXISTS ( SELECT SCHEMA_NAME FROM information_schema.schemata WHERE ROUTINE_SCHEMA = SCHEMA_NAME);
124、参考资料
·MySQL 8.0升级指南
·MySQL 8.0新特性
·MySQL 8.0移除的特性
·MySQL Shell 升级检查器