MySQL:MTS中显示事务和隐式事务延迟计算的区别和mysqldump死锁
一、问题描述
遇到一个这样的问题
-
隐式大事务:update db_alart_1.sbtest1 set k=k+'11dcs1' where id between 10000 and 1001000; 延迟从20分钟开始 -
显示大事务:begin;update db_alart_1.sbtest1 set k=k+'11dcs1' where id between 10000 and 1001000; commit;大部分延迟一会从0开始
二、问题分析
我们以前说过MTS的延迟计算有如下公式
-
从库服务器时间 - 检查点XID_EVENT header中timestamp的时间 - 主从服务器时间差
这个代码流程获取流程如下:
一、工作线程执行到事务XID_EVENT的时候,会设置如下值:
ptr_group->ts= common_header->when.tv_sec + (time_t) exec_time;
//Seconds_behind_master related //checkpoint的时候会将这个值再次传递
//mts_checkpoint_routine()
二、当进行检查点的时候设置变量ts,调用函数mts_checkpoint_routine
/*
Update the rli->last_master_timestamp for reporting correct Seconds_behind_master.
If GAQ is empty, set it to zero.
Else, update it with the timestamp of the first job of the Slave_job_queue
which was assigned in the Log_event::get_slave_worker() function.
*/
ts= rli->gaq->empty()
? 0
: reinterpret_cast<Slave_job_group*>(rli->gaq->head_queue())->ts;
//rli->gaq->head_queue 检查点位置的GROUP的时间
三、更改last_master_timestamp值为ts变量,函数Relay_log_info::reset_notified_checkpoint
last_master_timestamp= new_ts;//设置last_master_timestamp为ts
也就是如下:左边<---右边 GAP队列表示
x代表是已经提交的位置,o代表正在执行,检查点已经做到了LWM位置,GAP队列出队了,那么计算就是第一个o位置xid event的时间。
显然我们知道的是
-
显示事务,xid event记录的时间为commit命令发起的时间 -
隐式事务,xid event记录的时间为语句发起的时间
那么在计算延迟的时候,显示事务从0开始计数,隐式事务从主库执行时间开始计数。
因此我们得出结论:如果长期没有新的事务那么GAP队列会出队完成,且清空。当新的事务到来 第一个GTID EVENT会分配GROUP元素,并且放入GAP队列,
gaq->assigned_group_index= gaq->en_queue(&group);
代表一个事务开始了,那么这个时候,GAP队列就不为空了。当SQL协调线程分配到XID event的时候,会将这个event的 timestap 赋予给GROUP->TS,作为计算延迟的标准。但是这里有一个特殊情况(疑问):事务较大,虽然GTID EVENT分发了但是由于分发实际的数据even的t时间较长,还没来到XID event,那么这个时候GTOUP->TS 到底为何值,要看GROUP 结构的初始化是如何做的了。这个后面在分析一下。
三、测试
测试很简单:
-
显示大事务从0开始计数。
-
隐式大事务从主库执行时间开始计数。
仅此记录,不做过多描述。