Mysql 5.7中mysql.gtid_executed表及其他变量更改时机是什么

网友投稿 409 2023-12-29 13:12:09

Mysql 5.7中mysql.gtid_executed表及其他变量更改时机是什么

本篇内容介绍了“Mysql 5.7中mysql.gtid_executed表及其他变量更改时机是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一、主库修改时机 (2) binlog打开

mysql.gtid_executed表修改时机

在binlog发生切换(rotate)的时候保存直到上一个binlog文件执行过的全部Gtid,它不是实时更新的。栈帧如下:

#0  Gtid_table_persistor::save (this=0x2f9f9c0, gtid_set=0x7ffff03595a0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_persist.cc:425 #1  0x0000000001803dbe in Gtid_state::save (this=0x2ff8bb0, gtid_set=0x7ffff03595a0) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:796 #2  0x0000000001803f62 in Gtid_state::save_gtids_of_last_binlog_into_table (this=0x2ff8bb0, on_rotation=true)     at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:835 #3  0x000000000185266d in MYSQL_BIN_LOG::new_file_impl (this=0x2dffc80, need_lock_log=false, extra_description_event=0x0)     at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:6751 #4  0x00000000018520a7 in MYSQL_BIN_LOG::new_file_without_locking (this=0x2dffc80, extra_description_event=0x0)     at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:6636 #5  0x0000000001853e67 in MYSQL_BIN_LOG::rotate (this=0x2dffc80, force_rotate=true, check_purge=0x7ffff0359c4b)     at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:7292

其主要逻辑在Gtid_state::save_gtids_of_last_binlog_into_table 中我们在随后的部分讨论这个函数逻辑。

gtid_executed变量修改时机

如前文所述ordered_commit flush阶段生成Gtid,在commit阶段才计入gtid_executed变量,它是实时更新的。栈帧如下:

#0  Gtid_set::_add_gtid (this=0x2ff8d38, sidno=1, gno=16at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid.h:1135 #1  0x0000000001804576 in Gtid_set::_add_gtid (this=0x2ff8d38, gtid=...)at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid.h:1166 #2  0x00000000018024ba in Gtid_state::update_gtids_impl (this=0x2ff8bb0, thd=0x7fff2c000b70, is_commit=true)     at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:304 #3  0x00000000018020df in Gtid_state::update_on_commit (this=0x2ff8bb0, thd=0x7fff2c000b70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:148 #4  0x00000000018573d4 in MYSQL_BIN_LOG::process_commit_stage_queue (this=0x2dffc80, thd=0x7fff2c000b70, first=0x7fff2c000b70)     at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:8646 #5  0x0000000001858b51 in MYSQL_BIN_LOG::ordered_commit (this=0x2dffc80, thd=0x7fff2c000b70, all=false, skip_commit=false)     at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:9304

其主要逻辑在Gtid_state::update_gtids_impl中我们在随后的部分讨论这个函数逻辑。

gtid_purged变量修改时机

在Mysql触发的清理binlog的情况下,比如purge binary logs to或者超过参数expire_logs_days设置的天数后自动删除,需要将丢失的Gtid计入这个变量中。栈帧如下:

#0  MYSQL_BIN_LOG::init_gtid_sets (this=0x2e00280, all_gtids=0x0, lost_gtids=0x2fcaee8, verify_checksum=false, need_lock=false, trx_parser=0x0, gtid_partial_trx=0x0, is_server_starting=false)at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:4333 #1  0x0000000001850b8e in MYSQL_BIN_LOG::purge_logs (this=0x2e00280, to_log=0x7fff57a74ad0 "/root/mysql5.7.14/percona-server-5.7.14-7/mysql-test/var/mysqld.1/test.000202", included=false, need_lock_index=true,      need_update_threads=true, decrease_log_space=0x0, auto_purge=false) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:6036 #2  0x0000000001848ecf in purge_master_logs (thd=0x7fff49200dc0, to_log=0x7fff492051a8"test.000202"at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:2815

