MySQL 升级

5.7.33 升级到 8.0.23。

一、必知事项

1. 建议

  • 升级前必须备份数据,且备份需包含 mysql 库
  • 升级后需重新安装 MySQL 语言接口

2. 升级路径

  • 从 5.6 升级到 5.7,建议先升级到 5.6 最新版本,再升级到 5.7
  • 不支持跨系列跳版本升级(如 5.5 直接升级到 5.7)
  • 支持同系列内升级或跳版本升级(如 5.7.x 到 5.7.y、5.7.x 到 5.7.z)

3. 了解目标版本变化

MySQL 8.0 与 5.7 差异较大,建议查阅官方文档了解详细变化。

二、升级前的准备

1. 检查事项

参考官方文档:https://dev.mysql.com/doc/refman/8.0/en/upgrade-prerequisites.html

2. 升级检查器(MySQL Shell)

MySQL Shell 可检查服务器实例的兼容性错误和升级问题,最低支持检查 5.7 GA 版本,还可检查配置文件中目标版本已删除或默认值变化的系统变量。

(1)安装

  • 下载:

    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
    
  • 添加环境变量:在 /etc/profile 中添加

    MYSQLSH_HOME=/opt/mysqlsh
    export PATH=$PATH:$MYSQLSH_HOME/bin
    

    使配置生效:

    source /etc/profile
    
  • 验证:

    $ mysqlsh
    MySQL Shell 8.0.23
    ...
    Type '\help' or '\?' for help; '\quit' to exit.
     MySQL  JS 
    

(2)语法

util.checkForServerUpgrade([connectionData][, options])
  • 可选参数:
    • ConnectionData:提供连接数据
    • options:选项字典,部分选项如下
      • password:密码
      • targetVersion:目标版本(建议指定完整版本号)
      • configPath:配置文件路径
      • outputFormat:输出格式(TEXT 默认,JSON 便于解析)

(3)查看帮助与状态

  • 帮助:

    mysqlsh> util.help("checkForServerUpgrade")
    
  • 当前实例状态:

    MySQL JS> \status
    MySQL Shell version 8.0.23
    
    Not Connected.
    

(4)使用方法

支持登录 MySQL Shell 内部调用函数或直接命令行启动。

  • 登录后调用:

    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 方式:

      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()"
      

三、升级方式

1. 原地升级

(1)结束未提交的 XA 事务

  • 检查未提交的 XA 事务:

    -- 若有返回结果,需结束事务
    XA recover;
    
  • 结束事务:

    XA COMMIT xid [ONE PHASE]
    XA ROLLBACK xid
    

(2)轮换 InnoDB 主密钥(若存在加密表空间)

ALTER INSTANCE ROTATE INNODB MASTER KEY;

(3)设置缓慢关闭

建议 5.7 升级到 8.0 时使用。

-- innodb_fast_shutdown 取值 0(缓慢关闭)、1(快速关闭)、2(冷关闭)
-- 5.7 版本设置缓慢关闭
SET GLOBAL innodb_fast_shutdown = 0;

-- 8.0 版本可选择快速或缓慢关闭(此处为说明,升级前无需操作 8.0)
SET GLOBAL innodb_fast_shutdown = 1; -- 快速关闭
-- 或
SET GLOBAL innodb_fast_shutdown = 0; -- 缓慢关闭

(4)关闭 MySQL 服务器

mysqladmin -uroot -p -S /mdata/3306/mysql.sock shutdown

(5)升级软件版本

将新安装包解压到安装目录,创建软链接,修改环境变量。

(6)启动新 MySQL 服务器

# 使用原有数据目录
mysqld_safe --user=mysql --datadir=/mdata/3306/data &

Note:8.0 版本若有加密的 InnoDB 表空间,需用 --early-plugin-load 选项加载 keyring 插件;启动时会自动升级数据字典等信息,不会升级时区表内容。

(7)登录验证

mysql -uroot -p -S /mdata/3306/mysql.sock

Note:生产环境需对库表、数据及应用程序做全面验证。

2. 逻辑升级

类似数据迁移,使用备份工具导出再恢复。

(1)备份数据

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。

(2)关闭原 MySQL 服务器

mysqladmin -uroot -p -S /mdata/3306/mysql.sock shutdown

(3)部署新实例

(步骤略,需安装配置 MySQL 8.0.23)

(4)恢复数据到新实例

mysql -u root -p -S /tmp/mysql.sock --force < /tmp/full.sql

(5)执行剩余升级操作

# 8.0.16 版本之前
mysql_upgrade -uroot -p -S /tmp/mysql.sock
mysqladmin -u root -p -S /tmp/mysql.sock shutdown
mysqld_safe --user=mysql --datadir=/mdata/data &
# 8.0.16 版本之后(mysql_upgrade 已废弃)
mysqladmin -u root -p -S /tmp/mysql.sock shutdown
mysqld_safe --user=mysql --datadir=/mdata/data --upgrade=FORCE &

(6)删除多余表(MySQL 8.0 不再使用)

DROP TABLE mysql.event;
DROP TABLE mysql.proc;

(7)登录验证

生产环境需对库表、数据及应用程序做全面验证。

mysql -uroot -p -S /tmp/mysql.sock

四、错误汇总

1. 逻辑升级恢复时的权限与主键冲突错误

  • 报错信息
$ 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 前系统表使用 MyISAM 引擎)。

  • 解决方法

备份时使用 --ignore-table 选项跳过报错表:--ignore-table=mysql.innodb_index_stats --ignore-table=mysql.innodb_table_stats

  • 扩展说明

    • innodb_index_stats:保存优化器的索引统计信息

    • innodb_table_stats:保存优化器的表统计信息

    • 复制时,这两张表仅复制结构,不复制内容