Skip to content

MySQL 升级步骤

概述

升级方式介绍

MySQL 升级主要有两种方式:

  • In-place 升级:直接在现有数据库实例上升级,替换 MySQL 二进制文件,然后运行 mysql_upgrade 工具更新系统表。这种方式升级速度快,但风险较高,因为升级失败后回滚比较复杂。
  • Logical 升级:通过逻辑备份工具(如 mysqldumpmydumper)导出旧版本数据库的数据,然后在新版本 MySQL 实例上导入数据。这种方式升级风险较低,回滚简单,但升级速度较慢,特别是对于大型数据库。

升级方式选择原则

因素In-place 升级Logical 升级
升级速度
风险程度
回滚难度复杂简单
数据一致性依赖于备份和回滚机制天然一致
适用场景小到中型数据库,次要版本升级大型数据库,跨大版本升级,对数据安全性要求高

升级前最后检查

在开始升级前,进行最后一次检查,确保所有准备工作都已完成:

  • [ ] 已完成数据库全量备份
  • [ ] 已完成配置文件备份
  • [ ] 已在测试环境完成升级演练
  • [ ] 已制定详细的升级计划和回滚方案
  • [ ] 已通知相关人员,包括业务部门、开发团队、运维团队等
  • [ ] 已准备好升级所需的工具和资源
  • [ ] 监控系统已就绪,能够实时监控升级过程

In-place 升级步骤

升级前准备

  1. 确认当前 MySQL 版本
bash
mysql -V
mysql Ver 8.0.28 for Linux on x86_64 (MySQL Community Server - GPL)
  1. 停止 MySQL 服务
bash
# 系统自带服务管理
systemctl stop mysql

# 或使用 mysqld_safe 停止
mysqladmin -u root -p shutdown
  1. 备份数据目录和配置文件
bash
# 备份数据目录
cp -r /var/lib/mysql /var/lib/mysql.bak.$(date +%Y%m%d_%H%M%S)

# 备份配置文件
cp /etc/my.cnf /etc/my.cnf.bak.$(date +%Y%m%d_%H%M%S)

替换 MySQL 二进制文件

根据操作系统和安装方式,选择合适的方法替换 MySQL 二进制文件。

使用 RPM/YUM 包管理器升级(CentOS/RHEL)

bash
# 查看当前安装的 MySQL 包
rpm -qa | grep mysql

# 卸载当前版本(保留数据)
yum remove mysql-community-server mysql-community-client mysql-community-common mysql-community-libs

# 安装目标版本的 MySQL 源
wget https://dev.mysql.com/get/mysql80-community-release-el8-3.noarch.rpm
yum localinstall mysql80-community-release-el8-3.noarch.rpm

# 启用目标版本的 MySQL 仓库
yum-config-manager --enable mysql80-community

# 安装目标版本的 MySQL
yum install mysql-community-server

使用 APT 包管理器升级(Debian/Ubuntu)

bash
# 查看当前安装的 MySQL 包
dpkg -l | grep mysql

# 卸载当前版本(保留数据)
apt-get remove --purge mysql-server mysql-client mysql-common

# 清理残留文件
apt-get autoremove
apt-get autoclean

# 添加目标版本的 MySQL 源
echo "deb https://repo.mysql.com/apt/debian/ buster mysql-8.0" >> /etc/apt/sources.list.d/mysql.list

# 更新包列表
apt-get update

# 安装目标版本的 MySQL
apt-get install mysql-server

手动编译安装升级

bash
# 下载目标版本的 MySQL 源码包
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.33.tar.gz

tar -zxvf mysql-8.0.33.tar.gz
cd mysql-8.0.33

# 编译安装
cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/var/lib/mysql -DSYSCONFDIR=/etc
make && make install

启动 MySQL 服务

bash
# 系统自带服务管理
systemctl start mysql

# 或使用 mysqld_safe 启动
mysqld_safe --defaults-file=/etc/my.cnf &

运行 mysql_upgrade 工具

mysql_upgrade 工具用于更新系统表,确保它们与新版本 MySQL 兼容。

bash
mysql_upgrade -u root -p

重启 MySQL 服务

bash
# 系统自带服务管理
systemctl restart mysql

# 或使用 mysqld_safe 重启
mysqladmin -u root -p shutdown
mysqld_safe --defaults-file=/etc/my.cnf &

Logical 升级步骤

升级前准备

  1. 安装目标版本的 MySQL

在新服务器或现有服务器的不同端口上安装目标版本的 MySQL。

  1. 配置新版本 MySQL

根据旧版本的配置文件,调整新版本的配置文件,确保参数兼容。

导出旧版本数据

使用逻辑备份工具导出旧版本数据库的数据。

使用 mysqldump 导出

