返回顶部
首页 > 资讯 > 数据库 >从库的SQL线程和sql_slave_skip_counter参数分析
  • 687
分享到

从库的SQL线程和sql_slave_skip_counter参数分析

2024-04-02 19:04:59 687人浏览 泡泡鱼
摘要

本篇内容主要讲解“从库的sql线程和sql_slave_skip_counter参数分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“从库的SQL线程和sql_

本篇内容主要讲解“从库的sql线程和sql_slave_skip_counter参数分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“从库的SQL线程和sql_slave_skip_counter参数分析”吧!

一、调用流程大概如下

handle_slave_sql
 ->是否开启了slave_preserve_commit_order和log_slave_updates参数,开启的话需要设置提交顺序管理器
   if (opt_slave_preserve_commit_order && rli->opt_slave_parallel_workers > 0 &&
       opt_bin_log && opt_log_slave_updates)
     commit_order_mngr= new Commit_order_manager(rli->opt_slave_parallel_workers); //order commit 管理器
   rli->set_commit_order_manager(commit_order_mngr);
 ->如果是MTS则需要启动worker线程
   if (slave_start_workers(rli, rli->opt_slave_parallel_workers, &mts_inited) != 0)//启动worker线程
  {
    Mysql_cond_broadcast(&rli->start_cond);
    mysql_mutex_unlock(&rli->run_lock);
    rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
                "Failed during slave workers initialization");
    Goto err;
  ->检查rep table是否是事务类型的如果不是则报警告
     if (!rli->is_transactional()) //是否是 table或者是file类型是table类型则支持事物
    rli->report(WARNING_LEVEL, 0,
    "If a crash happens this configuration does not guarantee that the relay "
    "log info will be consistent");
  -> 初始化 relay log 的访问位置
      if (rli->init_relay_log_pos(rli->get_group_relay_log_name(),
                              rli->get_group_relay_log_pos(),
                              true, &errmsg,
                              1 )) //初始化 relay log 的访问位置
     这个位置比较关键也就是从哪里开始读取我们的relay log。如果出现错误将会导致读取的relay log错误。
     因此我们需要保证rep info的安全,如果设置了recover relay log 那么将会初始化为最新一个relay log的
     开始位置,因为所有的未执行的binlog event将会从新拉取,老的relay log 已经不重要了。后面再说。
  -> GTID event没有办法使用sql_slave_skip_counter 其具体含义参考:
    Log_event::do_shall_skip
    mysql> set global sql_slave_skip_counter=1;
    ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with 
    @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an 
    empty transaction with the same GTID as the transaction
  进入循环 知道SQL线程被杀死
  -> 进入状态stage_reading_event_from_the_relay_log
  -> 进行一段skip event的判断和日志输出
    GTID event没有办法使用sql_slave_skip_counter 其具体含义参考:
    Log_event::do_shall_skip
    mysql> set global sql_slave_skip_counter=1;
    ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with 
    @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an 
    empty transaction with the same GTID as the transaction  
  -> exec_relay_log_event 读取应用 一个event的上层接口
    ->next_event 读取下一个Event 完成MTS的检查点
      ->获取开始位置 rli->set_event_start_pos(my_b_tell(cur_log));
      ->Log_event::read_log_event
      ->如果是MTS 是否需要进行检查点
        1、是否超过检查点周期
           周期检查在函数mts_checkpoint_routine内部
             set_timespec_nsec(&curr_clock, 0);
             ulonglong diff= diff_timespec(&curr_clock, &rli->last_clock);
              if (!force && diff < period)
              {
                
                DBUG_RETURN(FALSE);
              }
        2、是否已经GAQ已经满了 
          bool force= (rli->checkpoint_seqno > (rli->checkpoint_group - 1)); //如果达到了 GAQ的大小 设置为force 强制checkpoint 
      ->是否relay log 大小已经达到最大 是否需要relay log切换
        但是需要注意如果本事物没有结束不能进行切换
                                                                                                                                     
            if (rli->log_space_limit &&                                                                                                         
                rli->log_space_limit < rli->log_space_total)                                                                                    
            {                                                                                                                                   
                                                                                              
              if (!rli->is_parallel_exec())                                                                                                     
              {                                                                                                                                 
                rli->sql_force_rotate_relay= !rli->is_in_group(); //如果不是一组就需要切换                                                      
              }                                                                                                                                 
              else                                                                                                                              
              {                                                                                                                                 
                rli->sql_force_rotate_relay=                                                                                                    
                  (rli->mts_group_status != Relay_log_info::MTS_IN_GROUP);                                                                      
              }                                                                                                                                 
                                                                                                                    
              rli->ignore_log_space_limit= true;//是一组 不能切换                                                                               
            }           
    ```                    
    ->如果读取了当前relay log的全部的relay log event,
     ->如果是当前relay log
       ->空闲状态下等待io 线程的唤醒,如果是MTS还需要定期醒来进行检查点,如下:
         ```  
         if (rli->is_parallel_exec() && (opt_mts_checkpoint_period != 0 ||
          DBUG_EVAluaTE_IF("check_slave_debug_group", 1, 0)))
      {
        int ret= 0;
        struct timespec waittime;
        ulonglong period= static_cast<ulonglong>(opt_mts_checkpoint_period * 1000000ULL);
        ulong signal_cnt= rli->relay_log.signal_cnt;
        mysql_mutex_unlock(log_lock);
        do
        {
          
          (void) mts_checkpoint_routine(rli, period, false, true); // TODO: ALFRANIO ERROR
          mysql_mutex_lock(log_lock);
          if (DBUG_EVALUATE_IF("check_slave_debug_group", 1, 0))
            period= 10000000ULL;
          set_timespec_nsec(&waittime, period);
          ret= rli->relay_log.wait_for_update_relay_log(thd, &waittime);
        } while ((ret == ETIMEDOUT || ret == ETIME)  &&
                 signal_cnt == rli->relay_log.signal_cnt && !thd->killed);
      }
      else
      {
        rli->relay_log.wait_for_update_relay_log(thd, NULL); //等待relay log 更改的信号 SQL THREAD 会等待在这里
      }        
         ```     
     -> 如果不是当前relay log 那么 SQL线程应用或者分发完成完成后就可以清理了
        并且参数relay_log_purge需要设置为1     
        if (rli->relay_log.purge_first_log
        (rli,
         rli->get_group_relay_log_pos() == rli->get_event_relay_log_pos()
         && !strcmp(rli->get_group_relay_log_name(),rli->get_event_relay_log_name())))//做relay log的清理
-> 如果是单SQL现成 获取event的时间
   这一步 就是获取计算延迟的重要因素,但是注意MTS不是在这里实在检查点里面
   last_master_timestamp
   ```
   rli->last_master_timestamp= ev->common_header->when.tv_sec + //event header 的timestamp
                              (time_t) ev->exec_time; //获取event的 timestamp作为 计算last_master_timestamp的基础数据 query event才有的执行时间
   DBUG_ASSERT(rli->last_master_timestamp >= 0);       //但是对于MTS来讲应该注意是最后一个XID EVENT的 时间不是这里设置的 在mts_checkpoint_routine里面
   ```
-> 如果gitD_MODE 且AUTO_POSITION 且是MTS需要由协调线程进行半事物的恢复 (partial transaction)    
   构造回滚EVENT进行恢复,而对已非MTS会在gtid event做回滚。
   这种情况可能出现在:
   - AUTO_POSITION情况下如果重连,会重新发送已经传输的Event。
   - AUTO_POSITION情况下如果从库异常宕机重启,并且recovery_relay_log=0的情况下,会重新发送已经传输的Event,并且relay log pos不会重置
   因此我们前面在IO线程和DUMP线程中已经讨论了,每次sql线程的启动都会通过GTID去重新寻找需要拉取的
   位置。
   coord_handle_partial_binlogged_transaction(rli, ev) 
-> apply_event_and_update_pos 非MTS 完成 应用 MTS完成分发
  -> 进行skip event操作
  -> 维护skip counter计数器
       if (reason == Log_event::EVENT_SKIP_COUNT)
          {
            --rli->slave_skip_counter;//维护skip count
            skip_event= TRUE;
          }
     我们看到slave_skip_counter是以event为单位的,但是对于最后一个event如果跨事务了
     那么整个事物都需要跳过。但是skip在GTID模式下是不能用的。       
  -> 如果不能跳过的事务 就需要应用了。MTS则完成分发
     ->完成延迟应用逻辑
       sql_delay_event(ev, thd, rli)
     ->ev->apply_event(rli); 这里单SQL线程应用 MTS完成分发,分发方式参考前面
       ->是否是进行 MTS recovery if (rli->is_mts_recovery())
          根据 bitmap 设置进行跳过处理 
           if (rli->is_mts_recovery())//如果是恢复 这个地方就是前面恢复扫描出来的位置
           {
             bool skip=
               bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index) &&
               (get_mts_execution_mode(::server_id,
                                       rli->mts_group_status ==
                                       Relay_log_info::MTS_IN_GROUP,
                                       rli->current_mts_submode->get_type() ==
                                       MTS_PARALLEL_TYPE_DB_NAME)
                == EVENT_EXEC_PARALLEL);
             if (skip)
             {
               DBUG_RETURN(0);
             }
             else
             {
               DBUG_RETURN(do_apply_event(rli));
             }
           }

到此,相信大家对“从库的SQL线程和sql_slave_skip_counter参数分析”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

您可能感兴趣的文档:

--结束END--

本文标题: 从库的SQL线程和sql_slave_skip_counter参数分析

本文链接: https://lsjlt.com/news/63446.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 从库的SQL线程和sql_slave_skip_counter参数分析
    本篇内容主要讲解“从库的SQL线程和sql_slave_skip_counter参数分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“从库的SQL线程和sql_...
    99+
    2024-04-02
  • 参数SQL_SLAVE_SKIP_COUNTER的分析
    本篇内容介绍了“参数SQL_SLAVE_SKIP_COUNTER的分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够...
    99+
    2024-04-02
  • MySQL 5.7从库system lock线程分析
    本篇内容介绍了“MySQL 5.7从库system lock线程分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学...
    99+
    2024-04-02
  • 分析数据库参数ENABLE_DDL_LOGGING从11.2到12c变化
    这篇文章主要讲解了“分析数据库参数ENABLE_DDL_LOGGING从11.2到12c变化”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“分析数据库参数EN...
    99+
    2024-04-02
  • Java多线程之线程池七个参数的示例分析
    这篇文章主要介绍Java多线程之线程池七个参数的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!ThreadPoolExecutor是JDK中的线程池实现,这个类实现了一个线程池需要的各个方法,它提供了任务提交...
    99+
    2023-06-14
  • 由FTWRL导致的MySQL从库死锁分析及参数深究
    最近线上执行备份的从库时出现复制卡死现象,分析以后发现是两个死锁,show full processlist的状态如图1所示,其中,数据库版本是官方5.7.18版本,我们内部做了些许修改,但与此次死锁无关。 ...
    99+
    2022-05-15
    MySQL MySQL
  • SQL数据库的案例分析
    小编给大家分享一下SQL数据库的案例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!数据表PRAGMA foreign_keys =&nbs...
    99+
    2023-06-22
  • Android编程之数据库Sql编程实例分析
    本文实例讲述了Android编程之数据库Sql编程实现方法。分享给大家供大家参考。具体分析如下: Android中安装轻量级数据库Sqlite,现在测试数据库基本操作。 数据库...
    99+
    2022-06-06
    数据库sql 程之 SQL 数据 Android
  • 对比Golang协程和线程的分析
    Golang协程与线程的差异解析 在现代编程语言中,多线程并发已经成为一种常见的编程模式,用于提高程序的性能和响应能力。然而,线程的创建和管理往往需要消耗大量的系统资源,同时在编程复杂性和错误处理上也存在一些...
    99+
    2024-01-24
  • SQL Server数据库分区分表的示例分析
    这篇文章主要介绍SQL Server数据库分区分表的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!1、 需求说明将数据库Demo中的表按照日期字段进行水平分区分表。要求数据文件按一年一个文件存储,且...
    99+
    2023-06-14
  • C++中占位参数和默认参数的示例分析
    这篇文章将为大家详细讲解有关C++中占位参数和默认参数的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。1,默认参数在c++中,函数的形参列表中的形参是可以有默认值的。语法: 返回值类型 函数名 (...
    99+
    2023-06-29
  • 数据库mysql存储中入参出参的示例分析
    这篇文章主要介绍数据库mysql存储中入参出参的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!入参出参语法: in|out|inout 参数名 数据类型 , ...in 定义出参; out 定义入参; ino...
    99+
    2023-06-14
  • 二十四:从库数据的查找和参数slave_rows_search_algorithms(笔记)
    欢迎关注我的《深入理解MySQL主...
    99+
    2024-04-02
  • Node.js中进程和线程的示例分析
    这篇文章给大家分享的是有关Node.js中进程和线程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。进程与线程是一个程序员的必知概念,面试经常被问及,但是一些文章内容只是讲讲理论知识,可能一些小伙伴并没有...
    99+
    2023-06-15
  • Linux中进程和线程的示例分析
    这篇文章主要为大家展示了“Linux中进程和线程的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Linux中进程和线程的示例分析”这篇文章吧。计算机实际上可以做的事情实质上非常简单,比如...
    99+
    2023-06-13
  • java中进程和线程的示例分析
    小编给大家分享一下java中进程和线程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!为什么会有进程在简单的批处理操作系统中,作业时串行执行的,即一个作业...
    99+
    2023-06-20
  • Python的进程,线程和协程实例分析
    这篇“Python的进程,线程和协程实例分析”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Python的进程,线程和协程实例...
    99+
    2023-06-29
  • numpy函数常用参数和用法的分析
    解析numpy函数的常用参数与用法 numpy是Python中常用的数值计算库,提供了丰富的数值运算函数和数据结构,能够方便快捷地进行数组运算和数值计算。本文将解析numpy函数的常用参数与用法,并提供具体的代码示例。 一、nu...
    99+
    2024-01-26
    参数 用法 数组
  • 数据分析师怎么应对数据库取数后的离线分析
    本篇内容主要讲解“数据分析师怎么应对数据库取数后的离线分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“数据分析师怎么应对数据库取数后的离线分析”吧!因为缺乏好用工具的支持,数据分析人员的离线分...
    99+
    2023-06-03
  • 数据库SQL SELECT查询的示例分析
    小编给大家分享一下数据库SQL SELECT查询的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!作为Web开发人员,虽并...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作