暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

万里数据库GreatDB离线升级操作步骤

原创 Dbb 2024-05-23
406

离线升级

GreatDB Cluster支持版本升级。5.0.7以前的版本没有项目在使用,本文档仅限5.0.7及之后的版本。

GreatDB Cluster版本号有为四段,如5.0.7.3。前三位是release版本号,包含在安装包名称中。其中最后一位是数据字典版本号,可登陆到实例后查看。

GreatDB Cluster的升级可能涉及到数据字典表的变化,若最后一位小版本发生变化,则不支持回退。

以下用于升级操作演示的集群拓扑关系为:

实例:端口号实例名称归属shardnode名
127.0.0.1:3336sqlnode1
127.0.0.1:3337sqlnode2
127.0.0.1:3338datanode1sd1n1
127.0.0.1:3339datanode2sd1n2

准备工作

  • 确认集群当前版本

    连接集群的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节点最后关闭
  • 关闭DataNode

    • 确保一个MGR集群上不存在复制延迟。通过show master status比对GTID值。
    • 通过shutdown命令,关闭DataNode。
  • 替换二进制程序

    • 可以更改软链接的方式替换二进制程序。
  • 启动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 在存储格式发生了变化, 需要首先处理以下格式的表

    1. 对于 "row format=REDUNDANT" 的表, 5.1.8不能对其开启分布式事务的支持. 所以在升级之前,若是数据节点上存在这种格式的表, 需要首先使用 alter table 转化其格式为 compact 或者是dynamic.

    2. GreatDB5.1.8 因为存储格式的变化不兼容之前版本创建的 "row format=compress"格式的表. 在升级之前将"row format = compress"格式的表 alter row format 为 compact 或者是dynamic 升级完成后,可以用新版本启动 row format=compress.

  • 关闭sqlnode与datanode之前(避免升级时进入recovery流程)

    1. 确保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上的表重建:

  1. 把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
    
  2. 将a.sql文件导入到binlog server上,完成表的重建:
    source a.sql
    
  3. 启动binlog server。

人工介入操作

若从5.0.7开始升级,以上升级流程全部完毕后,登陆到各sqlnode确认是否已安装rewriter plugin。若未安装需要手工安装,否则不能使用flush rewrite_rules命令。

INSTALL PLUGIN rewriter SONAME 'rewriter.so';

若使用了binlog server。binlog server节点同样需要升级,升级步骤参考离线升级即可。

离线升级完毕,执行相应检查

至此,集群的滚动升级完毕。可登陆到集群的各个节点,执行select @@greatdb_versionselect @@gdb_sqld_version查看集群中sqlnode和datanode的版本。

确认版本无误后可进行一些验证测试。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

文章被以下合辑收录

评论