bash
# 导出所有数据库,包括系统数据库
mysqldump -u root -p --all-databases --single-transaction --master-data=2 --flush-logs --routines --triggers --events > /backup/mysql_full_$(date +%Y%m%d_%H%M%S).sql

# 或导出指定数据库
mysqldump -u root -p --databases db1 db2 --single-transaction --master-data=2 --flush-logs --routines --triggers --events > /backup/mysql_db1_db2_$(date +%Y%m%d_%H%M%S).sql

使用 mydumper 导出(并行导出,速度更快)

bash
# 安装 mydumper
yum install mydumper

# 导出所有数据库
mydumper -u root -p -o /backup/mysql_dump_$(date +%Y%m%d_%H%M%S) --all-databases --routines --triggers --events

导入数据到新版本 MySQL

使用逻辑备份工具导入数据到新版本 MySQL 实例。

使用 mysql 命令导入 mysqldump 备份

bash
# 导入所有数据库
mysql -u root -p < /backup/mysql_full_$(date +%Y%m%d_%H%M%S).sql

# 或导入指定数据库
mysql -u root -p < /backup/mysql_db1_db2_$(date +%Y%m%d_%H%M%S).sql

使用 myloader 导入 mydumper 备份(并行导入,速度更快)

bash
# 导入所有数据库
myloader -u root -p -d /backup/mysql_dump_$(date +%Y%m%d_%H%M%S) --overwrite-tables

运行 mysql_upgrade 工具

bash
mysql_upgrade -u root -p

重启新版本 MySQL 服务

bash
systemctl restart mysql

切换应用连接到新版本 MySQL

更新应用配置,将数据库连接指向新版本 MySQL 实例,然后重启应用。

主从复制环境升级步骤

升级策略

主从复制环境升级主要有两种策略:

  • 滚动升级:先升级从库,再升级主库。这种方式可以最大程度减少业务 downtime。
  • 并行升级:同时升级所有实例,业务需要短暂停机。这种方式升级速度快,但业务影响较大。

滚动升级步骤

准备工作

  • 确保主从复制正常运行,没有延迟
  • 备份所有实例的数据和配置文件
  • 在测试环境完成升级演练

升级从库

  1. 停止从库的复制进程
sql
-- MySQL 5.6/5.7
STOP SLAVE;

-- MySQL 8.0
STOP REPLICA;
  1. 停止从库 MySQL 服务
bash
systemctl stop mysql
  1. 升级从库 MySQL 版本(参考 In-place 升级或 Logical 升级步骤)

  2. 启动从库 MySQL 服务

bash
systemctl start mysql
  1. 运行 mysql_upgrade 工具
bash
mysql_upgrade -u root -p
  1. 重启从库 MySQL 服务
bash
systemctl restart mysql
  1. 启动从库复制进程
sql
-- MySQL 5.6/5.7
START SLAVE;

-- MySQL 8.0
START REPLICA;
  1. 验证从库复制状态
sql
-- MySQL 5.6/5.7
SHOW SLAVE STATUS\G

-- MySQL 8.0
SHOW REPLICA STATUS\G

确保 Slave_IO_Running/Replica_IO_RunningSlave_SQL_Running/Replica_SQL_Running 都为 Yes,且 Seconds_Behind_Master/Seconds_Behind_Source 为 0。

  1. 对所有从库重复以上步骤

升级主库

  1. 将一个从库提升为主库(可选,用于快速回滚)
sql
-- 在从库上执行
-- MySQL 5.6/5.7
STOP SLAVE;
RESET MASTER;

-- MySQL 8.0
STOP REPLICA;
RESET MASTER;
  1. 停止主库的写入流量
  • 通知业务部门停止写入操作
  • 或使用 read_only 参数设置主库为只读模式
sql
SET GLOBAL read_only = ON;
  1. 等待所有从库追上主库

在每个从库上执行:

sql
-- MySQL 5.6/5.7
SHOW SLAVE STATUS\G

-- MySQL 8.0
SHOW REPLICA STATUS\G

确保 Seconds_Behind_Master/Seconds_Behind_Source 为 0。

  1. 停止主库 MySQL 服务
bash
systemctl stop mysql
  1. 升级主库 MySQL 版本(参考 In-place 升级或 Logical 升级步骤)

  2. 启动主库 MySQL 服务

bash
systemctl start mysql
  1. 运行 mysql_upgrade 工具
bash
mysql_upgrade -u root -p
  1. 重启主库 MySQL 服务
bash
systemctl restart mysql
  1. 恢复主库的写入流量
sql
SET GLOBAL read_only = OFF;
  1. 通知业务部门恢复写入操作

升级过程中的监控和问题处理

实时监控

在升级过程中,需要实时监控以下指标:

  • 系统资源:CPU、内存、磁盘 I/O、网络流量等
  • MySQL 状态:连接数、QPS、TPS、锁等待等
  • 复制状态:主从延迟、复制错误等
  • 日志信息:错误日志、慢查询日志等

