mysql高可用架构

Posted on By xqw

主从同步流程

依赖binlog,binlog可以用来归档,也可以用来做主备同步

可以看到:主库接收到客户端的更新请求后,执行内部事务的更新逻辑,同时写binlog。

备库B跟主库A之间维持了一个长连接。主库A内部有一个线程,专门用于服务备库B的这个长连接。一个事务日志同步的完整过程是这样的:

  1. 在备库B上通过change master命令,设置主库A的IP、端口、用户名、密码,以及要从哪个位置开始请求binlog,这个位置包含文件名和日志偏移量。

  2. 在备库B上执行start slave命令,这时候备库会启动两个线程,就是图中的io_thread和sql_thread。其中io_thread负责与主库建立连接。

  3. 主库A校验完用户名、密码后,开始按照备库B传过来的位置,从本地读取binlog,发给B。

4.备库B拿到binlog后,写到本地文件,称为中转日志(relay log)。

5.sql_thread读取中转日志,解析出日志里的命令,并执行(执行后会生成自己的binlog)。

循环复制问题:log_slave_updates设置为on后,表示备库执行relay log后生成binlog(建议开启), 那么会产生日志循环执行的问题,mysql只需配置不同的server_id即可,表示生成binlog的server_id

同步复制、异步复制、半同步复制(只等一台从库写入就响应)

binlog格式

statement、rows、mixed

# t表上a、b都是辅助索引
insert into t(a,b) values(4,'2018-11-10');
insert into t(a,b) values(5,'2018-11-09');

# 执行下面语句,选择不同索引,删除的行就不同:
delete from t where a>=4 and t_modified<='2018-11-10' limit 1;

statement格式:

第一行SET @@SESSION.GTID_NEXT=’ANONYMOUS’你可以先忽略,后面文章我们会在介绍主备切换的时候再提到;

第二行是一个BEGIN,跟第四行的commit对应,表示中间是一个事务;

第三行就是真实执行的语句了。可以看到,在真实执行的delete命令之前,还有一个“use ‘test’”命令。这条命令不是我们主动执行的,而是MySQL根据当前要操作的表所在的数据库,自行添加的。这样做可以保证日志传到备库去执行的时候,不论当前的工作线程在哪个库里,都能够正确地更新到test库的表t。 use ‘test’命令之后的delete 语句,就是我们输入的SQL原文了。可以看到,binlog“忠实”地记录了SQL命令,甚至连注释也一并记录了。 最后一行是一个COMMIT。你可以看到里面写着xid=61。

row格式:

开始位置未8900: mysqlbinlog -vv data/master.000001 --start-position=8900; 记录了删除前数据、删除id是什么;

若有恢复数据的需求,则开启row; 即执行的是delete语句,row格式的binlog也会把被删掉的行的整行信息保存起来。所以,如果你在执行完一条delete语句以后,发现删错数据了,可以直接把binlog中记录的delete语句转成insert,把被错删的数据插入回去就可以恢复了。

如果你是执行错了insert语句呢?那就更直接了。row格式下,insert语句的binlog里会记录所有的字段信息,这些信息可以用来精确定位刚刚被插入的那一行。这时,你直接把insert语句转成delete语句,删除掉这被误插入的一行数据就可以了。

如果执行的是update语句的话,binlog里面会记录修改前整行的数据和修改后的整行数据。所以,如果你误执行了update语句的话,只需要把这个event前后的两行信息对调一下,再去数据库里面执行,就能恢复这个更新操作了。

其实,由delete、insert或者update语句导致的数据操作错误,需要恢复到操作之前状态的情况,也时有发生。MariaDB的Flashback工具就是基于上面介绍的原理来回滚数据的。

mix格式:

两种方式的混合,mysql判断出哪些语句会导致不同结果,则使用row模式