导语
大家知道binlog可以用来归档,也可以用来做主备同步,但它的内容是什么样的呢?为什么备库执行了binlog就可以跟主库保持一致了呢?我下面的内容就是针对这个问题。
MySQL主备的基本原理
在状态1中,客户端的读写都直接访问节点A,而节点B是A的备库,只是将A的更新都同步过来,到本地执行。这样可以保持节点B和A的数据是相同的。当需要切换的时候,就切成状态2。这时候客户端读写访问的都是节点B,而节点A是B的备库。
**注意:节点B(也就是备库)设置成只读(readonly)模式。**主要有以下几个原因:
- 节点B(也就是备库)设置成只读(readonly)模式;
- 防止切换逻辑有bug,比如切换过程中出现双写,造成主备不一致;
- 可以用readonly状态,来判断节点的角色。
内部执行流程
备库B跟主库A之间维持了一个长连接。主库A内部有一个线程,专门用于服务备库B的这个长连接。一个事务日志同步的完整过程是这样的:
-
在备库B上通过change master命令,设置主库A的IP、端口、用户名、密码,以及要从哪个位置开始请求bin log,这个位置包含文件名和日志偏移量。
-
在备库B上执行start slave命令,这时候备库会启动两个线程,就是图中的io_thread和sql_thread。其中io_thread负责与主库建立连接。
-
主库A校验完用户名、密码后,开始按照备库B传过来的位置,从本地读取bin log,发给B。
-
备库B拿到bin log后,写到本地文件,称为中转日志(relay log)。
-
sql_thread读取中转日志,解析出日志里的命令,并执行。
binlog的三种格式
- statement :SQL语句的原文,可能会有主备不一致性问题,但是占用内存小。
- row :两个event:Table_map 和 Delete_rows。Table_map event,用于说明接下来要操作的表是xx库的表xx;Delete_rows event,用于定义增删改查的行为。bin log里面记录了真实操作行的主键id。不会有主备不一致性问题,但是占用空间很大。
- mixed:mixed格式可以利用statment格式的优点,同时又避免了数据不一致的风险。
这里我建议;MySQL的bin log格式设置成row。
binlog恢复数据
用 mysqlbinlog工具解析出来,然后把解析结果整个发给MySQL执行。类似下面的命令:
mysqlbinlog master.000001 --start-position=2738 --stop-position=2973 | mysql -h127.0.0.1 -P13000 -u$user -p$pwd;
这个命令的意思是,将 master.000001 文件里面从第2738字节到第2973字节中间这段内容解析出来,放到MySQL去执行。