MySQL主从复制
在MySQL主从复制过程中,会有两个角色,master和slave,数据流向是从master到slave。单个主机的数据库服务器缺少健壮性,当主机出现故障后,数据库无法正常对外提供服务,对应用来是不可避免。所以这个时候需要提高数据库系统的健壮性,主从复制replication,是将master主机上指定数据库的变化,记录在指定的binlog文件中,slave主机通过读取master主机的binlog文件,将变化的数据,写入到slave主机的本地数据库中。实现数据库的备份。
MySQL数据库的主从复制,是一个异步的过程,也就是说master库的写操作,和slave库的复制操作,并没有关系,可以完全剥离开。
实现了MySQL数据库的主从复制之后,这个时候就带出一个更好的优势,不仅能对master数据库服务器进行数据备份,还能做读写分离,由于主从复制的特殊性,所有的更新数据库的操作,都必须在master主机上进行,避免在slave主机上操作后,导致主从复制的结果不一致,slave主机上保留的,是master主机的完全副本,所以这个时候,对应用来说,所有的读操作,就可以放在slave主机上。相比于之前,同一台数据库服务器上,既进行数据库写操作,又进行数据库读操作,开启主从复制之后,可以规划应用,写操作只在master主机上,将所有的读操作,分担到所有的slave主机上,这就减轻了master主机的压力,同时,也提升了数据库读写的性能。
主从复制的三个线程:
1、master主机的IO线程,Binlog dump thread
一旦要开启主从复制,master主机上必须要制定一个二进制文件的位置,也就是binlog文件位置,在binlog文件中,记录了master数据库的变化,在master数据库变化的时候,一方面,master数据库将IO写操作,写入到本地数据库中data,同时,通过这个IO线程,记录master数据库的变化,将变化的内容,写入到二进制文件中。
该IO线程,还作为服务端,处理slave主机发过来的请求,在slave主机发过来的IO请求中,包含了几个关键因素:用户名/密码,binlog_file文件和位置position,其中用户名/密码是在master主机上创建的,并且分配了指定数据库的replication权限的,用户对slave主机进行鉴权;binlog_file文件名和position是用来确定slave主机需要从哪里开始读取更新变化。根据slave主机发来的请求,该IO线程,会去指定的binlog_file和位置position,读取现有的更新内容,发送给slave端。同时还会将读取之后的新的binlog_file和位置position发送给slave主机。
show processlist,查看。
该线程向在读取master主机上binlog文件时,需要添加一个锁,当数据内容被读取之后,该锁就释放了,数据内容读取出来之后,就会由该线程发给slave。而锁的释放,有可能是在数据发送给slave之前。
2、slave主机的IO线程
slave主机通过该IO线程,向master主机请求binlog日志文件,请求时会带上用户名/密码,binlog_file和位置position,接收到master主机的反馈后,master主机会反馈两部分内容,数据库binlog文件,和新的binlog_file和position位置,该IO线程会将数据库binlog文件内容,写入到自己的relay_log中,以增加的方式,同时将新的master主机的binlog_file和位置position写入到自己的master.info文件中,直接覆盖。master主机的属性、自己的用户名/密码、binlog_file和position都是slave主机设置的,一旦开启了主从同步,会自动生成master.info文件,每同步一次,该master.info文件就会更新一次。
当slave主机上启用了start slave之后,就会创建这个IO线程,这个线程会连接到master主机上,请求master主机binlog中的更新。
该IO线程,会读取master主机发送回来的更新,然后复制到本地文件中,组成自己的relaylog
通过show slave status中SLAVE io running,可以看到该线程的状态。
3、slave主机的SQL线程
slave主机的SQL线程,会时时监控slave主机的relay_log文件,当发现relay_log中有增加内容时,会将读取内容,还原成master主机上执行过的SQL操作,写入到本地的数据库中。
在一个主从复制组group中,有3个线程,其中master上只会有一个bin log dump线程,每一个slave主机上,都会有两个线程。
在slave主机上,2个线程分开处理,1个从master上去读取binlog,1个在本地执行,这是两个分别独立的任务,这两个任务之间也不会有什么影响,IO线程慢,不会影响SQL线程。比如,当slave主机停止复制了一段时间,当slave主机启动开始复制周,IO线程会从master主机上抓取所有的binlog信息,不管SQL线程处理了多少。当SQL线程还没有完全将IO线程抓取的binlog信息内容完全处理时,slave主机停止了,这个时候数据也不会丢失,因为IO线程已经获取了所有的binlog,并且存放到自己的本地relaylog中,当下一次slave主机启动时,继续执行SQL线程,这也方便master主机清理自己的binlog,一旦slave获取了binlog内容,master主机就会清理了。
master主机上的线程

