手动恢复_MariaDB_集群

发布时间 2023-04-24 11:04:39作者: XU-NING

KEYWORDS: tencent, tstack, solution,

HISTORY:

  • Created at 15:26:22 on 2020-02-15.

手动恢复 MariaDB 集群 (TStack K 与 P 版均适用) (2020-02-15)

[ERROR] WSREP: bind: Address already in use
[ERROR] WSREP: failed to open glom backend connection: 98 : error while trying to listen 'tcp://0.0.0.0:4567?socket.non_blocking=1', Asia error 'bind: Address already in use': 98 (Address already in use) at gcomm/src/asio_tcp.cpp:listen():843
[ERROR] WSREP: gcs/src/gcs_core.cpp:gcs_core_open():208: Failed to open backend connection: -98 (Address already in use)
[ERROR] WSREP: gas/src/gcs.cpp:gcs_open():1380: Failed to open channel 'galera_cluster' at 'gcomm://192.168.100.103,192.168.100,101,192.168.100.102': -98 (Address already in use)
[ERROR] WSREP: gcs connect failed: Address already in use
[ERROR] WSREP: wsrep::connect(gcomm://192.168.100.103,192.168.100.101,192.168.100.102) failed: 7
[ERROR] WSREP: Aborting

场景描述 (2020-02-15)

TStack K 版, 监控云, MariaDB 集群中的一个节点启动失败. 在执行启动操作时, /var/log/mariadb/mariadb.log 报错如下. 需要手动恢复 MariaDB 集群.

2020-02-15 12:44:17 140297052874496 [Note] WSREP: (d0e7f692, 'tcp://0.0.0.0:4567') turning message relay requesting off
WSREP_SST: [ERROR] xtrabackup_checkpoints missing, failed innobackupex/SST on donor (20200215 12:44:26.448)
WSREP_SST: [ERROR] Cleanup after exit with status:2 (20200215 12:44:26.451)
2020-02-15 12:44:26 140297042384640 [ERROR] WSREP: Process completed with error: wsrep_sst_xtrabackup-v2 --role 'joiner' --address '172.18.58.243' --datadir '/data/mariadb/data/'   --parent '5189' --binlog '/data/mariadb/binlog/mysql-bin' : 2 (No such file or directory)
2020-02-15 12:44:26 140297042384640 [ERROR] WSREP: Failed to read uuid:seqno and wsrep_gtid_domain_id from joiner script.
2020-02-15 12:44:26 140302735898592 [ERROR] WSREP: SST failed: 2 (No such file or directory)

操作示例

本文档理论上 K 版与 P 版的监控云都适用, 但有些环境依然不能同步. 详情参见下一小节.

下述操作以 3 个节点为例进行演示. 在实际生产环境中, 特别是早期的版本, 监控云 MariaDB 集群实际可能只有 2 个节点.

下述指令在执行前请 务必注意 切换到执行节点.

  1. 在 3 台节点停掉 supervisor/systemd 管理的 mysql 并且确定无残余进程. 在监控云 3 个节点分别执行.

    # 根据实际生产环境, 选择处理方式
    supervisorctl stop mariadb
    
    # 没有托管在 supervisor 中的 mariadb
    systemctl stop mariadb
    
    # K 版监控云, 本例所采用的方式.
    service mariadb stop
    
    # 确认无残余进程
    ps aux | grep -e mysql -e mariadb
    
  2. 找到数据量最多的节点. 在监控云 3 个节点分别执行.

    /usr/local/mariadb/bin/mysqld_safe --user=mysql --wsrep-recover=1 && \
        tail -n 2 /var/log/mariadb/mariadb.log
    
    # 输出类似于
    # 200215 14:13:47 mysqld_safe Logging to '/var/log/mariadb/mariadb.log'.
    # 2020-02-15 14:13:57 140598020413408 [Note] WSREP: Recovered position: f349eed7-22bd-11e8-9fd7-76c4da6ecde0:1775589804
    # 200215 14:14:00 mysqld_safe mysqld from pid file /var/run/mariadb/mariadb.pid ended
    

    数字最大的即为数据量最多的节点. 例如, 这里的返回值为 1775589804 的节点.

    若存在返回值为 -1 的节点, 还需要根据数据量和文件夹更新时间等信息进一步判断.

  3. 修改配置. 在数字最大的节点上执行, 此节点为主节点.

    sed -i '/safe_to_bootstrap/s/0/1/' /data/mariadb/data/grastate.dat
    
    # 确认修改是否成功
    cat /data/mariadb/data/grastate.dat
    
  4. 在主节点上启动 MariaDB. 在主节点执行, 即数据量最多的节点.

    # 确认该文件夹是否存在, "用户与用户组" 是否为 "mysql:mysql"
    ls -ld /var/run/mariadb/ /var/run/mariadb/*
    
    # 若不是, 执行以下指令修正
    #mkdir -p /var/run/mariadb
    #chown -R mysql:mysql /var/run/mariadb
    
    # 确认该文件夹内是否有名为 "mysql" 的文件, 如果有, 则删除
    ls -l /var/lock/subsys/
    #rm -f /var/lock/subsys/mysql
    
    # 在主节点上启动 MariaDB.
    /usr/local/mariadb/bin/mysqld_safe --user=mysql \
        --wsrep-cluster-address='gcomm://' > /dev/null 2>&1 &
    
    # 直到连通, 即返回 "active"
    /usr/local/mariadb/bin/mysqladmin ping
    

    补充说明 (2020-02-23): 在某些情况下, 会遇到数据库启动失败的情况, 除通过日志确认启动失败的原因外, 还可以考虑的处理措施有以下几点:

    注意, 下述处理措施存在风险, 请务必谨慎操作.

    • 如果日志中显示某个或某些 .ibd 文件影响到数据库服务启动, 可考虑将前缀相同的 2 个文件 (后缀分别为 .ibd.frm ) 备份后删除, 然后尝试重启数据库, 由数据库同步和恢复.
    • 如果该节点不是 Venus 节点的话, 如果数据库和 RabbitMQ 启不来, 先把 supervisorctl 所有服务停止, 全力把 MariaDB 和 RabbitMQ 集群启直来.
    • 如果该节点是 Venus 节点的话, 需要先向客户确认是否有业务的需要, 才可停止 supervisorctl 托管的服务.
    • (建议向研发确认) 如果节点仍然启动失败, 可考虑在节点上将 /data/mariadb/data/galera.cache 文件移动 (不要直接删除) 到其他目录, 尝试重启.

  5. 启动另外 2 个节点的数据库. 在主节点之外的另外 2 个节点上执行.

    # 确认该文件夹是否存在, 以及属主是否为 "mysql:mysql"
    ls -ld /var/run/mariadb/ /var/run/mariadb/*
    
    # 若不是, 执行以下指令修正
    #mkdir -p /var/run/mariadb
    #chown -R mysql:mysql /var/run/mariadb
    
    # 在第 2 和第 3 个节点上分别启动数据库.
    /usr/local/mariadb/bin/mysqld_safe --datadir=/data/mariadb/data \
        --pid-file=/var/run/mariadb/mariadb.pid > /dev/null 2>&1 &
    
    # 直到连通, 即返回 "mysqld is alive"
    /usr/local/mariadb/bin/mysqladmin ping
    

    需要说明的是, 在第 2 和 3 个节点上, 分别启动数据库之后, 可能需要很长的时候, mysqladmin ping 才能返回 mysqld is alive 的结果.

    在这 2 个节点启动数据库后, 数据同步需要一定的时间, 具体视数据量的大小而定. 具体情况一方面可以查看 3 个节点的日志 /var/log/mariadb/mariadb.log, 另一方面也可以通过 df -h 等指令查看 MariaDB 数据所在分区进行观察.

    以处理一次故障为例, 数据同步过程持续了约 40 分钟.


    如果遇到数据库启动失败的情况, 请参见上一节的 "补充说明".


  6. 检查集群状态. 在监控云 3 个节点分别执行.

    # 确认数量是否为 "3"
    /usr/local/mariadb/bin/mysql -e 'show status like "wsrep_cluster_size";' \
        2>/dev/null | sed -n '2p' | awk '{print $2}'
    
  7. 上述步骤如果返回结果均为 3. 在主节点执行下述操作.

    # 杀掉主节点的 "mysql" 进程
    ps aux | grep mysql | grep -v grep | awk '{print $2}' | xargs kill
    
    # 先行几秒, 确认无残留进程
    ps aux | grep -e mysql -e mariadb
    
    # 在主节点上以正常方式启动 MariaDB.
    /usr/local/mariadb/bin/mysqld_safe --datadir=/data/mariadb/data \
        --pid-file=/var/run/mariadb/mariadb.pid > /dev/null 2>&1 &
    
    # 直到连通, 即返回 "active"
    /usr/local/mariadb/bin/mysqladmin ping
    
  8. 再次检查集群状态. 在监控云 3 个节点分别执行.

    # 确认数量是否为 "3"
    /usr/local/mariadb/bin/mysql -e 'show status like "wsrep_cluster_size";' \
        2>/dev/null | sed -n '2p' | awk '{print $2}'
    

扩展性内容

本文档理论上 K 版与 P 版的监控云都适用, 但有些环境依然不能同步.

这是因为部分 P 版, 是有设置同步时长的, 如果数据很多, 超时就会被中止.

对于这部分环境, MariaDB 是托管在 supervisor 中的, MariaDB 的启动脚本为 /usr/local/mariadb/scripts/start_cluster.sh.

如果遇到数据量过大的情况, 可修改此脚本, 搜索 300 (单位应该为 "秒"), 并修改为一个合适的值, 一共 2 处.


除此之外, 也可 "自己通过命令先手动同步, 然后再通过 supervisor 启动".