其主要逻辑在MYSQL_BIN_LOG::purge_logs中,我们随后查看其代码片段,同时MYSQL_BIN_LOG::init_gtid_sets函数是一个及其重要的函数,主要用在:

Mysql启动时候初始化整个Gtid_state中的各种Gtid_set。

Mysql删除binlog(如purge binary logfiles或者超过expire_logs_days设置)后需要确认gtid_purged变量(及Gtid_state.lost_gtids)的值的时候。

随后我会单独一节来讲解Mysql Gtid模块的初始化还会讲解这个函数。

二、主库修改时机源码函数分析

这里就对上面提到的主要逻辑函数进行分析

Gtid_state::save_gtids_of_last_binlog_into_table函数逻辑

logged_gtids_last_binlog.add_interval_memory(PREALLOCATED_INTERVAL_COUNT, iv);//这里构建一个logged_gtids_last_binlog集合来保存切换后需要写入表和previous_gtids_logged的Gtid   /*     logged_gtids_last_binlog= executed_gtids - previous_gtids_logged -                               gtids_only_in_table   */   global_sid_lock->wrlock();//ret= (logged_gtids_last_binlog.add_gtid_set(&executed_gtids) !=//将当前执行过的Gtid全部加入logged_gtids_last_binlog 列如:executed_gtids start=1, end=27         RETURN_STATUS_OK);   if(!ret)   {     logged_gtids_last_binlog.remove_gtid_set(&previous_gtids_logged);//获得上一个binlog文件包含的全部Gtid,并且做一个差集 列如:previous_gtids_logged 为start=1, end=25                                                                       //做完差集后logged_gtids_last_binlog为start=26, end=27logged_gtids_last_binlog.remove_gtid_set(&gtids_only_in_table);//此处主库一定为空,除非异常情况     if (!logged_gtids_last_binlog.is_empty())      {       /* Prepare previous_gtids_logged for next binlog on binlog rotation */       if(on_rotation)         ret= previous_gtids_logged.add_gtid_set(&logged_gtids_last_binlog);//将这个start=26, end=27的Gtid集合加入到previous_gtids_logged中,这样previous_gtids_logged也完整了       global_sid_lock->unlock();       /* Save set of GTIDs of the last binlog into gtid_executed table */       if (!ret)         ret= save(&logged_gtids_last_binlog);//将这个start=26, end=27的Gtid集合写入到表mysql.gtid_executed表中     }

Gtid_state::update_gtids_impl函数代码片段