slave上的线程

在数据复制过程中,slave上会生成多个日志文件,用来保存从master主机上获取的binlog信息,现在的状态,以及出列到relaylog中的位置,主要有三种:
1、relay log中的内容,是从master的binlog中读取的信息,由slave的IO线程写入,在relay log中的事件event,会被SQL线程执行
2、master info log,会记录slave主机连接的master主机的状态信息和当前的配置信息,包含master主机名,登录凭据,以及slave主机已经读取到的位置
3、relay log info,记录了SQL线程执行了relay log中的位置。
Relay log
relay log和binlog类似,包含了大量了描述数据库变更的文件,同时包含一个索引文件,该索引文件是所有使用过的relay log的名称。
relay log文件,指的是包含许多描述数据库变更的事件,而relay log,则是relay log文件和索引。
relay log文件,和binlog有相同的格式,可以通过mysqlbinlog来读取。默认情况下,relaylog文件存放在data目录中,命名格式是hostname-relay-bin.****,hostname是主机名,××××是序列号,序列号是连续的,连续的日志文件都是通过连续的序列号产生的,slave会用一个index索引文件,来跟踪当前使用的relay log文件,默认的索引文件也是在data目录中显示。默认情况下,relay log文件和index文件,都是连续产生的,也可以通过设置服务器属性,来直接覆盖。
如果slave主机使用的是基于主机名的命名方式,来命名relaylog文件,当修改了slave主机的主机名后,会产生问题,导致复制失败,Failed to open the relay log and Could not find target log during relay log initialization。为了避免出现这样的问题,在初始化配置slave主机的时候,可以通过属性来设置relay log和index的命名。这就使得命名和主机名独立开来。
当SQL执行了relay log之后,会自动删除,因为已经执行了,也就不在需要这些文件了,
master.info文件和relay-log.info文件存储在硬盘上,当slave主机重新启动时,通过读取这两个文件,就能知道需要从master的binlog的何处开始读取binlog内容,以及需要从自己的relay-log的何处开始执行。其中,master.info文件是由slave上的IO线程负责更新的,relay-log.info文件是由SQL线程负责更新。

这是slave上的master.info文件,一次显示的是文件中行数、master的binlog文件、位置、master主机名、用户、密码、端口、重复次数。
而relay-log.info中显示了4行,relay log文件,位置,从master的读取的binlog文件名,slave上已经执行的位置(如果已经复制完成,后两行,应该和master上show master status内容一致)

如果slave复制在进行,直接通过show slave status就可以看到状态,如果没有运行,就需要看文件了。
主从复制的4中架构演变
- 一主一从,主机负责写,从机负责读
- 一主多从,防止从机故障,影响读操作
- 多级主从,防止主机故障,影响写操作
- multi-source
在一主多从中,一个master主机,下挂了多个slave从机,当master主机出现故障时,slave主机也就无法执行写操作,所以要对master主机进行保护,这个时候,可以考虑master主机做一个双主从服务,举个例子,两台主机A和B,A即是B的master主机,也是B的slave从机,保证无论是从A上面写还是从B上写,都能够实现AB数据的一致性。
当有了两个主机之后,主机下挂的从机,就需要对两个主机进行同步,如果有4台主机A、B、C、D,其中AB互为主从,AC为主从,BD为主从,当在A上发生数据修改,则BC都能同步,但是D无法同步,因为D同步的是B的binlog,而B同步的是A的binlog,在B上面是relaylog,并没有写入到binlog中,所以D也就无法同步数据。就是因为这种情况,所以所有的从机,需要对所有的主机进行同步,也就是所谓的multi-source,实际上就是添加多个change master to ,结尾是for channel "",为这个master起一个名字,就好了。
CHANGE MASTER TO MASTER_HOST='192.168.64.132', MASTER_PORT=3307, MASTER_USER='replication', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysqlbin.000012', MASTER_LOG_POS=319 for channel 'mastera'; CHANGE MASTER TO MASTER_HOST='192.168.64.129', MASTER_PORT=3307, MASTER_USER='replication', MASTER_PASSWORD='123456', MASTER_LOG_FILE='mysqlbin.000015', MASTER_LOG_POS=2262 for channel 'masterb'; 在slave的配置文件中增加 master_info_repository=TABLE; relay_log_info_repository=TABLE; 或者在启动之后,设置全局系统变量 STOP SLAVE; SET GLOBAL master_info_repository = 'TABLE'; SET GLOBAL relay_log_info_repository = 'TABLE';
当实现了multi-source之后,就能够保证任何主节点的数据修改,都会同步到所有的从节点中。实现了数据的一致性。

浙公网安备 33010602011771号