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

可以看到:主库接收到客户端的更新请求后,执行内部事务的更新逻辑,同时写binlog。
备库B跟主库A之间维持了一个长连接。主库A内部有一个线程,专门用于服务备库B的这个长连接。一个事务日志同步的完整过程是这样的:
-
在备库B上通过change master命令,设置主库A的IP、端口、用户名、密码,以及要从哪个位置开始请求binlog,这个位置包含文件名和日志偏移量。
-
在备库B上执行start slave命令,这时候备库会启动两个线程,就是图中的io_thread和sql_thread。其中io_thread负责与主库建立连接。
-
主库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模式