技术分享 | MySQL MGR 滚动升级可行么?

2023-12-01 12:34:36 浏览数 (1)

作者:雷文霆,爱可生华东交付服务部 DBA 成员,主要负责 MySQL 故障处理及相关技术支持。爱好看书,电影。座右铭,每一个不曾起舞的日子,都是对生命的辜负。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文约 2000 字,预计阅读需要 7 分钟。

1为什么要升级?

因为 MySQL 8.0.24 之前有很多 Bug,详见 MySQL 8.0 Release Notes[1],本文定稿时最近版本是 2023 年 7 月18 号发布的 8.0.34。

2升级前 DBA 和业务侧需要做什么?

如果是 MySQL 8.0.x 到 MySQL 8.0.z 的小版本升级,可以直接升级。参数名称的变化和弃用情况,可以在 MySQL 服务启动后,错误日志中看到,更新到配置文件中即可。

如果你没有做过升级或是需要从 MySQL 5.7 到 MySQL 8.0 大版本升级,需要根据官方升级文档[2] 进行检查。

至少要有的初步检查:

  • 必须备份数据,只支持 GA。
  • mysqlcheck -u root -p --all-databases --check-upgrade
  • util.checkForServerUpgrade()

3升级思路

前提条件:升级到 MySQL 8.0 的检查项都已经检查完毕。

根据官方的升级文档,升级分为如下 2 个步骤:

  • Step 1: Data dictionary upgrade.
  • Step 2: Server upgrade.

在 MySQL 8.0.16 之前:升级用 mysql_upgrade;从 MySQL 8.0.16 开始:mysqld 可以自动升级。

  1. 依次升级 MGR 的 Secondary 节点
  2. 切换到新 Primary 节点
  3. 最后升级旧 Primary 节点

所以理论上如果有 MySQL Router(它在应用程序和 MGR 集群之间,起到代理作用,自动发现后端可写主库),那么不影响业务。但是,实践出真知,升级要通知业务侧,因为常会重启应用程序服务用于验证升级或是验证程序代码。所以申请一个变更窗口是最优解

4具体的升级步骤是什么?

环境信息:MySQL 8.0.27 升级到 MySQL 8.0.33 从库升级时,建议设置 skip_slave_start=1skip_replica_start=1

4.1 升级前的检查

代码语言:javascript复制
# 以下三种方式均可
mysqlsh root@localhost:3306 -e "util.checkForServerUpgrade();"

MySQL  JS > util.checkForServerUpgrade("admin@127.0.0.1:3306")

util.checkForServerUpgrade("admin@127.0.0.1:3306", {"targetVersion":"8.0.33","outputFormat":"JSON","configPath":"/data/mysql/3306/my.cnf.3306"})[指定版本检查]

# 辅助检查
mysqlcheck -uadmin -p -h127.0.0.1 --all-databases --check-upgrade 

4.2 备份数据和配置文件

逻辑或是物理备份。

代码语言:javascript复制
cp -rp /data/mysql/data/3306   /data/mysql/data/3306_bak「备份数据目录为可选」
cp my.cnf bak_8.0.xx_my.cnf

4.3 关闭服务和准备 basedir

查看表的状态是否正常(关库之前)

代码语言:javascript复制
select * from information_schema.tables where TABLE_COMMENT like "%repair%"; 

安全关闭服务。

代码语言:javascript复制
set global innodb_fast_shutdown = 0; 

# 数据刷到磁盘,关闭快速关机;
shutdown;

# 关闭服务之后检查
ps -ef | grep mysql

如果是从库(无主从延迟)。

代码语言:javascript复制
show slave statusG 
stop slave;

备份数据文件(如果磁盘充足)。

代码语言:javascript复制
cp -rp /data/mysql/data/3366 /data/mysql/data/3366_bak_1013

准备 basedir,软连接或是直接替换。

代码语言:javascript复制
show variables like "�sedir%"; 或 which mysql

# 备份原 base 目录 
mv mysql_Basedir mysql_Basedir_bak 
chown -R mysql:mysql mysql-8.0.33-linux-glibc2.12-x86_64

# ln -s /目录/新软件包 软连接的目录
ln -s mysql-8.0.xx新版本-linux-glibc2.12-x86_64 mysql_Basedir 
chown -R mysql:mysql mysql_Basedir

# 示例
ln -s mysql-8.0.33-linux-glibc2.12-x86_64 base
lrwxrwxrwx 1 mysql mysql        35 Sep  7 16:14 base -> mysql-8.0.33-linux-glibc2.12-x86_64

# 环境变量可选
export PATH=$PATH:/usr/local/mysql/bin

# 或是 mv 替换,修改旧软件目录名称 
mv mysql mysql_8.0.xx
mv mysql-8.0.xx-linux-glibc2.12-x86_64 mysql

4.4 启动数据库

启动就是升级,数据字典升级和 server 升级。

记录 MySQL 服务的原启动方式。

查看和检查。

代码语言:javascript复制
var cluster = dba.getCluster()
cluster.status()

SELECT * FROM performance_schema.replication_group_members;

启动。

代码语言:javascript复制
# 两种启动方式
systemctl start

