目前MySQL主从还是主流架构,当主库出问题了,从库应该怎么办?
一、MySQL主从原理

A B
1.在备库B上通过 change master 命令,设置主库 A 的 IP、端口、用户名、密码,以及要从哪个位置开始请求 binlog,这个位置包含文件名和日志偏移量。
2.在备库 B 上执行 start slave 命令,这时候备库会启动两个线程,就是图中的 io_thread 和 sql_thread。其中 io_thread 负责与主库建立连接。
3.主库 A 校验完用户名、密码后,开始按照备库 B 传过来的位置,从本地读取 binlog,发给 B。
备库 B 拿到 binlog 后,写到本地文件,称为中转日志(relay log)。
4.sql_thread 读取中转日志,解析出日志里的命令,并执行。(5.6版本之后引入多线程方案)
二、主库出问题了,从库怎么办?

主从切换?
图中A和A’互为主备,B,C,D分别为A的备库,当主库A故障时,A’将变为主库,BCD也分别切换指向A’。
三、主从切换方式
1.基于主库位点切换(异步复制)
如果把B设置为A的主库,相应需要设置如下:6个参数
CHANGE MASTER TO
MASTER_HOST=$host_name
MASTER_PORT=$port
MASTER_USER=$user_name
MASTER_PASSWORD=$password
MASTER_LOG_FILE=$master_log_name
MASTER_LOG_POS=$master_log_pos
最后两个参数 MASTER_LOG_FILE 和 MASTER_LOG_POS 表示,要从主库的 master_log_name 文件的 master_log_pos 这个位置的日志继续同步。而这个位置就是我们所说的同步位点,也就是主库对应的文件名和日志偏移量。异步复制基本无法精确的找到位置,只能取大概的位置。
常见的取位点做法:
等待新主库 A’把中转日志(relay log)全部同步完成;在 A’上执行 show master status 命令,得到当前 A’上最新的 File 和 Position;取原主库 A 故障的时刻 T;用 mysqlbinlog 工具解析 A’的 File,得到 T 时刻的位点。
然而异步复制主从切换,取到的位点经常有问题,常见的切换后的错误:主键冲突(取的位点靠前)
Duplicate entry ‘id_of_R’ for key ‘PRIMARY’,同步停止。这时候怎么办呢。
悲观的解决:跳过错误
set global sql_slave_skip_counter=1;
start slave;
另一种更暴力:通过设置 slave_skip_errors 参数,直接设置跳过指定的错误。在执行主备切换时,有这么两类错误,是经常会遇到的:
1062 错误是插入数据时唯一键冲突;
1032 错误是删除数据时找不到行。
因此,我们可以把 slave_skip_errors 设置为 “1032,1062”,这样中间碰到这两个错误时就直接跳过。
这种方式是不是太粗糙了。
2.GTID模式
上面的找位点的坑怎么办?
MySQL 5.6 版本引入了 GTID,彻底解决了异步复制找位点的难题。
启用GTID:加入两个参数
gtid_mode=on
enforce_gtid_consistency=on
基于GTID切换(GTID内容后续在深入说明)
GTID模式下,备库 B 要设置为新主库 A’的从库的语法如下:
CHANGE MASTER TO
MASTER_HOST=$host_name
MASTER_PORT=$port
MASTER_USER=$user_name
MASTER_PASSWORD=$password
master_auto_position=1 (词句代表使用GTID协议)
不需要找位点了,所以从库 B、C、D 只需要分别执行 change master 命令指向实例 A’即可。位点由MySQL内部自动找。
总结:传统的异步复制需要人工定位找主库位点,需要对应解析日志去判断故障点,很耗费时间,建议全部采用GTID模式,这样把内部找位点让MySQL去做,主从切换也非常方便。
思考:主从延时怎么办?