while(g.sidno !=0)     {       if (g.sidno != prev_sidno)         sid_locks.lock(g.sidno);       owned_gtids.remove_gtid(g);//从owned_gtid中去掉       git.next();       g= git.get();       if(is_commit)         executed_gtids._add_gtid(g);//将这个Gtid加入到executed_gtids     }

MYSQL_BIN_LOG::purge_logs函数代码片段

if(!is_relay_log)   {     global_sid_lock->wrlock();     error= init_gtid_sets(NULL,                           const_cast<Gtid_set *>(gtid_state->get_lost_gtids()),                           opt_master_verify_checksum,false/*false=dont need lock*/,                           NULL/*trx_parser*/NULL/*gtid_partial_trx*/);//这里我看到将gtid_state->lost_gtids直接传入给了init_gtid_sets                                                                         //init_gtid_sets会做正向查找获得gtid_state->lost_gtids这个函数稍后                                                                         //详细讨论     global_sid_lock->unlock();     if (error)       gotoerr;   } 三、从库修改时机 (2)binlog开启同时参数log_slave_updates开启的情况

这种情况sql_thread执行过的Gtid事物可以通过binlog进行维护,所以mysql.gtid_executed表和gtid_purged变量不需要实时更新。

mysql.gtid_executed表修改时机

和主库一致。及在进行日志切换的时候进行更新,不做讨论

gtid_executed变量修改时机

和主库一样实时更新,不做讨论

gtid_purged变量修改时机

和主库一致,binlog删除时更新,不做讨论

四、从库修改时机源码函数分析

commit_owned_gtids函数逻辑:

//如果 binlog 没有开启包括(log_bin=0 和 sql_log_bin =0 )或者 开启了binlog 但是slave线程并且slave update 没有开启,都会记录gtid到表 //但是这里要注意一点在主库上如果binlog不开启那么thd->owned_gtid.sidno ==0 因为这个时候Gtid都没有生成,生成阶段为order_commit的commit阶段   if((!opt_bin_log || (thd->slave_thread && !opt_log_slave_updates)) &&        (all || !thd->in_multi_stmt_transaction_mode()) &&//all 代表是否是显示begin 事物 in_multi_stmt_transaction_mode则相反       !thd->is_operating_gtid_table_implicitly && //是否是GTID_NEXT方式 flase       !thd->is_operating_substatement_implicitly)//是否是子语句 flase   {     /*       If the binary log is disabled for this thread (either by       log_bin=0 or sql_log_bin=0 or by log_slave_updates=0 for a       slave thread), then the statement will not be written to       the binary log. In this case, we should save its GTID into       mysql.gtid_executed table and @@GLOBAL.GTID_EXECUTED as it       did when binlog is enabled.     */     if (thd->owned_gtid.sidno > 0)     {       error= gtid_state->save(thd);//就是这里进行了mysql.gtid_executed表的实时更新       *need_clear_owned_gtid_ptr= true;     }     else if(thd->owned_gtid.sidno == THD::OWNED_SIDNO_ANONYMOUS)       *need_clear_owned_gtid_ptr=true;   }

Gtid_state::update_gtids_impl_own_gtid 函数逻辑片段

这个函数是5.7.17的,5.7.14没有逻辑放到了Gtid_state::update_gtids_impl中if (is_commit)   {     DBUG_EXECUTE_IF(       "rpl_gtid_update_on_commit_simulate_out_of_memory",       DBUG_SET("+d,rpl_gtid_get_free_interval_simulate_out_of_memory"););     /*       Any session adds transaction owned GTID into global executed_gtids.       If binlog is disabled, we report @@GLOBAL.GTID_PURGED from       executed_gtids, since @@GLOBAL.GTID_PURGED and @@GLOBAL.GTID_EXECUTED       are always same, so we did not save gtid into lost_gtids for every       transaction for improving performance.       If binlog is enabled and log_slave_updates is disabled, slave       SQL thread or slave worker thread adds transaction owned GTID       into global executed_gtids, lost_gtids and gtids_only_in_table.     */     executed_gtids._add_gtid(thd->owned_gtid); //加入executed_gtids集合     thd->rpl_thd_ctx.session_gtids_ctx().       notify_after_gtid_executed_update(thd);     if(thd->slave_thread && opt_bin_log && !opt_log_slave_updates)//如果是slave线程同时binlog开启了并且log_slave_updates关闭了                                                                    //如果binlog关闭则使用 executed_gtids这样提高性能前面的注释说了     {       lost_gtids._add_gtid(thd->owned_gtid);  //写入lost_gtids也就是更新参数gtid_purged变量       gtids_only_in_table._add_gtid(thd->owned_gtid);     }   } 五、通用更改时机

mysql.gtid_executed表修改时机

在reset master的时候清空本表栈帧如下:

#0  Gtid_table_persistor::delete_all (this=0x2f9f9c0, table=0x7fff2c0116a0)at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_persist.cc:795 #1  0x000000000180a4ef in Gtid_table_persistor::reset (this=0x2f9f9c0, thd=0x7fff2c000b70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_persist.cc:689 #2  0x0000000001801f2e in Gtid_state::clear (this=0x2ff8bb0, thd=0x7fff2c000b70)at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:36 #3  0x000000000184fee6 in MYSQL_BIN_LOG::reset_logs (this=0x2dffe80, thd=0x7fff2c000b70, delete_only=false)     at /root/mysql5.7.14/percona-server-5.7.14-7/sql/binlog.cc:5586 #4  0x0000000001872308 in reset_master (thd=0x7fff2c000b70) at/root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_master.cc:587

其主要逻辑在Gtid_state::clear中。

在set global gitd_purged的时候,设置本表栈帧如下:

#0  Gtid_table_persistor::save (this=0x2f9f9c0, gtid_set=0x7ffff0359a70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_persist.cc:425 #1  0x000000000180400a in Gtid_state::save (this=0x2ff8bb0, gtid_set=0x7ffff0359a70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:796 #2  0x0000000001803c25 in Gtid_state::add_lost_gtids (this=0x2ff8bb0, gtid_set=0x7ffff0359a70)at /root/mysql5.7.14/percona-server-5.7.14-7/sql/rpl_gtid_state.cc:737 #3  0x00000000016778f3 in Sys_var_gtid_purged::global_update (this=0x2de9fe0, thd=0x7fff2c000b70, var=0x7fff2c006630)     at /root/mysql5.7.14/percona-server-5.7.14-7/sql/sys_vars.cc:5888 #4  0x00000000014d5cd1 in sys_var::update (this=0x2de9fe0, thd=0x7fff2c000b70, var=0x7fff2c006630) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/set_var.cc:184 #5  0x00000000014d74ee in set_var::update (this=0x7fff2c006630, thd=0x7fff2c000b70) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/set_var.cc:812 #6  0x00000000014d6d1a in sql_set_variables (thd=0x7fff2c000b70, var_list=0x7fff2c003528) at /root/mysql5.7.14/percona-server-5.7.14-7/sql/set_var.cc:669

其主要逻辑在Gtid_state::add_lost_gtids中。

gtid_executed变量修改时机

在reset master的时候清空本变量栈帧同上

在set global gitd_purged的时候,设置本变量栈帧同上

在mysql启动的时候初始化设置gtid_executed变量,这个将在后面章节详细描述描述步骤。

gtid_purged变量修改时机

在reset master的时候清空本变量栈帧同上

在set global gitd_purged的时候,设置本变量栈帧同上

在mysql启动的时候初始化设置gtid_executed变量,这个将在后面章节详细描述描述步骤。

六、通用更改时机源码函数分析

Gtid_state::clear函数逻辑

int Gtid_state::clear(THD *thd) {  ....   // the wrlock implies that no other thread can hold any of the mutexes   sid_lock->assert_some_wrlock();   lost_gtids.clear();//此处清空gtid_purged变量   executed_gtids.clear();//此处清空gtid_executed变量   gtids_only_in_table.clear();//清空only in table Gtid set   previous_gtids_logged.clear();//清空 previous gtids logged Gtid set   /* Reset gtid_executed table. */   if ((ret= gtid_table_persistor->reset(thd)) == 1)//此处清空mysql.gtid_executed表   {     /*       Gtid table is not ready to be used, so failed to       open it. Ignore the error.     */     thd->clear_error();     ret= 0;   }   next_free_gno= 1;   DBUG_RETURN(ret); }

Gtid_state::add_lost_gtids函数逻辑

enum_return_status Gtid_state::add_lost_gtids(const Gtid_set *gtid_set) {   ......   if (save(gtid_set)) //此处将set gtid_purge的值加入到mysql.gtid_executed表中     RETURN_REPORTED_ERROR;   PROPAGATE_REPORTED_ERROR(gtids_only_in_table.add_gtid_set(gtid_set));PROPAGATE_REPORTED_ERROR(lost_gtids.add_gtid_set(gtid_set));//此处将set gtid_purge的值加入到gtid_purge变量中   PROPAGATE_REPORTED_ERROR(executed_gtids.add_gtid_set(gtid_set));//此处将set gtid_purge的值加入到gtid_executed变量中   lock_sidnos(gtid_set);   broadcast_sidnos(gtid_set);   unlock_sidnos(gtid_set);   DBUG_RETURN(RETURN_STATUS_OK); }

“Mysql 5.7中mysql.gtid_executed表及其他变量更改时机是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Mysql 5.7中Gtid相关内部数据结构有哪些
下一篇:Innodb中RR隔离级别下insert...select 对select表加锁模型和死锁案列分析
相关文章