1.说明

首先明白升级的意义的是什么,最重要的两点应该就是Bug,还有就是新版本的重要新特性。当然对于大版本的升级,需要注意的地方还有很多,最重要的就是新版本对于一些特性的移除或不再支持了,那么对于应用来说必须进行代码的修改。
注:不支持从MySQL8.0降级到5.7或8之前的版本,所以只能通过还原之前的备份来达到回退的目的,那么升级前的备份是至关重要的。

2.升级前的应了解的东西

注:由于我只是在虚拟机上进行升级的实验,所以很多细节并没有充分考虑。如果是生产环境应该全面了解8.0相关的新特性,然后做好充分准备再进行升级,否则可能会造成众多问题。

2.1.做好备份

这是必须做的,至于备份方法多种多样,不在介绍。特别是8.0不支持直接回 退到之前版本。

2.2.升级线路

参考下一章节

2.3.MySQL8.0版本中的变化

  • 数据字典
    参考:

​https://www.cndba.cn/Expect-le/article/3141​

  • 密码验证插件
    默认创建的用户密码会使用新的密码验证插件caching_sha2_password,会导致8.0之前版本的客户端无法连接。
    具体参考:

​https://www.cndba.cn/Expect-le/article/3087s​

  • 参数配置变化
  • 服务配置变化
  • InnoDB变化
  • SQL变化
    还有更多的包括新特性,移除的特性,废弃的特性。
    更详细的内容,请查看官方文档:

​https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html​

3.升级线路

  • 从MySQL5.7可以直接升级到8.0,然而仅限与General Availability (GA) 版本之间,然后也只是5.7.9及以上版本支持。如果是非GA版本,那么不支持直接升级。
  • 跨版本升级是不支持的,如:从5.6升级到8.0。

4.升级前的准备工作

升级前要确认你现在的版本是5.7或8.0,否则会升级失败。

4.1.MySQL Shell检查是否满足升级条件

可以通过MySQL Shell升级检查工具来检查是否满足升级条件:
首先要安装MySQL Shell,安装非常简单,不一定是本地要有。
MySQL Shell的安装:

​https://www.cndba.cn/Expect-le/article/3157​

4.1.1.查看当前数据库版本

MySQL  127.0.0.1:3306  JS > /status
MySQL Shell version 8.0.13
Session type: Classic
Connection Id: 4
Current schema:
Current user: root@localhost
SSL: Not in use.
Using delimiter: ;
Server version: 5.7.17 MySQL Community Server (GPL)

4.1.2.检查

默认情况下,检查的是当前版本升级到8.0.13版本的兼容性,也可以手动指定目标版本。

   MySQL  127.0.0.1:3306  JS > util.checkForServerUpgrade()

  util.checkForServerUpgrade('root@127.0.0.1:3306', {"password":"root", "targetVersion":"8.0.11"})

检查结果:

The MySQL server at 127.0.0.1:3306 will now be checked for compatibility issues for upgrade to MySQL 8.0.13...
MySQL version: 5.7.17 - MySQL Community Server (GPL)

1) Usage of old temporal type
No issues found

2) Usage of db objects with names conflicting with reserved keywords in 8.0
No issues found

3) Usage of utf8mb3 charset
Warning: The following objects use the utf8mb3 character set. It is recommended to convert them to use utf8mb4 instead, for improved Unicode support.
More information: https://dev.mysql.com/doc/refman/8.0/en/charset-unicode-utf8mb3.html

test- schema's default character set: utf8
dbmonitor - schema's default character set: utf8
dbmonitor2 - schema's default character set: utf8
dbmonitor_bak - schema's default character set: utf8
mysql - schema's default character set: utf8
略。。。
4) Table names in the mysql schema conflicting with new tables in 8.0
No issues found

5) Foreign key constraint names longer than 64 characters
No issues found

6) Usage of obsolete MAXDB sql_mode flag
No issues found

7) Usage of obsolete sql_mode flags
No issues found

8) ENUM/SET column definitions containing elements longer than 255 characters
No issues found

9) Usage of partitioned tables in shared tablespaces
No issues found

10) Usage of removed functions
No issues found

11) Usage of removed GROUP BY ASC/DESC syntax
No issues found

12) Issues reported by 'check table x for upgrade' command
No issues found

Errors: 0 --重要关注
Warnings: 552
Notices: 0

