前面我们已经知道 MTS 中为每个工作线程维护了一个 Event 的分发队列。除此之外协调线程还维护了一个非常的重要的队列 GAQ,它是一个环形队列。下面是源码中的定义:
/*
master-binlog ordered queue of Slave_job_group descriptors of groups
that are under processing. The queue size is @c checkpoint_group. Group assigned
*/
Slave_committed_queue *gaq;
每次协调线程分发事务的时候都会将事务记录到 GAQ 队列中,因此 GAQ 中事务的顺序总是和 relay log 文件中事务的顺序一致的。检查点正是作用在 GAQ 队列上的,每次检查点的位置称为 LWM,还记得上一节我叫大家先忽略的 LWM 吗?就是这个。源码中定义也正是如此,它在 GAQ 队列中进行维护。如下:
/*
The last checkpoint time Low-Water-Mark
*/
Slave_job_group lwm;
在 GAQ 队列中还维护有一个叫做 checkpoint_seqno 的序号,它是最后一次检查点以来每个分配事务的序号,下面是源码中的定义:
uint checkpoint_seqno; // counter of groups executed after the most recent CP
在协调线程读取到 GTIDLOGEVENT 后为其分配序号,记作 checkpoint_seqno,如下:
rli->checkpoint_seqno++;//增加seqno
当协调线程进行检查点的时候 checkpoint_seqno 序号会减去出队的事务数量,如下:
checkpoint_seqno= checkpoint_seqno - shift; //这里减去出队的事务
在 MTS 异常恢复的时候也会用到这个序号,每个工作线程会通过这个序号来确认本工作线程执行事务的上限,如下:
for (uint i= (w->checkpoint_seqno + 1) - recovery_group_cnt,
j= 0; i <= w->checkpoint_seqno; i++, j++)
{
if (bitmap_is_set(&w->group_executed, i))
//如果这一位 已经设置
{
DBUG_PRINT("mts", ("Setting bit %u.", j));
bitmap_fast_test_and_set(groups, j);
//那么GTOUPS 这个 bitmap中应该设置,最终GTOUPS会包含全的需要恢复的事务
}
}
关于详细的异常恢复流程将在第 25 节描述。