云数据库 MySQL MySQL 5.7升级 MySQL 8.0预检查及问题修复指南

这篇说说MySQL 5.7升级至8.0前的预检查项,涵盖InnoDB内部结构、数据库对象定义、存储引擎、表空间、系统变量及认证插件等检查,并给出各问题的错误原因、检测方法与解决方案,确保升级顺利。 InnoDB检查:旧时间格式、Schema不一致、Instant DDL不兼容等问题均需在升级前重建表解决。 数据库对象检查:存储过程语法、保留关键字冲突、utf8mb3字符集等需修改或转换以兼容8.0。 系统变量检查:已。

相关产品
云数据库 MySQL 产品页,含版本规格、价格与购买入口。

一、目录

·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 升级检查器

赞 (0)
上一篇 4天前
下一篇 4天前