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

MySQL 关闭半同步

天天李拜天DBA 2022-11-11
986

这是以前的一个经历了,当时背景是要下线一套没有压力集群的两个slave的物理机,改为虚拟机。但是因为没了解到这套集群开了半同步,在关闭第二台slave时发生了ACK等待的报错。后来就有了这个关闭半同步的操作。

环境

IP版本角色PORT复制模式
172.0.0.665.6.10Master3306半同步
172.0.0.685.6.10slave3306半同步
172.0.0.685.6.10slave3307半同步

参数

Master端

mysql> show global status like '%semi%';
+--------------------------------------------+-----------+
| Variable_name                              | Value     |
+--------------------------------------------+-----------+
| Rpl_semi_sync_master_clients               | 2         |
| Rpl_semi_sync_master_net_avg_wait_time     | 508       |
| Rpl_semi_sync_master_net_wait_time         | 480620193 |
| Rpl_semi_sync_master_net_waits             | 945539    |
| Rpl_semi_sync_master_no_times              | 2         |
| Rpl_semi_sync_master_no_tx                 | 0         |
| Rpl_semi_sync_master_status                | ON        |
| Rpl_semi_sync_master_timefunc_failures     | 0         |
| Rpl_semi_sync_master_tx_avg_wait_time      | 910       |
| Rpl_semi_sync_master_tx_wait_time          | 576324352 |
| Rpl_semi_sync_master_tx_waits              | 633076    |
| Rpl_semi_sync_master_wait_pos_backtraverse | 1         |
| Rpl_semi_sync_master_wait_sessions         | 0         |
| Rpl_semi_sync_master_yes_tx                | 1900240   |
| Rpl_semi_sync_slave_status                 | OFF       |
+--------------------------------------------+-----------+
15 rows in set (0.00 sec)

mysql> show global variables like '%semi%';
+------------------------------------+---------+
| Variable_name                      | Value   |
+------------------------------------+---------+
| rpl_semi_sync_master_enabled       | ON      |
| rpl_semi_sync_master_timeout       | 1000000 |
| rpl_semi_sync_master_trace_level   | 32      |
| rpl_semi_sync_master_wait_no_slave | ON      |
| rpl_semi_sync_slave_enabled        | OFF     |
| rpl_semi_sync_slave_trace_level    | 32      |
+------------------------------------+---------+
6 rows in set (0.01 sec)


复制

Slave端

mysql> show global variables like '%semi%';
+------------------------------------+-------+
| Variable_name                      | Value |
+------------------------------------+-------+
| rpl_semi_sync_master_enabled       | OFF   |
| rpl_semi_sync_master_timeout       | 10000 |
| rpl_semi_sync_master_trace_level   | 32    |
| rpl_semi_sync_master_wait_no_slave | ON    |
| rpl_semi_sync_slave_enabled        | ON    |
| rpl_semi_sync_slave_trace_level    | 32    |
+------------------------------------+-------+
6 rows in set (0.00 sec)

复制

  • 注释:
    本次使用的MySQL是5.6
    5.7 中的show global variables like '%semi%' 会多两个参数 rpl_semi_sync_master_wait_for_slave_count: master获得ACK的数量 rpl_semi_sync_master_wait_point : master 等待ACK的位置

场景模拟

一个脚本不断往master插入数据

#!/bin/bash
for i in {1..300000}
do
#sleep 1
/mysql/bin/mysql -uroot -p'mbV' -e "insert into test_li.t1 values($i)"
/mysql/bin/mysql -uroot -p'mbV' -e "select i from test_li.t1 order by i desc limit 1;"
done


复制

关闭半同步

总述:

1.调整master 参数
2.关闭slave半同步
3.关闭master半同步

操作

1.调整master参数
 set global rpl_semi_sync_master_timeout=100;
 set global rpl_semi_sync_master_wait_no_slave='off';

复制
  • 在5.7 中还可以rpl_semi_sync_master_wait_for_slave_count
    设置为下线后的slave数(最小为1,因此该参数只能平稳的缩减半同步的slave数而不能达到关闭半同步的效果)

目的:

  • rpl_semi_sync_master_timeout
    在slave关闭半同步的时候缩短等待ACK锁的时间
  • rpl_semi_sync_master_wait_no_slave
    :设置为off,是当一个发生半同步降级后,如果slave 追上同步,MySQL不会自动升级为半同步模式
2. 关闭slave 半同步,并重启复制

重点注意:
注意  MySQL 5.6 中的master 获取ack 数量和有多少个slave无关(N>=1) 即只有当所有的半同步的slave都停了的时候才会发生ack 等待.因此只关闭1个slave 是不会发生ACK等待,不需要也不能关闭master的半同步模式

set global rpl_semi_sync_slave_enabled='off';
stop slave;
start slave;

复制
3.关闭master 半同步
set  global rpl_semi_sync_master_enabled='off';  

复制

错误操作

如果直接关闭所有slave 导致ACK等待

mysql> show processlist;
+--------+----------+-------------------+---------+-------------+------+-----------------------------------------------------------------------+-------------------------------------+
| Id     | User     | Host              | db      | Command     | Time | State                                                                 | Info                                |
+--------+----------+-------------------+---------+-------------+------+-----------------------------------------------------------------------+-------------------------------------+
|      1 | root     | localhost         | test_li | Sleep       |   66 |                                                                       | NULL                                |
|  45964 | root     | localhost         | NULL    | Query       |    0 | init                                                                  | show processlist                    |
755735 | rpl_user | 172.0.0.68:57061 | NULL    | Binlog Dump |  441 | Master has sent all binlog to slave; waiting for binlog to be updated | NULL                                |
| 764915 | root     | localhost         | NULL    | Query       |  142 | Waiting for semi-sync ACK from slave                                  | insert into test_li.t1 values(1715) |
+--------+----------+-------------------+---------+-------------+------+-----------------------------------------------------------------------+-------------------------------------+
4 rows in set (0.00 sec)

复制
  • 解决办法: 恢复一个slave 的半同步即可恢复
错误解决发生ACK等待的操作
  1. 调整 rpl_semi_sync_master_timeout 和rpl_semi_sync_master_wait_no_slave 参数在master操作不会影响现有回话的
    (可以证明关闭半同步 先调整set global rpl_semi_sync_master_timeout
    set global rpl_semi_sync_master_wait_no_slave
    参数的重要性)
    并且线上请求很多,无法容忍通过等待频繁的降级升级半同步的方法将现有堵塞事务完成,并断开回话,除非进行kill

  2. 关闭master 的半同步 set  global rpl_semi_sync_master_enabled='off';  该操作会造成数据库宕机!!!!!!!!!!!!!!!!!!!!!!!!!

文章转载自天天李拜天DBA,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论