No fatal errors were found that would prevent an upgrade, but some potential issues were detected. Please ensure that the reported issues are not significant before upgrading.

从上面来看,没有兼容性问题。

4.2.手动检查

除了使用shell检查之外,还可以手动检查,可能手动检查更放心。

4.2.1.下面问题必须不能出现

  • 表中一定不能含有废弃的数据类型或函数
  • 一定不能有.frm文件
  • 确保触发器触发器必须没有缺少或空的定义或无效的定义(通过SHOW TRIGGERS或INFORMATION_SCHEMA TRIGGERS表上来你查看触发器中的character_set_client,collation_connection,Database Collation的值)。
    以上问题可以通过mysqlcheck命令来检查,如下
    [root@storage1 local]# mysqlcheck -u root -p --all-databases --check-upgrade
    mysql.time_zone OK
    mysql.time_zone_leap_second OK
    mysql.time_zone_name OK
    mysql.time_zone_transition OK
    mysql.time_zone_transition_type OK
    mysql.user OK
    sys.sys_config OK
    如果有错误,必须修正。

4.2.2.分区表

确保没有使用不支持native分区的存储引擎的分区表,可通过以下命令查询:

SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE ENGINE NOT IN ('innodb', 'ndbcluster')
AND CREATE_OPTIONS LIKE '%partitioned%';

如果有返回结果,那么一定要将该分区表该为innodb存储引擎,或改为非分区表。
改表的存储引擎:

ALTER TABLE table_name ENGINE = INNODB;

将分区表改为非分区表:

ALTER TABLE table_name REMOVE PARTITIONING;

4.2.3.关键字

在MySQL 8.0版本中新增了一些关键字,而我们都知道关键字我们是无法使用的,如果在之前版本中使用了,那么就会报错。
具体哪些关键字,请查看官方文档:

​https://dev.mysql.com/doc/refman/8.0/en/keywords.html​

4.2.4.表名和数据字典名词

确保不要在MySQL 5.7版本的mysql系统数据库中有和8.0中数据字典相同名称的表。
可通过以下SQL查询:

SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE LOWER(TABLE_SCHEMA) = 'mysql'
and LOWER(TABLE_NAME) IN
(
'catalogs',
'character_sets',
'collations',
'column_statistics',
'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',
'resource_groups',
'routines',
'schemata',
'st_spatial_reference_systems',
'table_partition_values',
'table_partitions',
'table_stats',
'tables',
'tablespace_files',
'tablespaces',
'triggers',
'view_routine_usage',
'view_table_usage'
);

如果有这样的表,那么必须重命名。如:

LOCK TABLE old_table1 WRITE; --如果有数据写入,可以暂时锁该表。
Alter TABLE old_table1 RENAME new_table1

注:那么应用也要做相应的修改,否则会造成不必要的麻烦。

4.2.5.外键约束名称

确保没有表的外键约束名称超过64个字符的,可通过以下SQL查看:

SELECT TABLE_SCHEMA, TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME IN
(SELECT LEFT(SUBSTR(ID,INSTR(ID,'/')+1),
INSTR(SUBSTR(ID,INSTR(ID,'/')+1),'_ibfk_')-1)
FROM INFORMATION_SCHEMA.INNODB_SYS_FOREIGN
WHERE LENGTH(SUBSTR(ID,INSTR(ID,'/')+1))>64);

如果有,那么要修改。如:

ALTER TABLE tbl_name DROP FOREIGN KEY fk_symbol;

4.2.6.sql_mode

确保sql_mode系统变量中没有已废弃的SQL mode。如果有,那么数据库无法打开,而且应用程序也要注意这一点。
已废弃的SQL mode包括以下:

DB2, MAXDB, MSSQL, MYSQL323, MYSQL40, ORACLE, POSTGRESQL, NO_FIELD_OPTIONS, NO_KEY_OPTIONS, NO_TABLE_OPTIONS

4.2.7.ENUM或SET

确保没有表或存储过程中的ENUM或SET列的元素长度超过255个字符或1020个字节。在8.0版本之前长度允许到64k,而在8.0版本中最大长度是255个字符或1020个字节。

4.2.8.InnoDB表空间

在更新到8.0.13或更高之前,要确保没有表分区存储在InnoDB表空间中,包括系统表空间和一般表空间。可通过以下SQL查询:

