mysql宕机恢复原理

异常故障恢复

并行复制总是存在一个不可避免的问题,那就是在从库并行执行的过程中,如果数据库或操作系统挂了,那么此时每个线程执行的点就都是不确定的。也就是说顺序的binlog被分发出去了之后,从最小位置到最大位置之间这块连续的内容之间存在断点的。如此一来,从库恢复之后,开始执行时就需要准确无误地还原哪些已经执行,哪些还没有执行。

一个正在并行执行的事物队列,也可以说这些事务的last_committed都是相同的,并且从前到后。此外sequence_number是顺序增长的,也就是说以binlog文件内容的顺序排列的。

整个队列被分配之后,在某一时刻,队列执行的状态,假设从库挂了,,那么在次启动之后,如何继续执行?

mysql为了实现对执行状态的记录,做了很多工作,首先就是维护一个队列,这个队列叫做GAQ,group assigned queue,SQL线程在分配某一个事务时,首先会将这个事物加入到这个队列,之后系统会将当前事物分发到一个线程来执行。可以想到,在某一个时刻,任务队列GAQ及每个线程的执行队列,每一个事物,在分发之后,都会有一个标号,这个标号在某一段时间内,都是相对固定的,这个编号在某一时间段内都是相对固定的如图:

每一个事务都有一个编号,编号只要分配了,就不会在变。在事物获取编号且被所属线程执行之后,它的位置信息会被FLUSH一次,这与mysql5.5.版本中的relay_info是类似的,用来存储从库执行的位置。但是现在已经变为多线程了,那么每个线程执行到什么位置,是需要记录下来的,此时就用另一个表mysql.slave_worker_info来存储。

 

mysql> show create table slave_worker_info\G
*************************** 1. row ***************************
       Table: slave_worker_info
Create Table: CREATE TABLE `slave_worker_info` (
  `Id` int(10) unsigned NOT NULL,
  `Relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `Relay_log_pos` bigint(20) unsigned NOT NULL,
  `Master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `Master_log_pos` bigint(20) unsigned NOT NULL,
  `Checkpoint_relay_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `Checkpoint_relay_log_pos` bigint(20) unsigned NOT NULL,
  `Checkpoint_master_log_name` text CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
  `Checkpoint_master_log_pos` bigint(20) unsigned NOT NULL,
  `Checkpoint_seqno` int(10) unsigned NOT NULL,
  `Checkpoint_group_size` int(10) unsigned NOT NULL,
  `Checkpoint_group_bitmap` blob NOT NULL,
  `Channel_name` char(64) NOT NULL COMMENT 'The channel on which the slave is connected to a source. Used in Multisource Replication',
  PRIMARY KEY (`Channel_name`,`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 STATS_PERSISTENT=0 COMMENT='Worker Information'
1 row in set (0.00 sec)
这个表用来存储每一个线程的执行情况,有多少个线程,就有多少条记:

Relay_log_name:存储挡墙线程最新执行到的从库relay_log的文件名。

Relay_log_pos:存储当前线程罪行执行到的上面文件中的位置。

Master_log_name:存储当前线程最新执行到的主库master log的文件名。

Master_log_pos:存储当前线程最新执行到的上面文件中的位置。

Checkpoint_relay_log_name:存储当前线程最新的检查点的从库relay log的文件名。

Checkpoint_relay_log_pos:存储当前线程最新执行到的上面温江中的位置。

Checkpoint_master_log_name存储当前线程最新检查点的主库masterlog文件名。

Checkpoint_master_log_pos:存储当前线程最新执行到的上面的文件中的位置。

Checkpoint_seqno:分配给当前最新执行事务,这时相对于当前线程最新的检查点而言的。

Checkpoint_group_size:用来存储最大的执行队列长度,当执行线程的队列达到这个长度时,必须做一次检查点。

Checkpoint_group_bitmap:用来存储在当前线程最新检查点的上下文环境里,这个线程已经执行的事务,是一个位图值,这是用来恢复数据库的一个关键值。

Channel_name:多源复制时使用。

 

 

每个线程在执行玩一个事务之后,会把执行星系写入到slave_worker_info表中。到那时CAQ队列长度是有限的,不可能一直增长下去,所以必须在这个队列中,找到一个位置,这个位置事物CAQ的起点,并且之前的binlog都是已经执行过的,而这个过程,就被称作,检查点。那么多线程复制就可以归结为:检查点在CAQ中周而复始地向前推进复制位置,每个线程在不断地APPLY binlog,并且通过checkpoint_group_bitmap记录已经执行的事务与最新检查点的相对位置。

 

从库crash之后如何恢复复制?而在恢复时,系统首先要做的就是把slave_master_info,slave_relay_log_info及slave_worker_info表中的内容读出来,找到连接主库的信息(slave_master_info),然后在找到复制位置及线程个数(slave_relay_log_info),然后在找到每一个线程的复制信息(slave_worker_info)等,读取完毕后就可以开始恢复了。

从slave_relay_log_info读出来的位置,就是系统整体最新检查点的位置。这个位置以前的每个事物肯定都已经复制完成了,那么恢复也从这个位置开始。因为从这个位置开始,后面的有些事物已经执行,有写还没有执行。

恢复的过程是按照不同线程诸葛分析的过程。首先如果线程最新的执行位置落后于最新检查点的位置,那么这个线程就不需要恢复了,因为这个线程执行的所有事务都是完整的,做完这层过滤之后,就分别对剩下的线程做恢复检查。

 

 

 

 

 

 

 

 

 

 

 

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页