常见问题和解决方案

MySQL 服务无法启动

问题现象

systemctl start mysql
Job for mysql.service failed because the control process exited with error code.

解决方案

  • 查看错误日志,定位具体问题
  • 检查配置文件是否有语法错误
  • 检查数据目录权限是否正确
  • 检查端口是否被占用

示例

bash
# 查看错误日志
tail -n 100 /var/log/mysql/error.log

# 检查配置文件语法
mysqld --defaults-file=/etc/my.cnf --validate-config

# 检查数据目录权限
ls -la /var/lib/mysql/

# 检查端口是否被占用
netstat -tlnp | grep 3306

mysql_upgrade 工具执行失败

问题现象

mysql_upgrade: [ERROR] 1051 (42S02): Unknown table 'mysql.column_stats'

解决方案

  • 检查 MySQL 服务是否正常运行
  • 检查用户权限是否足够
  • 尝试使用 --force 参数强制运行
  • 手动修复有问题的系统表

示例

bash
# 使用 --force 参数强制运行
mysql_upgrade -u root -p --force

# 手动修复系统表
mysql -u root -p -e "DROP TABLE IF EXISTS mysql.column_stats; CREATE TABLE mysql.column_stats (...)"

主从复制中断

问题现象

sql
SHOW SLAVE STATUS\G
...
Slave_IO_Running: Yes
Slave_SQL_Running: No
Last_Error: Error 'Table 'db1.table1' doesn't exist' on query. Default database: 'db1'. Query: 'INSERT INTO table1 VALUES (...)'
...

解决方案

  • 根据错误信息,修复相应的问题
  • 使用 SKIP SLAVE SQL ERRORS 跳过错误(仅在确认错误不影响数据一致性时使用)
  • 重新配置复制关系

示例

sql
-- MySQL 5.6/5.7
-- 跳过一个错误
SET GLOBAL sql_slave_skip_counter = 1;
START SLAVE;

-- MySQL 8.0
-- 跳过一个错误
SET GLOBAL sql_replica_skip_counter = 1;
START REPLICA;

-- 或跳过所有错误(不推荐)
-- MySQL 5.6/5.7
STOP SLAVE;
SET GLOBAL slave_exec_mode = 'IDEMPOTENT';
START SLAVE;

-- MySQL 8.0
STOP REPLICA;
SET GLOBAL replica_exec_mode = 'IDEMPOTENT';
START REPLICA;

升级后的初步验证

验证 MySQL 版本

bash
mysql -V
mysql Ver 8.0.33 for Linux on x86_64 (MySQL Community Server - GPL)

验证系统表

sql
SHOW DATABASES;
USE mysql;
SHOW TABLES;

验证数据完整性

  • 检查关键表的数据行数是否与升级前一致
  • 运行简单的查询语句,验证数据可以正常访问
  • 检查存储过程、触发器、视图等对象是否正常

示例

sql
-- 检查关键表的数据行数
SELECT COUNT(*) FROM db1.table1;
SELECT COUNT(*) FROM db1.table2;

-- 验证存储过程
CALL db1.sp_test();

-- 验证触发器
INSERT INTO db1.table1 VALUES (...);
SELECT * FROM db1.log_table WHERE id = LAST_INSERT_ID();

验证主从复制状态(如果有)

sql
-- MySQL 5.6/5.7
SHOW SLAVE STATUS\G

-- MySQL 8.0
SHOW REPLICA STATUS\G

确保 Slave_IO_Running/Replica_IO_RunningSlave_SQL_Running/Replica_SQL_Running 都为 Yes,且 Seconds_Behind_Master/Seconds_Behind_Source 为 0。

验证应用连接

  • 重启应用,确保应用可以正常连接到数据库
  • 执行简单的业务操作,验证端到端功能正常

版本差异考虑

MySQL 5.6 到 5.7 升级注意事项

  • 系统表结构变化:mysql 系统数据库表结构发生变化,需要使用 mysql_upgrade 更新
  • SQL_MODE 默认值变化:MySQL 5.7 默认 SQL_MODE 更加严格,包含 STRICT_TRANS_TABLESNO_ZERO_IN_DATENO_ZERO_DATE
  • 密码策略变化:引入了更严格的密码策略,默认启用 validate_password 插件
  • InnoDB 变化:InnoDB 成为默认存储引擎,MyISAM 逐渐被弃用
  • Performance Schema 增强:Performance Schema 收集更多性能数据,默认启用