mysqld_safe --defaults-file=/*.cnf --user=mysql &

4.5 最后升级旧 Primary 节点之前, 先切主

同版本时,切主命令(我们这次不能使用,因为不同版本不能切换)

代码语言:javascript复制
# shell 使用8.0 
# 不支持5.7.31
cluster.setPrimaryInstance('clusteruser@10.186.65.181:6681') 
# 简版
cluster.setPrimaryInstance('mgr01:3306')

# 手动指定主库 >8.0.13 推荐
SELECT group_replication_set_as_primary('select @@server_uuid');

不能切主,怎么办?停止旧主组复制,使其自动切换。

代码语言:javascript复制
# 低版本不能 SELECT 切换到高版本,通过退出组复制,自动切换。
stop group_replication; 
# 启动前配置文件添加防止应用更新
read_only=1;super_read_only=1; 

4.7 升级组的通信协议 >MySQL 8.0.16

group_replication_get_communication_protocol 函数返回组支持的最低 MySQL 版本(也就是说这个版本以下的 MySQL 版本无法加入集群)。

代码语言:javascript复制
SELECT group_replication_get_communication_protocol();
SELECT group_replication_set_communication_protocol("8.0.33");

-- 提示虽然我们 set 成功了,但是依然显示如下低版本号,因为它查到是最低支持的版本。官方建议升级之后升级对应通信协议,所以我们别忘记要set一下哈。

SELECT group_replication_get_communication_protocol();
 ------------------------------------------------ 
| group_replication_get_communication_protocol() |
 ------------------------------------------------ 
| 8.0.27                                         |
 ------------------------------------------------ 

4.8 验证

已升级成功,大吉大利。

代码语言:javascript复制
select version();
 ----------- 
| version() |
 ----------- 
| 8.0.33    |
 ----------- 

从库,需要启动复制。

代码语言:javascript复制
stop group_replication;

5关于回退

如果启动失败,重新以原来的软件版本启动。

  • 清理 redo log 文件 rm -f ib_logfile{0,1,2,3}
  • 清理 link,启动旧版本

参考步骤:

代码语言:javascript复制
unlink mysql
mv mysql_Basedir mysql_Basedir_bak
ln -s mysql-8.0.xx旧版本-linux-glibc2.12-x86_64 mysql_Basedir
# 启动服务

6关于节点切换

变相自定义切换 (虽说节点切换是自动的)。

  • 节点权重 group_replication_member_weight 值越大越优先
  • server_uuid 越小越容易被选为主

7关于升级中遇到的问题

启动数据库时,查看 error 日志,替换或是去除 Warning

代码语言:javascript复制
2023-09-04T08:54:54.092942-00:00 0 [Warning] [MY-011068] [Server] The syntax '--admin-ssl=off' is deprecated and will be removed in a future release. Please use --admin-tls-version='' instead.
2023-09-04T08:54:54.092975-00:00 0 [Warning] [MY-011068] [Server] The syntax 'skip_slave_start' is deprecated and will be removed in a future release. Please use skip_replica_start instead.

正确的升级提示信息。

代码语言:javascript复制
2023-09-04T08:55:10.136353-00:00 7 [System] [MY-013381] [Server] Server upgrade from '80027' to '80033' started.
2023-09-04T08:55:12.621536-00:00 7 [System] [MY-013381] [Server] Server upgrade from '80027' to '80033' completed.

低版本不能切换到高版本。

代码语言:javascript复制
023-09-07T07:41:09.211541-00:00 59 [ERROR] [MY-013223] [Repl] The function 'group_replication_set_as_primary' failed. Error processing configuration start message: The appointed primary member has a version that is greater than the one of some of the members in the group.
2023-09-07T07:50:34.708283-00:00 0 [ERROR] [MY-013212] [Repl] Plugin group_replication reported: 'Error while executing a group configuration operation: Error processing configuration start message: The appointed primary member has a version that is greater than the one of some of the members in the group.'

# 低版本离开集群之后无法重新加回来stop group_replication;start group_replication; 好在集群会自动切换。
2023-09-07T07:51:47.747695-00:00 0 [ERROR] [MY-011521] [Repl] Plugin group_replication reported: 'Member version is incompatible with the group.'

原因:当新成员加入复制组时,它会检查组的现有成员宣布的通信协议版本。如果加入成员支持该版本,则它将加入组并使用组已宣布的通信协议,即使该成员支持其他通信功能也是如此。如果加入成员不支持通信协议版本,则会将其从组中逐出。

一个 MySQL 服务器 5.7.24 实例无法成功加入使用通信协议版本 8.0.16 的组。(高版本可以加入低版本)

一种不推荐的方式:如果需要更改组的通信协议版本,以便早期版本中的成员可以加入,请使用该 group_replication_set_communication_protocol("5.7.25") 函数指定要允许的最旧成员的 MySQL Server 版本。

8总结

  • 此方法属于 in-place upgrade,核心步骤是用新软件包替换旧软件包(basedir),适合小版本升级。
  • 其他的升级方式还有逻辑备份(MysqlDump 和 MyDumper)之后导入新版本。
  • 如果是大版本升级数据量又大,可以建立 Master 低版本到 Slave 高版本的复制,最后主从切换实现升级。

充分测试之后,请选择自己擅长的方式吧!

参考资料

[1]

MySQL 8.0 Release Notes: https://dev.mysql.com/doc/relnotes/mysql/8.0/en/

[2]

upgrade-prerequisites: https://dev.mysql.com/doc/refman/8.0/en/upgrade-prerequisites.html

本文关键字:#MySQL# #MGR# #升级#

0 人点赞