这里以 MySQL 5.7.33 版本升级到 8.0.23 版本为例,版本类型选择二进制版本,操作系统使用 Linux。
必知事项
建议
- 升级之前必须进行备份,且备份应包含 mysql 库
- 升级后需要重新安装 MySQL 语言接口
升级路径
- 从 5.6 升级到 5.7,建议先升级到最新版本,然后再升级到下一版本
- 不支持跳版本升级,例如,从 5.5 升级到 5.7
- 支持在发行系列中进行升级和跳版本升级,例如,从 5.7.x 升级到 5.7.y,从 5.7.x 升级到 5.7.z
了解目标版本的变化
MySQL 8.0 版本相对于 5.7 版本的变化还是很大的,建议仔细查看官方文档。
升级前的准备
官方文档中列出了详细的检查事项,同时提供了一个官方的升级检查器。
检查事项
具体请查看 官方文档:https://dev.mysql.com/doc/refman/8.0/en/upgrade-prerequisites.html 。
升级检查器
MySQL Shell 用来检查服务器实例的兼容性错误和升级问题。最低只支持检查 5.7 版本实例,且必须是 GA 发行版。
也可以检查配置文件中已定义,但在目标版本中已删除的系统变量,以及未在配置文件中定义,但是在目标版本中有默认值的系统变量。
如果要检查配置文件, 需要提供配置文件路径。
- 安装
- 下载
下载地址:https://dev.mysql.com/downloads/shell/
wget https://dev.mysql.com/get/Downloads/MySQL-Shell/mysql-shell-8.0.23-linux-glibc2.12-x86-64bit.tar.gz
- 解压
tar -xvf mysql-shell-8.0.23-linux-glibc2.12-x86-64bit.tar.gz -C /opt/
- 创建软链接
ln -s /opt/mysql-shell-8.0.23-linux-glibc2.12-x86-64bit /opt/mysqlsh
- 添加环境变量
[root@yingzai ~]# vim /etc/profile ... MYSQLSH_HOME=/opt/mysqlsh export PATH=PATH:MYSQLSH_HOME/bin ... [root@yingzai ~]# source /etc/profile
- 验证
[root@yingzai ~]# mysqlsh MySQL Shell 8.0.23 ... Type '\help' or '\?' for help; '\quit' to exit. MySQL JS >
- 下载
- 语法
util.checkForServerUpgrade([connectionData][, options])
- 参数
这两个参数都是可选的。
- ConnectionData
- 提供连接数据
- options
- 选项字典,用来指定选项
- ConnectionData
- 选项
这里的选项不全,完整的选项列表请查看官方文档。
- password
- 密码
- targetVersion
- 计划升级到的目标版本,最好指定完整版本号
- configPath
- 配置文件路径
- outputFormat
- 输出格式,包括 TEXT (默认) 、JSON (易于解析和处理)
- password
- 查看
- 帮助
mysqlsh> util.help("checkForServerUpgrade")
- 当前实例状态
MySQL JS > \status MySQL Shell version 8.0.23 Not Connected.
- 帮助
- 参数
- 使用
MySQL Shell 支持两种查询方式,既可以登录到 mysqlsh 内部调用函数 util.checkForServerUpgrade(),也可以直接在命令行启动。
- 登录后调用函数
MySQL JS > util.checkForServerUpgrade('172.16.0.30:3306', {"password":"root", "targetVersion":"8.0.23", "outputFormat":"JSON", "configPath":"/mdata/3306/my.cnf"}) { "serverAddress": "172.16.0.30:3306", "serverVersion": "5.7.32-log - MySQL Community Server (GPL)", "targetVersion": "8.0.23", "errorCount": 0, "warningCount": 24, "noticeCount": 1, "summary": "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." ...
- 命令行启动
支持 TCP/IP 和 socket 两种连接方式。
- TCP/IP 方式
mysqlsh -- util checkForServerUpgrade root@'172.16.0.30':3306 --target-version=8.0.23 --output-format=JSON --config-path=/mdata/3306/my.cnf mysqlsh -- util check-for-server-upgrade { --user=root --host='172.16.0.30' --port=3306 } --target-version=8.0.23 --output-format=JSON --config-path=/mdata/3306/my.cnf
- socket 方式
mysqlsh --socket=/mdata/3306/mysql.sock --user=root -e "util.checkForServerUpgrade()"
- TCP/IP 方式
- 登录后调用函数
升级方式
原地升级
- 检查未提交的 XA 事务
mysql> XA recover;
Note: 如果返回结果,结束事务。
XA COMMIT xid [ONE PHASE] XA ROLLBACK xid
- 如果存在加密的 InnoDB 表空间
mysql> ALTER INSTANCE ROTATE INNODB MASTER KEY;
- 缓慢关闭服务
缓慢关闭时,InnoDB 会在关闭前执行完全清除和更改缓冲区合并,为版本中的文件格式差异做准备。
-- 5.7 版本 mysql> SET GLOBAL innodb_fast_shutdown = 0; -- 8.0 版本,快速/缓慢关闭都可以 mysql> SET GLOBAL innodb_fast_shutdown = 1; -- fast shutdown or mysql> SET GLOBAL innodb_fast_shutdown = 0; -- slow shutdown
Note: 5.7 版本升级到 8.0 版本,建议缓慢关闭。
- innodb_fast_shutdown={0|1|2}
- 0:缓慢关闭
- 1:快速关闭
- 2:冷关闭
- innodb_fast_shutdown={0|1|2}
- 关闭服务
shell> mysqladmin -uroot -p -S /mdata/3306/mysql.sock shutdown
- 升级软件版本
将新的安装包解压到安装目录,创建软链接,修改环境变量。
-
使用原有数据目录启动服务
shell> mysqld_safe --user=mysql --datadir=/mdata/3306/data &
Note: 8.0 版本,如果有加密的 InnoDB 表空间,需要使用 –early-plugin-load 选项加载 keyring 插件。启动过程中会自动升级数据字典等信息。
-
运行 mysql_upgrademysql_upgrade 检查所有表与当前版本的兼容性,并升级 mysql 库。但是,不会升级时区表和帮助表。
shell> mysql_upgrade -uroot -p
Note: 从 8.0.16 版本开始,这一步已经废弃了,原先这一步所做的操作在上一步已经自动完成。
-
重启服务
shell> mysqladmin -uroot -p -S /tmp/mysql.sock shutdown shell> mysqld_safe --defaults-file=/mdata/3306/my.cnf &
Note: 因为上一步启动时未指定 socket 文件,所以使用了默认的 /tmp/mysql.sock 。如果后续重启失败,很可能是因为配置文件中使用了已废弃的变量,需要排查错误日志。
-
登录验证
shell> mysql -uroot -p -S /mdata/3306/mysql.sock
Note: 实际生产中,验证的过程比较复杂,需要对库表、数据以及应用程序做多方面的验证。
逻辑升级
逻辑升级是指利用备份工具 mysqldump 或 mysqlpump 导出备份,然后恢复到新服务器的方法,类似数据迁移。
- 备份
shell> mysqldump -u root -p -S /mdata/3306/mysql.sock --add-drop-table -R --events -A \ --ignore-table=mysql.innodb_index_stats \ --ignore-table=mysql.innodb_table_stats --force > /tmp/full.sql
Note: 如果备份文件包含系统表,则不建议在服务器上启用 GTID。
-
关闭服务
shell> mysqladmin -uroot -p -S /mdata/3306/mysql.sock shutdown
- 部署新的实例
- 安装新的版本
略。
-
初始化新的数据目录
shell> mysqld --initialize --user=mysql --basedir=/opt/mysql --datadir=/mdata/3306/data
- 启动服务
shell> mysqld_safe --user=mysql --datadir=/path/to/5.7-datadir &
- 重置密码
mysql> ALTER USER USER() IDENTIFIED BY 'your new password';
- 安装新的版本
- 恢复数据
“`shell
shell> mysql -u root -p -S /tmp/mysql.sock –force mysql_upgrade -uroot -p -S /tmp/mysql.sock
shell> mysqladmin -u root -p -S /tmp/mysql.sock shutdown
shell> mysqld_safe –user=mysql –datadir=/mdata/data &
“`- 8.0.16 版本之后
shell> mysqladmin -u root -p -S /tmp/mysql.sock shutdown shell> mysqld_safe --user=mysql --datadir=/mdata/data --upgrade=FORCE &
Note: 从 8.0.16 版本开始,mysql_upgrade 已经废弃。改为 mysqld 程序搭配
--upgrade
选项,用来处理升级过程。
- 8.0.16 版本之后
-
登录验证
shell> mysql -uroot -p -S /tmp/mysql.sock
Note: 实际生产中,验证的过程比较复杂,需要对库表、数据以及应用程序做多方面的验证。
-
删除多余表
mysql> DROP TABLE mysql.event; mysql> DROP TABLE mysql.proc;
Note: MySQL 8.0 版本加载 5.7 版本的 dump 备份文件时,会重新创建两个不再使用的表:event 和 proc,升级完毕后需要删除。
错误汇总
权限错误和主键冲突
-
错误场景
- MySQL 5.7 版本升级到 8.0 版本,使用逻辑升级,在恢复时,报权限错误和主键冲突
- 报错信息
[root@yingzai tmp]$ mysql -u root -proot -S /tmp/mysql.sock --force < /tmp/full_gtid.sql mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 3554 (HY000) at line 318: Access to system table 'mysql.innodb_index_stats' is rejected. ERROR 3554 (HY000) at line 321: Access to system table 'mysql.innodb_index_stats' is rejected. ERROR 3554 (HY000) at line 338: Access to system table 'mysql.innodb_index_stats' is rejected. ERROR 1062 (23000) at line 340: Duplicate entry 'mysql-gtid_executed-PRIMARY-n_diff_pfx01' for key 'innodb_index_stats.PRIMARY' ERROR 3554 (HY000) at line 348: Access to system table 'mysql.innodb_table_stats' is rejected. ERROR 3554 (HY000) at line 351: Access to system table 'mysql.innodb_table_stats' is rejected. ERROR 3554 (HY000) at line 366: Access to system table 'mysql.innodb_table_stats' is rejected. ERROR 1062 (23000) at line 368: Duplicate entry 'mysql-gtid_executed' for key 'innodb_table_stats.PRIMARY'
- 报错原因
- 具体的原因网上也没有一个准确的说法,只能归结于 8.0 版本系统表和 5.7 版本系统的差异性。因为 8.0 之前的版本,mysql 系统表使用 MyISAM 存储引擎。
- 解决方法
- 可以在备份时,使用
--ignore-tables
选项,跳过这两个报错的表
- 可以在备份时,使用
这里有一处显示格式的错误,不是 Markdown 语法的问题,而是 WordPress 的插件导致的,这个插件对 Markdown 语法的识别有误,导致部分格式没有正确显示。