美文网首页
MySQL:半同步(四)参数和统计值相关

MySQL:半同步(四)参数和统计值相关

作者: 重庆八怪 | 来源:发表于2021-02-10 18:23 被阅读0次

    源码版本5.7.29

    一、半同步从库的流程图

    未命名文件 (16).png

    二、半同步中几个重要的状态值(主库)

    半同步插件是否注册:半同步插件注册状态

    ReplSemiSyncMaster::init_done_
     /* True when initObject has been called */
    

    半同步插件是否启用:半同步开启状态

    ReplSemiSyncMaster::master_enabled_
    /* semi-sync is enabled on the master */
    getMasterEnabled用于获取变量
    set_master_enabled设置变量
    

    完全取决于参数rpl_semi_sync_master_enabled

    是否使用半同步(异步):半同步复制方式

    ReplSemiSyncMaster::state_
    /* whether semi-sync is switched */
    

    本状态非常重要,决定了是否是半同步复制方式,在函数ReplSemiSyncMaster::commitTrx中会完全依赖这个状态决定是否进行用户线程事务的等待,也是Rpl_semi_sync_master_status信息的来源。

    三、相关参数(主库)

    研究的参数包括

    | rpl_semi_sync_master_enabled              | ON         |
    | rpl_semi_sync_master_timeout              | 10000      |
    | rpl_semi_sync_master_trace_level          | 32         |
    | rpl_semi_sync_master_wait_for_slave_count | 1          |
    | rpl_semi_sync_master_wait_no_slave        | ON         |
    | rpl_semi_sync_master_wait_point           | AFTER_SYNC |
    
    rpl_semi_sync_master_enabled

    默认为false

    生效点:

    • 插件初始化初始化生效,参考第一节初始化函数ReplSemiSyncMaster::initObject
    • Ack_receiver线程初始化生效,参考第一节初始化函数Ack_receiver::init
    • 参数动态生效,参考函数fix_rpl_semi_sync_master_enabled

    fix_rpl_semi_sync_master_enabled函数会动态转换为半同步开启状态,并且开启Ack_receiver线程,当然根据参数rpl_semi_sync_master_wait_for_slave_countrpl_semi_sync_master_wait_no_slave
    的设置,考虑是否使用同步复制方式,并且本参数会设置到 ReplSemiSyncMaster::master_enabled_ 全局变量。如果是关闭则会转化为异步复制switch_off(),并且做一些清理操作,比如active_tranxs_。

    rpl_semi_sync_master_timeout

    默认为10000毫秒,即10秒

    生效点:

    • 等待需要的ack反馈的事务超时,生效函数为ReplSemiSyncMaster::commitTrx,如果超时那么切换为异步复制,调用switch_off函数
    • 插件初始化生效
    • 参数动态生效,参考函数fix_rpl_semi_sync_master_timeout设置方式就是赋值给ReplSemiSyncMaster::wait_timeout_
    rpl_semi_sync_master_wait_for_slave_count

    默认为 1
    本参数可以和参数rpl_semi_sync_master_wait_no_slave共同作用共同决定半同步复制还是异步复制,这里先说rpl_semi_sync_master_wait_no_slave设置on的情况
    生效点:

    • 初始化Ack_recevier线程的AckContainer的元素个数,调用函数setWaitSlaveCount
    • 等待需要的ack反馈的事务超时,会通过AckContainer遍历找到最小的ack反馈点,参考repl_semi_report_binlog_sync函数
    • 动态参数修改fix_rpl_semi_sync_master_wait_for_slave_count,这里也会重新设置AckContainer的元素个数,调用函数setWaitSlaveCount

    因此和rpl_semi_sync_master_timeout参数配合,可以决定收到多少个(默认为1个)半同步从库的ack后进行反馈。

    rpl_semi_sync_master_wait_no_slave

    默认为on

    如果为on则遵守如上rpl_semi_sync_master_wait_for_slave_count的说明,这里重点说一下它设置为false有什么作用,如果其设置为false那么会有如下影响

    生效点:

    • 每次有半连接从库退出的时候,dump线程退出之前会通过回调函数repl_semi_binlog_dump_end,调入ReplSemiSyncMaster::remove_slave函数进行判断rpl_semi_sync_master_clients(现有存在的半同步从库数量)是否小于了rpl_semi_sync_master_wait_for_slave_count的个数,如果小于了则直接切换为异步复制方式。而不需要等到无ack反馈才进行切换。
    • 如果设置半同步开启状态,需要进行判断是否rpl_semi_sync_master_clients(现有存在的半同步从库数量)是否小于了pl_semi_sync_master_wait_for_slave_count的个数,如果小于则不开启同步复制。参考函数ReplSemiSyncMaster::enableMaster
    • 动态参数修改fix_rpl_semi_sync_master_wait_no_slave,根据rpl_semi_sync_master_clients(现有存在的半同步从库数量)是否为0来决定是否开启半同步复制方式,但是这里有一个疑问判断条件为rpl_semi_sync_master_clients==0。

    因此本参数设置为false,设置rpl_semi_sync_master_timeout为一个很大的值,也不能保证主从一定是半同步复制。

    rpl_semi_sync_master_trace_level

    默认为32

    我们在前面已经多次说过,如果这个参数设置16,将会有大量的半同步日志输出。这里不做描述

    rpl_semi_sync_master_wait_point

    默认为AFTER_SYNC,这个参数也是在前面说过了,这里不做详细描述。

    生效点:

    • 主要位于回调函数repl_semi_report_commit和repl_semi_report_binlog_sync中,用于确认是在commit队列处理之前进行用户的ack反馈还是commit队列处理之后进行ack反馈。

    四、重点统计值(主库)

    主要研究的统计值包含

    | Rpl_semi_sync_master_clients               | 0     |
    | Rpl_semi_sync_master_no_times              | 0     |
    | Rpl_semi_sync_master_no_tx                 | 0     |
    | Rpl_semi_sync_master_status                | OFF   |
    | Rpl_semi_sync_master_tx_wait_time          | 0     |
    | Rpl_semi_sync_master_tx_waits              | 0     |
    | Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
    | Rpl_semi_sync_master_wait_sessions         | 0     |
    | Rpl_semi_sync_master_yes_tx                | 0     |
    
    Rpl_semi_sync_master_clients:当前处于半同步复制的从库个数
    • 增加:repl_semi_binlog_dump_start回调函数调用ReplSemiSyncMaster::add_slave,及dump线程启动时刻
    • 减少:repl_semi_binlog_dump_end回调函数调用ReplSemiSyncMaster::remove_slave,及dump线程退出时刻
    Rpl_semi_sync_master_no_times:关闭半同步复制方式的次数

    内部为rpl_semi_sync_master_off_times

    • 增加:ReplSemiSyncMaster::switch_off函数
    Rpl_semi_sync_master_no_tx:没有在半同步复制方式状态下,事务commit队列处理的次数(after_sync)/事务处理的次数(after_commit)

    内部为rpl_semi_sync_master_no_transactions。

    • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数的末尾
    Rpl_semi_sync_master_yes_tx:半同步复制方式状态下,事务commit队列处理的次数(after_sync)/事务处理的次数(after_commit)

    内部为rpl_semi_sync_master_yes_transactions。

    • 增加:同上
    Rpl_semi_sync_master_status:内部表示就是ReplSemiSyncMaster::state_,也就是当前主库状态是否处于半同步复制方式下。

    参考ReplSemiSyncMaster::setExportStats函数

    • 更改就是ReplSemiSyncMaster::switch_off函数。
    Rpl_semi_sync_master_wait_sessions:主要用于表示当前处于堵塞的session数量。
    • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数,进入等待前
    • 减少:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数,退出等待后但是需要注意的能够进入这个函数的是commit的leader线程,因此实际堵塞的会话数量可能是远远大于这个数字。
    Rpl_semi_sync_master_tx_wait_time:主要用于表示由于等待ack反馈而等待的时间,单位微秒(百万分之1秒)

    内部表示为rpl_semi_sync_master_trx_wait_time。

    • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数,等待ack之后(未超时)
    Rpl_semi_sync_master_tx_waits:同上,表示次数
    • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数,等待ack之后(未超时)
    rpl_semi_sync_master_wait_pos_backtraverse:降低wait_file_name_/wait_file_pos_的次数
    • 增加:用户线程repl_semi_report_commit/repl_semi_report_binlog_sync调用ReplSemiSyncMaster::commitTrx函数。

    五、从库参数和统计值

    从库的参数和统计值很简单,和主库不同开启rpl_semi_sync_slave_enabled参数,不会动态让从库的Rpl_semi_sync_slave_status生效,启用半同步复制方式

    参数rpl_semi_sync_slave_enabled:用于表示是否从库开启了半同步状态

    生效点为

    • ReplSemiSyncSlave::initObject初始化的时候
    • fix_rpl_semi_sync_slave_enabled动态修改,但是需要注意这里的动态修改并不影响统计值Rpl_semi_sync_slave_status
    状态值Rpl_semi_sync_slave_status:用于表示从库是否是半同步复制方式

    无法动态开启这点和主库不同,并且此状态不会由于主库问题在运行期间改变,因此不能做判断半同步复制方式的根据,应该在主库判断。
    改变:

    • dump线程启动时刻根据,rpl_semi_sync_slave_enabled参数和主库是否安装半同步插件来共同判定是否开启。
    • dump线程关闭时刻。

    下面是一个测试(主库未安装半同步插件)

    mysql> show variables like '%semi%slave_enabled';
    +-----------------------------+-------+
    | Variable_name               | Value |
    +-----------------------------+-------+
    | rpl_semi_sync_slave_enabled | ON    |
    +-----------------------------+-------+
    1 row in set (0.00 sec)
    
    mysql> start slave;
    Query OK, 0 rows affected (0.02 sec)
    
    mysql> show status like '%Rpl_semi_sync_slave_status';
    +----------------------------+-------+
    | Variable_name              | Value |
    +----------------------------+-------+
    | Rpl_semi_sync_slave_status | OFF   |
    +----------------------------+-------+
    
    

    可以看到Rpl_semi_sync_slave_status并未启动。

    下面是另外一个测试

    mysql> show slave status \G;
    *************************** 1. row ***************************
                   Slave_IO_State: Reconnecting after a failed master event read
                      Master_Host: 192.168.1.63
                      Master_User: repsem
                      Master_Port: 3325
                    Connect_Retry: 60
                  Master_Log_File: log_bin.000004
              Read_Master_Log_Pos: 194
                   Relay_Log_File: relaylog.000020
                    Relay_Log_Pos: 363
            Relay_Master_Log_File: log_bin.000004
                 Slave_IO_Running: Connecting
                Slave_SQL_Running: Yes
    
    ERROR: 
    No query specified
    
    mysql> show status like '%Rpl_semi_sync_slave_status';
    +----------------------------+-------+
    | Variable_name              | Value |
    +----------------------------+-------+
    | Rpl_semi_sync_slave_status | ON    |
    +----------------------------+-------+
    1 row in set (0.02 sec)
    

    可以看到即便IO线程已经处于重连状态,Rpl_semi_sync_slave_status依旧为on。

    六、运行状态下主库半同步状态切换时刻

    • 我们熟知的超过参数rpl_semi_sync_master_timeout的设置
      调用为
    ReplSemiSyncMaster::commitTrx 
      ->switch_off
    
    • 如果参数rpl_semi_sync_master_wait_no_slave设置false,那么当dump线程退出之前会判断是否小于rpl_semi_sync_master_wait_for_slave_count的设置,小于切换为异步
      调用为
    repl_semi_binlog_dump_end 
     ->ReplSemiSyncMaster::remove_slave
       ->switch_off
    
    • 如果Ack_recevier线程发现反馈ack的半同步从库数量满足rpl_semi_sync_master_wait_for_slave_count的设置,尝试使用半同步复制方式
      调用为
    ReplSemiSyncMaster::reportReplyPacket
     ->handleAck
       ->ReplSemiSyncMaster::reportReplyBinlog
        ->try_switch_on
    
    • 设置参数rpl_semi_sync_master_enabled参数的时候,会尝试使用半同步复制模式,参考上文
    • 设置参数rpl_semi_sync_master_wait_no_slave参数的时候,会尝试改变半同步复制模式,参考上文

    六、两个半同步从库的流程图

    未命名文件 (16).png

    相关文章

      网友评论

          本文标题:MySQL:半同步(四)参数和统计值相关

          本文链接:https://www.haomeiwen.com/subject/kxekxltx.html