离线升级
GreatDB Cluster支持版本升级。5.0.7以前的版本没有项目在使用,本文档仅限5.0.7及之后的版本。
GreatDB Cluster版本号有为四段,如5.0.7.3。前三位是release版本号,包含在安装包名称中。其中最后一位是数据字典版本号,可登陆到实例后查看。
GreatDB Cluster的升级可能涉及到数据字典表的变化,若最后一位小版本发生变化,则不支持回退。
以下用于升级操作演示的集群拓扑关系为:
| 实例:端口号 | 实例名称 | 归属shard | node名 |
|---|---|---|---|
| 127.0.0.1:3336 | sqlnode1 | ||
| 127.0.0.1:3337 | sqlnode2 | ||
| 127.0.0.1:3338 | datanode1 | sd1 | n1 |
| 127.0.0.1:3339 | datanode2 | sd1 | n2 |
准备工作
确认集群当前版本
连接集群的sqlnode,执行语句select @@greatdb_version(或@@gdb_sqld_version)。打印信息如下
mysql> select @@greatdb_version; +-------------------+ | @@greatdb_version | +-------------------+ | 5.0.7.3 | +-------------------+ 1 row in set (0.00 sec)连接集群的datanode,执行语句select @@gdb_sqld_version。打印信息如下
mysql> select @@gdb_sqld_version; +--------------------+ | @@gdb_sqld_version | +--------------------+ | 5.0.7.3 | +--------------------+ 1 row in set (0.00 sec)备份当前版本二进制包
用于升级回退或失败回退(仅限最后一位小版本未发生变化)。
准备目标版本的二进制包
升级步骤
此升级步骤不包含由非DTM版本(5.0.x)升级到DTM版本(5.1.x)的操作。如果是要从非DTM版本升级到DTM版本,需要将本升级步骤结合《DTM升级》中的步骤进行升级。
停应用
停止连接集群的所有应用,防止升级过程中向集群查询或写入数据。
在各个SQLNode上执行show processlist,确认除系统session外无应用侧连接的会话。
检查集群状态
(1)、查询information_schema.greatdb_sqlnodes和information_schema.greatdb_datanodes,确认各节点处于正常在线状态,无异常节点。
(2)、当前集群SQLNode是否还有未完成的用户task, 例如:migrate/alter/backup,保证用户task都完成。通过
mysql.greatdb_sqlnode_tasks查询:GreatDB Cluster[test]> select task_type, task_status, info, task_owner from mysql.greatdb_sqlnode_tasks;(3)、检查集群中所有SQLNode的gtid是否一致,要保证
Executed_Gtid_Set都一致。通过以下命令查看gtid:GreatDB Cluster[test]> show master status;(4)、检查每个shard中的所有Datanode的gtid是否一致,要保证都一致。
检查表是否有instant column
从8025以及之前的版本(5.1.9及以前)升级到8032版本(6.0.0及以后)时,在升级之前需要检查表中是否含有instant column,如果含有instant column需要进行消除。
提供两种办法进行检测和修复,一种是手工,一种是程序。
手工检查和修复过程为连接到其中一个SQLnode和所有shard的active datanode节点,通过
information_schema.innodb_tables查询表中是否含有instant column,如下:mysql> SELECT table_id, name, instant_cols FROM information_schema.innodb_tables WHERE instant_cols > 0; +----------+-------------+--------------+ | table_id | name | instant_cols | +----------+-------------+--------------+ | 1061 | dbtest/tvar | 8 | +----------+-------------+--------------+
instant_cols不为0,则表示该表中含有instant column。
在升级之前须通过optimize table table_name方式消除 instant column,直到instant_cols不存在,如下:
mysql> optimize table tvar;
+-------------+----------+----------+-------------------------------------------------------------------+
| Table | Op | Msg_type | Msg_text |
+-------------+----------+----------+-------------------------------------------------------------------+
| dbtest.tvar | optimize | note | Table does not support optimize, doing recreate + analyze instead |
| dbtest.tvar | optimize | status | OK |
+-------------+----------+----------+-------------------------------------------------------------------+
2 rows in set (2.29 sec)
mysql> SELECT table_id, name, instant_cols FROM information_schema.innodb_tables WHERE instant_cols > 0;
Empty set (0.01 sec)
程序检查和修复办法为压缩包中提供有python脚本可以批量消除instant column。 其中
包括两种情况,一是部署的是集群,集群中包括SQLNode和shard;另一种情况是使用集群版本部署的是单个实例。
如果集群中包括SQLNode和shard,使用下面的两个文件,路径是:
bin/upgrade_optimize.py
bin/conf.ini
其中conf.ini是配置文件,将集群中其中的一个SQLNode的配置信息填写到conf.ini即可。conf.ini的内容如下:
[confg]
user=用户名
password=密码
port=端口号
host=ip地址
user和password是初始化集群时使用的用户名和password。 配置文件conf.ini设置完毕之后,
先执行 python3 upgrade_optimize.py 0 命令查询集群中SQLNode和各个shard中包含instant column的表,如下:
~$ python3 upgrade_optimize.py 0
the config is :
user: root
password:
port: 3306
host: 127.0.0.1
all instant tables in sqlnode:
`%&%$&%&!`.`!%$&*skai12``*;"'`
all instant tables in every shard:
shard name : sd1
`test`.`@'"2*&^_``p@#p#0`
shard name : sd2
`test`.`@'"2*&^_``p@#p#1`
`test`.`t1@qw<>`
然后执行 python3 upgrade_optimize.py 1 命令,消除集群中包含instant column的所有的表:
~$ python3 upgrade_optimize.py 1
the config is :
user: root
password:
port: 3306
host: 127.0.0.1
optimize instant tables in sqlnode :
optimize table `%&%$&%&!`.`!%$&*skai12``*;"'`
optimize instant tables in every shard :
shard name : sd1
optimize table `test`.`@'"2*&^_``p@#p#0`
shard name : sd2
optimize table `test`.`t1@qw<>`
optimize table `test`.`@'"2*&^_``p@#p#1`
SUCCESSS : all instant column is eliminated in SQLNode and every shard.
这时表示集群中SQLNode和各个shard中的表都已经消除了instant列。
再次使用python3 upgrade_optimize.py 0命令确认集群中所有表的instant列都被消除。
如果执行 python3 upgrade_optimize.py 1 命令时,有optimize table table_name失败,则会将optimize table失败的表列出来,例子如下:
~$ python3 upgrade_optimize.py 1
the config is :
user: root
password:
port: 3306
host: 127.0.0.1
optimize instant tables in sqlnode :
optimize table `test`.`t2`
optimize instant tables in every shard :
optimize table `test`.`tt`
Failed optimize tables in SQLNode :
`test`.`?2`
Failed optimize tables in every shard :
shard name : sd1
`t``1`.`t``1`
shard name : sd2
`t`.`t@)(^`
其中SQLNode上的test.?2表执行optimize table时失败;
shard sd1中t``1.t``1表执行optimize table失败;
shard sd2中t.t@)(^表执行optimize table失败;
执行optimize table失败的表需要人工检查失败的原因,然后消除剩余表中的instant列。
如果部署的是单个实例,那么使用下面的两个文件:
bin/upgrade_optimize_greatdb.py
bin/conf_greatdb.ini
须修改脚本upgrade_optimize_greatdb.py,加上MySQL schema,对应的函数是check_support_db()。
确保SQLNode task运行在一个SQLNode上(避免shutdown时产生binlog)
确定
mysql.greatdb_sqlnode_tasks表中的任务都要在同一个SQLNode上执行。即task_owner必须指向了同一个SQLNode。如果
mysql.greatdb_sqlnode_tasks表中的任务不在同一个SQLNode上,则需要手动强制让所有的任务都转移到同一个SQLNode上。DBA可以将无任务或者任务较少的其它SQLNode逐个关闭,待task任务都集中到一个SQLNode上后,再将其他节点启动。GreatDB Cluster[(none)]> select * from mysql.greatdb_sqlnode_tasks; +---------+--------------------+-------------+--------------------------------------+-------------+--------------------------------+---------------------+---------------------+---------+ | task_id | task_type | task_status | task_owner | object_name | info | create_time | update_time | version | +---------+--------------------+-------------+--------------------------------------+-------------+--------------------------------+---------------------+---------------------+---------+ | 1 | SHARD_RECOVER | RUNNING | 99891452-2cc6-11ed-acfe-e454e8995a0e | N/A | shard recover daemon task | 2022-09-05 10:58:49 | 2022-09-08 14:45:32 | 2 | | 4 | DEADLOCK_DETECTION | RUNNING | 99891452-2cc6-11ed-acfe-e454e8995a0e | N/A | deadlock detection daemon task | 2022-09-05 10:58:49 | 2022-09-08 14:45:32 | 2 | +---------+--------------------+-------------+--------------------------------------+-------------+--------------------------------+---------------------+---------------------+---------+ 2 rows in set (0.00 sec) GreatDB Cluster[(none)]> select @@server_uuid; +--------------------------------------+ | @@server_uuid | +--------------------------------------+ | 99891452-2cc6-11ed-acfe-e454e8995a0e | +--------------------------------------+ 1 row in set (0.00 sec)
关闭SQLNode
- 确定所有SQLNode上不存在复制延迟。通过
show master status比对GTID值。 - 通过
shutdown命令,关闭SQLNode。需要保证包含所有task任务的SQLNode节点最后关闭。
- 确定所有SQLNode上不存在复制延迟。通过
关闭DataNode
- 确保一个MGR集群上不存在复制延迟。通过
show master status比对GTID值。 - 通过
shutdown命令,关闭DataNode。
- 确保一个MGR集群上不存在复制延迟。通过
替换二进制程序
- 可以更改软链接的方式替换二进制程序。
启动SQLNode和DataNode各节点实例
- 登陆到各节点,查看系统变量@@gdb_sqld_version和@@greatdb_version(仅SQLNode存在)是否为目标版本。
启动集群服务
当SQLNode节点启动完毕且能够接受用户连接后,连接到任一SQLNode,调用如下接口重启集群服务:
-- 当集群包含多个sqlnode节点时,至少需升级半数以上sqlnode,并保证其处于正常启动状态 call mysql.greatdb_restart_cluster();若升级完毕且处于正常启动状态的SQLNode节点数未能超过半数,上述接口将报错退出。此时,只能在正常的SQLNode上调用强制重启集群接口(可能会破坏数据一致性,需评估正常启动的SQLNode中是否包含最新数据):
-- 慎用该接口 call mysql.greatdb_force_restart_cluster();确认各节点状态
查询information_schema.greatdb_sqlnodes和information_schema.greatdb_datanodes,确认各节点处于正常在线状态,无异常节点。本次升级成功。
mysql> select * from information_schema.greatdb_sqlnodes \G *************************** 1. row *************************** UUID: 595e12a8-67a0-11ec-b09d-2cf05daaf22a HOST: 127.0.0.1 PORT: 3336 STATUS: ONLINE EXECUTED_GTID: Received_transaction_set: *************************** 2. row *************************** UUID: 5f6acf11-67a0-11ec-861f-2cf05daaf22a HOST: 127.0.0.1 PORT: 3337 STATUS: ONLINE EXECUTED_GTID: Received_transaction_set:mysql> select * from information_schema.greatdb_datanodes \G *************************** 1. row *************************** NODE_ID: 29 NODE_NAME: n1 SHARD_ID: 29 SHARD_NAME: sd1 HOST: 127.0.0.1 PORT: 3338 NODE_TYPE: NODE_MGR NODE_STATE: STATE_ACTIVE EXECUTED_GTID: 32390000-0000-0000-0000-000000000000:1-6 RECEIVED_TRANSACTION_SET: 32390000-0000-0000-0000-000000000000:1-6 *************************** 2. row *************************** NODE_ID: 38 NODE_NAME: n2 SHARD_ID: 29 SHARD_NAME: sd1 HOST: 127.0.0.1 PORT: 3339 NODE_TYPE: NODE_MGR NODE_STATE: STATE_STANDBY EXECUTED_GTID: 32390000-0000-0000-0000-000000000000:1-6 RECEIVED_TRANSACTION_SET: 32390000-0000-0000-0000-000000000000:1-6
DTM升级
由非dtm版本(5.0.x) 升级到dtm版本(5.1.x),建议先将非dtm版本升级到相对新的非dtm版本,然后再升级到dtm版本。比如想从5.0.8-GA-3,升级到5.1.9-RC-5,则可以先从5.0.8-GA-3升级到5.0.9-RC-5,然后再升级到5.1.9-RC-5。
从非dtm版本(5.0.x)升级至dtm版本(5.1.x)前需要首先做额外的处理才能升级。
预处理以下格式的表
因为5.1.8较之前的版本 5.0.7, 5.0.8 在存储格式发生了变化, 需要首先处理以下格式的表
对于 "row format=REDUNDANT" 的表, 5.1.8不能对其开启分布式事务的支持. 所以在升级之前,若是数据节点上存在这种格式的表, 需要首先使用 alter table 转化其格式为 compact 或者是dynamic.
GreatDB5.1.8 因为存储格式的变化不兼容之前版本创建的 "row format=compress"格式的表. 在升级之前将"row format = compress"格式的表 alter row format 为 compact 或者是dynamic 升级完成后,可以用新版本启动 row format=compress.
关闭sqlnode与datanode之前(避免升级时进入recovery流程)
- 确保shutdown之前, 确保shard的各个节点数据是一致的(从节点的binlog应用完毕),sqlnode同样如此.
shutdown之前设置:
``` #一定要确保关闭前设置如下变量 innodb_fast_shutdown=0 innodb_buffer_pool_dump_at_shutdown=OFF innodb_buffer_pool_load_at_startup=OFF ```
通过show variables确认参数设置正确。注意,如果在配置文件中设置上述参数,需要将参数添加在[mysqld]标签内。升级完成之后,可以恢复为原来的值。
升级之前确保节点是正常关闭的 这主要是确保升级之后不需要处理升级之前失败的事务。因为数据格式的变化, 新版本不能处理之前版本残留的、需要恢复的事务。 如果升级之前可能存在这样的事务,确保
innodb_force_recovery=0启动旧版本,使用旧版本处理完这些事务。为了确保安全 也是为了验证shutdown 本身没有出问题,最好是检查各个节点的error日志,如果最近一次shutdown输出了如下 带有
Shutdown complete关键字的log, 则说明本次是 "clean shutdown":2022-03-04T14:03:28.027953+08:00 0 [System] [MY-010910] [Server] /greatdb_cluster/svr/greatdb/bin/greatdbd: Shutdown complete设置 打开 升级变量(替换二进制后、启动前) 此时, sqlnode与datanode已经正常关闭,在新版本启用之前在配置文件中
[mysqld]标签内设置:innodb_greatdb_non_dtm_upgrade_to_dtm = true;这个变量是专门为从非DTM版本升级到支持DTM版本添加的.
替换二进制程序并启动 使用支持DTM的版本启动, 并确认启动成功.
设置 关闭 升级变量(替换二进制并成功启动节点后)
innodb_greatdb_non_dtm_upgrade_to_dtm = false;这个变量是专门为升级过程添加的,在升级完成后,必须要把这个变量关闭. 这个变量不能在运行过程中处于打开状态. 关闭这个变量之后, shutdown 各个节点然后重新启动.
以上的步骤已经完成了升级,后续执行重新启动后的步骤!
升级完成后,只有sqlnode greatdb_enable_dtid=ON,greatdb_enable_xa=on,并且事务涉及的表的enable_dtid=ON才是正确使用DTM事务的方式,否则等同于普通事务,无法保证全局一致性。
binlog server升级
若binlog server从旧版本(包括GreatDB Cluster 6.0.1-GA-5、GreatDB Cluster 6.0.2-GA-1)升级到6.0.3或则GreatDB Cluster 6.0.1-GA-5、GreatDB Cluster 6.0.2-GA-1之后的版本,则在START BINLOG SERVER需要DBA手动执行如下步骤,完成binlog server上的表重建:
- 把binlog server上用户的表结构导出来:
./bin/greatsqldump --user=xxx --password=xxx --host=xxx --port=xxx --skip-comments --single-transaction --flush-logs --set-gtid-purged=COMMENT --sql-log-bin=0 --no-data --databases xxx > a.sql - 将a.sql文件导入到binlog server上,完成表的重建:
source a.sql - 启动binlog server。
人工介入操作
若从5.0.7开始升级,以上升级流程全部完毕后,登陆到各sqlnode确认是否已安装rewriter plugin。若未安装需要手工安装,否则不能使用flush rewrite_rules命令。
INSTALL PLUGIN rewriter SONAME 'rewriter.so';
若使用了binlog server。binlog server节点同样需要升级,升级步骤参考离线升级即可。
离线升级完毕,执行相应检查
至此,集群的滚动升级完毕。可登陆到集群的各个节点,执行select @@greatdb_version和select @@gdb_sqld_version查看集群中sqlnode和datanode的版本。
确认版本无误后可进行一些验证测试。




