【MySQL 8.0】MySQL5.7升级MySQL8.0的步骤与常见问题

TangLu MySQL 2024-03-03 172 0

一、为什么推荐将MySQL从5.7升级到8.0

MySQL5.7的生命周期已经在2023年10月结束,沿用老版本将存在以下问题:

· 所有漏洞不再修复,如自增ID回退问题

· 核心新特性无法使用,如秒级加列、在线持久化配置

· 生态衰退,如Xtrabackup等工具的使用

· 后期跨版本升级风险更大


二、升级过程中可能出现的问题

这里的问题都是实际升级过程中发生的,有代表意义

1、注释乱码问题

在升级过程中有部分表或字段的注释出现了乱码,原因无法追究,但是乱码会导致升级失败,所以需要先对这部分乱码内容进行修复

1.jpg


2、清理孤儿存储过程

在部分实例中发现有存储过程变为了孤儿存储过程(即存储过程所依赖的库表已不存在),这部分存储过程会导致升级失败。在正式升级前,需对存储过程进行梳理,清理无用的存储过程

#查看存储过程
SHOW PROCEDURE STATUS;

#删除无用的存储过程
DROP PROCEDURE your_database_name.your_procedure_name;

#部分存储过程无法直接通过SHOW命令查询,可以通过特殊方式删除
SELECT * FROM mysql.proc WHERE db = 'your_database_name';
DELETE FROM mysql.proc WHERE db = 'your_database_name' AND NAME = 'your_procedure_name';


3、用户认证插件选择问题

新版本数据库中默认的用户认证插件为caching_sha2_password,相比早期的mysql_native_password插件而言,有更强的安全性、更好的插件支持、更大的灵活性。

如果使用新的插件,需要对实例中所有用户的认证信息进行统一修改。如果为了兼顾老版本配置,可以通过修改数据库服务端配置,将认证插件指定为mysql_native_password(未来有弃用风险)

[mysqld]
default_authentication_plugin = mysql_native_password


4、row_format格式问题

MySQL 5.7和8.0的默认行格式都是Dynamic,而5.7之前是COMPACT,Dynamic和COMPACT在对于数据出现行溢出问题时处理策略不同。如果有库表的行格式使用到了MySQL早期的Compact格式,在进行升级前必须对这部分表字段格式先行调整为Dynamic。

#查看存储引擎默认的行格式
select @@innodb_default_raw_format; 

#查看表的行格式
show table status like 'table_name' \G 

#建表时指定行格式的语法
create table t1(in int,name varchar(10)) row_format=compact;

#修改表的行格式
alter table t1 row_format=dynamic;



5、数据库发行版不一致的问题

如果是跨发行版升级,比如从 Percona 5.7升级到 MySQL 官方发行版8.0,需要先将 Percona 5.7转换为官方版然后再进行升级操作


6、canal升级测试

如果有依赖Canal组件,需要注意Canal1.14对于mysql8的支持不够好,比如隐藏索引导致报错、新的binlog格式无法识别等问题,所以还需要对Canal进行升级


7、表名大小写问题

MySQL配置项 lower_case_table_names用于设置表文件名大小写存储规则。该值默认为0,表示在进行物理存储和查询时都区分大小写。在升级过程中需要注意之前实例的配置,如果有配置为1的(表示在进行物理存储和查询时自动将大写转换为小写),那么在进行升级的时候就必须要指定为1,因为8.0开始该值不能进行修改,需要在实例进行初始化时就指定好,或者统一代码写法,大小写不混用


8、NOT NULL字段插入NULL值

非空字段如果有定义默认值(如DEFAULT CURRENT_TIMESTAMP) ,在传值的时候应该使用 DEFAULT 或者省略这个字段,不能继续采用NULL来获取默认值。虽然在8.0版本可以通过数据库服务端配置来强行允许这个行为,但是官方已经明确未来会废弃该功能,如果继续沿用会在未来的升级中带来更大量的排查工作所以需要开发人员对这部分代码进行优化,后续新增代码不再使用NULL获取默认值的方式

#字段属性
`create_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间'

#插入语句
insert into t1(create_time) VALUES (NULL)


9、Unsupported conversion from DATETIME to java.lang.Long 

部分老旧系统的代码存在将 DATETIME 类型数据转换为 Long 类型的情况,由于新版本JDBC驱动中不支持这种自动转换,所以需要对这部分代码进行优化,显式地进行日期/时间到时间戳的转换



10、驱动兼容问题

数据库升级后JDBC版本也需要进行统一升级,这也是最容易遇到的问题

<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>


11、字符集默认排序规则问题

在MySQL8中,UTF8MB4使用的排序规则默认为utf8mb4_0900_ai_ci,而之前的版本中是utf8mb4_general_ci,为了兼容性可以通过配置文件指定为之前的排序规则

[mysqld]
character_set_server			= utf8mb4
collation_server            = utf8mb4_general_ci


评论