SELECT DISTINCT NAME, SPACE, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES 
WHERE NAME LIKE '%#P#%' AND SPACE_TYPE NOT LIKE 'Single';

如果有,则将表从共享表空间移到自己的表空间中( innodb-file-per-table ),如:

ALTER TABLE table_name REORGANIZE PARTITION partition_name 
INTO (partition_definition TABLESPACE=innodb_file_per_table);

4.2.9.GROUP BY … ASC或DESC

在8.0.12或更低版本中,确保不要有GROUP BY … ASC或DESC这种SQL语句,因为在8.0.13及以上版本中已不支持这种写法,必须和ORDER BY … ASC或DESC一起使用。

4.2.10.废弃,已移除特性

确保当前环境没有使用在目标版本中已经不支持的特性,这个在Mysql8.0官方文档中进行了详细的介绍,
可以参考:
MySQL8.0中已移除的特性,功能:

​https://www.cndba.cn/Expect-le/article/3135​​​​https://dev.mysql.com/doc/refman/8.0/en/mysql-nutshell.html#mysql-nutshell-removals​

5.升级

我这里是采用的本机升级(IN-Place)方式,直接将原库关闭然后用新的数据库软件替代旧的软件,然后用新版本启动,执行mysql_upgrade。

5.1.XA事务

如果当前有XA事务,那么要执行XA_COMMIT或XA_ROLLBACK。

5.2.加密表空间

如果有加密的InnoDB表空间,那么要旋转主密钥:

ALTER INSTANCE ROTATE INNODB MASTER KEY;

5.3.快速关库

如果当前环境配置了冷关闭(innodb_fast_shutdown = 2),那么需要改为快速或慢关闭,如:

SET GLOBAL innodb_fast_shutdown = 1; --快关闭
SET GLOBAL innodb_fast_shutdown = 0; --慢关闭

通过快速或慢速关闭,InnoDB将其undo日志和数据文件保留在可以在发布版本之间存在文件格式差异的情况下处理的状态。

5.4.关闭数据库

关库命令没有要求,以下命令都可以

[root@storage1 ~]# mysqladmin -u root -p shutdown

service mysql stop

5.5.解压新版本的数据库压缩包

解压到/usr/local目录下

[root@ka-m software]# tar xvf mysql-8.0.13-linux-glibc2.12-x86_64.tar.xz -C /usr/local/

替换原来版本的目录

[root@ka-m local]#mv mysql mysql_old
[root@ka-m local]#mv mysql-8.0.13-linux-glibc2.12-x86_64 mysql

赋权限

[root@ka-m local]# chown -R mysql.mysql mysql/

5.6.启动新库

[root@ka-m bin]# mysqld_safe --user=mysql --datadir=/data   --原来数据文件存放目录
2018-11-16T03:00:29.864066Z mysqld_safe Logging to '/data/ka-m.err'.
2018-11-16T03:00:29.966328Z mysqld_safe Starting mysqld daemon with databases from /data
2018-11-16T03:00:32.091267Z mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended

注:如果有加密表空间,需要–early-plugin-load选项:–early-plugin-load=“​​myplug1=myplug1.so​​​;​​myplug2=myplug2.so​​”

5.7.执行升级程序

检查所有数据库中的所有表与新版本的兼容性,它会做必要的更改以保证兼容性。但是它不会升级help表中的信息。

[root@ka-m local]# mysql_upgrade -u root -p
Enter password:
Checking if update is needed.
Checking server version.
Running queries to upgrade MySQL server.
。。。
sys.sys_config OK
Upgrade process completed successfully. –表示升级成功
Checking if update is needed.

5.8.重启数据库即可

再次重启数据库就完成数据库的升级工作。

[root@ka-m local]#mysqladmin -u root -p shutdown
[root@ka-m local]#mysqld_safe --user=mysql --datadir=/data &

注:为了方便关闭,启动mysql,可以将mysql.server拷贝到/etc/init.d目录下,如:

cp support-files/mysql.server /etc/init.d/mysql

5.9.验证

[root@ka-m local]# mysql -uroot -proot
mysql> select version();
+-----------+
| version() |
+-----------+
| 8.0.13 |
+-----------+
1 row in set (0.00 sec)

至此升级就完成了,最好再次进行一次正库备份。