MySQL 5.7 到 8.0 升级注意事项

  • 认证插件变化:默认认证插件从 mysql_native_password 变为 caching_sha2_password
  • 数据字典变化:引入了新的数据字典,替换了原有的.frm文件
  • 复制命令变化:复制相关命令发生变化,如 STOP SLAVE 变为 STOP REPLICA
  • 系统变量变化:大量系统变量被重命名或废弃
  • SQL 语法变化:某些 SQL 语法不再被支持,如 GROUP BY 隐式排序
  • 错误日志格式变化:错误日志格式发生变化,更加结构化

最佳实践

In-place 升级最佳实践

  • 选择合适的升级时间:在业务低峰期进行升级,减少业务影响
  • 充分备份:升级前进行完整备份,包括数据目录和配置文件
  • 测试升级:在测试环境进行升级演练,熟悉升级流程和步骤
  • 监控升级过程:实时监控系统资源和 MySQL 状态,及时发现问题
  • 准备回滚方案:制定详细的回滚方案,确保升级失败后可以快速回滚
  • 注意版本差异:特别是跨大版本升级时,注意版本之间的功能和配置差异

Logical 升级最佳实践

  • 使用并行备份和恢复工具:如 mydumpermyloader,提高备份和恢复速度
  • 分批次导出和导入:对于大型数据库,分批次导出和导入,减少内存占用
  • 优化导入参数:调整 innodb_buffer_pool_sizeinnodb_log_file_size 等参数,提高导入速度
  • 验证数据一致性:升级前后使用校验工具验证数据一致性
  • 考虑数据压缩:使用压缩工具减少备份文件大小,加快传输速度

主从复制环境升级最佳实践

  • 先升级从库,再升级主库:滚动升级可以最大程度减少业务 downtime
  • 确保主从复制正常:升级前确保主从复制没有延迟,升级后验证复制状态
  • 准备备用主库:在升级主库前,可以将一个从库提升为备用主库,以便快速回滚
  • 监控复制延迟:升级过程中实时监控复制延迟,确保从库能够跟上主库
  • 注意复制命令变化:MySQL 8.0 中复制命令发生了变化,需要使用新的命令

升级后优化

  • 更新统计信息:升级后更新表统计信息,确保查询优化器能够生成最优执行计划
  • 重新分析表:对关键表进行重新分析,更新索引统计信息
  • 检查慢查询日志:监控升级后的慢查询,及时优化
  • 调整配置参数:根据新版本的特性,调整配置参数以获得更好的性能
  • 更新数据库驱动:确保应用使用的数据库驱动与新版本 MySQL 兼容

常见问题和解决方案

升级后应用连接失败

问题现象

ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (111)

解决方案

  • 检查 MySQL 服务是否正常运行
  • 检查防火墙是否开放了 3306 端口
  • 检查用户权限是否允许远程连接
  • 检查密码是否正确
  • 对于 MySQL 8.0,检查认证插件是否兼容

示例

bash
# 检查 MySQL 服务状态
systemctl status mysql

# 检查防火墙规则
iptables -L -n | grep 3306

# 检查用户权限和认证插件
mysql -u root -p -e "SELECT User, Host, plugin FROM mysql.user WHERE User='app_user'"

升级后性能下降

问题现象

  • 查询响应时间变长
  • CPU 使用率升高
  • 内存占用增加

解决方案

  • 调整配置参数,特别是 innodb_buffer_pool_sizeinnodb_log_file_sizemax_connections
  • 优化查询语句,重新分析表和索引
  • 更新统计信息
  • 检查慢查询日志,定位性能瓶颈
  • 对于 MySQL 8.0,检查新的查询优化器行为

示例

sql
-- 重新分析表和索引
ANALYZE TABLE db1.table1, db1.table2;

-- 更新统计信息
mysqlcheck -u root -p --all-databases --analyze

-- 查看慢查询日志
mysqldumpslow -s t -t 10 /var/log/mysql/mysql-slow.log

升级后某些功能不可用

问题现象

ERROR 1149 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '...' at line 1

解决方案

  • 检查 SQL 语法是否符合新版本要求
  • 检查是否使用了已废弃的功能或参数
  • 查阅官方文档,了解版本之间的功能变更
  • 修改应用代码,适配新版本 MySQL
  • 对于 MySQL 8.0,检查是否使用了已移除的系统变量

示例

bash
# 检查废弃功能
mysql -u root -p -e "SHOW WARNINGS;"

总结

MySQL 升级是一项复杂的系统工程,需要充分的准备和精心的实施。选择合适的升级方式,严格按照升级步骤操作,实时监控升级过程,准备好回滚方案,这些都是确保升级成功的关键。

无论采用哪种升级方式,都应该在测试环境完成升级演练,熟悉升级流程和步骤,识别潜在风险,制定相应的应对措施。同时,要特别注意不同版本之间的差异,特别是跨大版本升级时,这些差异可能会导致升级失败或升级后出现问题。

只有这样,才能确保生产环境升级的成功,最大限度减少对业务的影响。