Haohao Notes

DREAM OF TECHNICAL ACHIEVEMENT

0%

MySQL主从复制

复制概述

MySQL中的主从复制是将数据从一端(通常称为Master,即主库)复制到另一端(通常称为Slave,即从库).

MySQL的复制特性操作很灵活,即可以实现整个服务级别的复制,也可以只复制某一个数据库,甚至某个数据库中的某个表对象;

  • 主从单向复制(即可以实现从A复制到B)
  • 单主多从复制(B在复制到C,也可以实现A直接复制到B和C)
  • 双主复制(甚至是A的数据复制给B,B的数据也复制回A)

一主多从架构与双主双从架构

服务器间复制数据有很多种解决方案,究竟哪种方案最适合,取决于使用的数据引擎和期望实现的复制需求.一般来说,可以将MySQL的复制特性应用在下来场景上:

  • 实时灾备,用于故障切换
  • 读写分离,提供查询服务
  • 备份
  • 延时库

搭建环境

由于MySQL安装方式 网上很多教程 这里就不重复写了

  • 运行环境 CentOS 7.5
  • 数据库环境 MySQL 5.7.30

1. Master端启用二进制日志(binlog),指定mysql服务全局唯一server_id

1
2
3
4
5
[mysqld]
## 设置server_id,注意要唯一
server-id=1
## 开启二进制日志功能
log-bin=mysql-bin

2. Slave端启用二进制日志(binlog),指定mysql服务全局唯一server_id,指定中继日志文件路径

1
2
3
4
5
6
7
[mysqld]
## 设置server_id,注意要唯一
server-id=2
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave-bin
## relay_log配置中继日志
relay_log=edu-mysql-relay-bin

3. 创建Slave同步专用账户

在Master数据库创建数据同步用户,授予用户 slave REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据。

1
2
CREATE USER 'slave'@'%' IDENTIFIED BY 'root';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

4. 链接Master(主)和Slave(从)

在Master进入mysql,执行show master status;

Master Status

File和Position字段的值后面将会用到,在后面的操作完成之前,需要保证Master库不能做任何操作,否则将会引起状态变化,File和Position字段的值变化。

在Slave中进入mysql,执行

1
change master to master_host='172.17.0.2', master_user='slave', master_password='root', master_port=3306, master_log_file='mysql-bin.000003', master_log_pos= 804, master_connect_retry=30;

命令说明:

  • master_host:Master MySQL的地址,如果用Docker指的是容器的独立ip,可以通过docker inspect --format='{ {.NetworkSettings.IPAddress}}' 容器名称|容器id查询容器的ip
  • master_port:Master的端口号,指的是容器的端口号
  • master_user:用于数据同步的用户
  • master_password:用于同步的用户的密码
  • master_log_file:指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
  • master_log_pos:从哪个 Position 开始读,即上文中提到的 Position 字段的值
  • master_connect_retry:如果连接失败,重试的时间间隔,单位是秒,默认是60秒

在Slave 中的mysql终端执行show slave status \G;用于查看主从同步状态。

Slave未同步状态
正常情况下,SlaveIORunning 和 SlaveSQLRunning 都是No,因为我们还没有开启主从复制过程。使用start slave开启主从复制过程,然后再次查询主从同步状态show slave status \G;
Slave同步状态
SlaveIORunning 和 SlaveSQLRunning 都是Yes,说明主从复制已经开启。此时可以测试数据同步是否成功。

我们再看一下线程:
Master进程
Slave进程

5. 排错

使用start slave开启主从复制过程后,如果SlaveIORunning一直是Connecting,则说明主从复制一直处于连接状态,这种情况一般是下面几种原因造成的,我们可以根据 Last_IO_Error提示予以排除。

  1. 网络不通 检查ip,端口
  2. 密码不对 检查是否创建用于同步的用户和用户密码是否正确
  3. pos不对 检查Master的 Position

6. 测试主从复制

测试主从复制方式就十分多了,最简单的是在Master创建一个数据库,然后检查Slave是否存在此数据库。

Master:

Master

Slave:

Slave

命令

  • show processlist;–显示用户正在运行的线程
  • show slave status;–显示slave状态
  • show slave hosts;–显示slave地址信息
  • start slave;–开始slave同步
  • stop slave;–停止slave同步
  • start slave io_thread;–开始slave io线程
  • start slave sql_thrad;–开始slave sql线程
  • stop slave io_thread;–停止slave io线程
  • stop slave sql_thrad;–停止slave sql线程

复制关键因素及原理

复制格式

复制格式和二进制日志格式本质上是一个东西,只是在不同场景下称谓不同,都由系统变量binlog_format控制.

二进制日志格式:

  1. 基于语句记录(Statement-Based Logging, SBL),对应的参数值为statement.二进制日志文件中保存的是执行过的SQL语句.
  2. 基于行格式记录(Row-Based Loging, RBL),对应的参数值为row.二进制日志文件中记录的是变更行的信息.
  3. 混合模式(Mixed-Based Loging. MBL),对应的参数值为mixed.在记录事件到二进制日志时,MySQL服务根据需要,动态修改日志记录的格式.

复制格式:

  1. 基于语句复制(Statement-Based Replication, SBR)
  2. 基于行复制(Row-Based Replication, RBR)
  3. 混合记录模式(Mixed-Based Replication. MBR)

SBR优点:

  1. 生成日志少.
  2. 可读性高 mysqlbinlog.
    SBR缺点:
  3. 不严谨,如SQL语句包含new()等函数 复制到从库就会出现时间不一致.
  4. 执行insert select 语句时需要持有更多的锁(相比RBR)锁多相当于并发性低.
  5. 对于InnoDB引擎,insert语句使用AUTO_INCREMENT会阻塞其他insert语句.

RBR优点:

  1. 所有修改都能被安全的复制到Slave节点.
  2. Master端执行修改操作时,仅需要极少的锁,可以获得更高的并发性.
  3. Slave节点执行增删改时也仅需要有少量锁.
    RBR缺点:
  4. 可能会生成更多的日志.
  5. 日志可读性减低 mysqlbinlog.
  6. 对于非事务存储引擎,比如MyISAM表对象,Slave节点应用insert操作时,使用RBR模式要比使用SBR模式持有更强的锁

场景1:

有条复杂的SQL语句,在Master节点执行10分钟,最终成功修改了1一条记录.

  • 采用SBR模式,二进制日志中记录的事件就是这条SQL语句,那么,这个记录被复制到Slave节点后,也要执行10分钟.
  • 采用RBR模式,不管Master节点执行了多长时间,最终变更记录只有一条,那么二进制日志中记录的事件就这一条记录的更新,日志被同步到Slave节点后,瞬间就会被执行完.

场景2:

有一条简单的SQL语句,在Master节点执行时,要更新一千万条记录.

  • 采用RBR模式,这一千万条记录会生成较大的二进制日志文件,数据在网络传输过程就要消耗一定时间,Slave接收完数据,还要花费相当长的时间慢慢应用到库中.
  • 采用SBR模式,二进制日志文件中就记录了该SQL语句,Slave节点可以迅速接收改语句,然后再执行,执行可能消耗一定时间,单总体时间开销还是要比RBR小.

看完上面两个场景,相信读者已经有自己的选择了.但是在生成环境中强烈建议使用RBR模式(基于行复制),因为稳定.稳定压倒一切

查看binlog格式show variables like "binlog_format"

1
2
3
4
5
6
7
mysql> show variables like "binlog_format";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)

中继日志文件和状态文件

MySQL数据中有二进制日志文件,用于记录所有执行的变更事件,复制特性正是基于这类文件实现”复制”操作.Slaves节点中有两个线程,其中IO_THREAD线程用于接收和保存二进制日志,IO_THREAD将接收二进制日志就保存在本端的中继日志中.

通过show variables like "%relay%";查看中继日志文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mysql> show variables like "%relay%";
+---------------------------+------------------------------------------+
| Variable_name | Value |
+---------------------------+------------------------------------------+
| max_relay_log_size | 0 |
| relay_log | edu-mysql-relay-bin |
| relay_log_basename | /var/lib/mysql/edu-mysql-relay-bin |
| relay_log_index | /var/lib/mysql/edu-mysql-relay-bin.index |
| relay_log_info_file | relay-log.info |
| relay_log_info_repository | FILE |
| relay_log_purge | ON |
| relay_log_recovery | OFF |
| relay_log_space_limit | 0 |
| sync_relay_log | 10000 |
| sync_relay_log_info | 10000 |
+---------------------------+------------------------------------------+
11 rows in set (0.01 sec)
  • relay_log_index 中继日志索引文件
  • relay_log_basename 中继日志文件保存路径
  • relay_log_info_file 中继日志状态
  • max_relay_log_size 中继日志最大值

中继日志和binlog日志相同可以mysqlbinlog操作

Slaves节点会在瞒足下列条件时,触发创建新的中继日志文件:

  1. 启动Slaves节点IO线程时
  2. 执行日志刷新命令 flush logs
  3. 中继日志文件达到指定最大值时
    • 如果max_relay_log_size参数值大于0,则日志文件超过该值后即会重建
    • 如果max_relay_log_size参数值等于0,则通过max_binlog_size确定单个中继日志文件最大值

通过show variables like "max_binlog_size";查看binlog文件最大值

1
2
3
4
5
6
7
mysql> show variables like "max_binlog_size"; 
+-----------------+------------+
| Variable_name | Value |
+-----------------+------------+
| max_binlog_size | 1073741824 |
+-----------------+------------+
1 row in set (0.00 sec)

状态文件:
复制环境中Slave节点会创建两个状态文件:既master.info和relay-log.info,这两个文件默认保存在data目录,可以通过–master-info-file和–relay-log-info-file参数修改文件和保存路径.

master.info和relay-log.info均来自show slave status里面的信息刷新到这些文件中.

  • IO_THREAD会读取master.info信息
  • SQL_THREAD会读取relay-log.info信息

复制原理

复制原理

高级应用技巧

复制过滤规则

Master端:

  • binlog-do-db 指定对某数据库的操作事件被记录.
  • binlog-ignore-db 指定对某数据库的操作事件不被记录
  • set sql_log_bin=0 会话级别所做操作不被记录

在Master端进行复制过滤会导致主服务器上的二进制日志记录不完整,一旦主服务器崩溃将无法做到还原所有数据

Slave端:

Slave节点在接收日志时没有选择权,Master节点写过的日志它全部接收到本地,保存在中继日志文件中.但Slave节点在应用哪些数据库哪些表时具有选择器权限.MySQL提供了一系列参数用于Slave节点定义过滤规则.

  • replicate-do-db=name 执行name表
  • replicate-ignore-db=name 忽略name表
  • replicate-do-table=name 执行name库
  • replicate-ignore-table=name 忽略name库
  • replicate-wild-do-table=foo%.bar% 执行以foo开头的库以bar开头的表
  • replicate-wild-ignore-table=foo%.bar% 忽略以foo开头的库以bar开头的表

配置方式

配置文件

按照上面列的replicate-do-db=表名即可

数据库配置

指定复制某一个或多个库

1
2
3
STOP SLAVE SQL_THREAD; # 停止SQL线程
CHANGE REPLICATION FILTER REPLICATE_DO_BD = (表名1,表名2)
START SLAVE SQL_THREAD; # 启动SQL线程

通过上面设置方式可以看出 CHANGE REPLICATION FILTER 加上上面列的选项即可实现配置

取消复制限制

CHANGE REPLICATION FILTER REPLICATE_DO_BD = ();同上

切记一定要停止SQL线程后再设置

半同步机制

简介

MySQL在5.5版本之前,一直采用的是异步复制的方式.主库的事务执行不会管备库的同步进度,如果备库落后,主库不幸crash,那么就会导致数据丢失.

MySQL在5.5版本中引入了半同步复制,主库在答应客户端提交的事务钱需要保证至少一个从库收到并写到relay log中,但性能比较差.

MySQL在5.6版本中增强了半同步

MySQL在5.7版本比较完善(在5.7.2无损复制)

原理

默认情况下,MySQL的复制是异步的,主库执行完Commit提交操作后,在主库写入binlog后即可成功返回给客户端,无需等待binlog传给从库.当在主库上写入一个事务并提交成功,而从库尚未得到主库的binlog时,主机宕机了,从而从库可能损失该事务,造成主从库的不一致.

为了解决这个问题,MySQL引入了半同步复制.半同步复制保证了主库上的每一个binlog都能可靠的复制到从库上,主库在每次事务提交时,并不及时反馈给前端用户,而是等待其中一个从库也接收到binlog并成功写入中继日志后,主库才返回给客户端.此时,至少有两份日志记录,一份在主库binlog上,另一方在至少一个从库的中继日志上,从而保证了数据的完整性.

半同步复制机制的改进

MySQL 5.7.2版本增加了rpl_semi_sync_master_wait_point参数,该参数有两个值:AFTER_COMMITAFTER_SYNC.

AFTER_COMMIT 半同步复制(5.6默认该模式)

Master将每个事务写入binlog(sync_binlog=1),传递到slave刷新到磁盘(sysnc_relay=1),同时主库提交事务.Master等待Slave反馈收到relay_log,只有收到ACK后Master才将commit ok结果反馈给客户端.
After Commit

在使用AFTER_COMMIT的模式下,客户端事务在存储引擎成提交后,在得到从库确认的过程中,主库宕机了.此时,既主库在等待Slave ACK的时候,虽然没有返回当前客户端,但是事务已经提交,其他客户端会读取到已提交事务.如果Slave端还没有读取到该事务的events,同时主库发生了crash,然后切换到备库.那么之前读取到的事务就不见了,出现幻读.
出现幻读情况图

AFTER_SYNC 无损复制(5.7默认该模式,5.6没有该模式)

Master将每个事务写入binlog,传递到Slave刷新到磁盘(relay log).Master等待Slave反馈接收到relay log的ACK之后,再提交事务并且返回commit ok 结果给客户端.
After Sync

半同步复制与无损复制的对比

  1. ACK的时间点不同:
    • 一个先engine commit后再接收ACK
    • 一个在接收ACK后在engine commit
  2. 主从数据一致性
    • 半同步复制意味着在Master节点上,这个刚刚提交的事务对数据库的修改,对其他事务是可见的.因此,如果在等待Slave ACK的时候crash了,那么会对其他事务出现幻读,数据丢失.
    • 无损复制在write binlog完成后,就传输binlog,但还没有去写commit log,意味着当前这个事务对数据库的修改,其他事务也是不可以见的.因此,不会出现幻读,数据丢失的风险.

半同步配置

  • 查看MySQL系统版本 select version();

  • 查看安装插件列表 show plugins;

Master配置

  • 安装 install plugin rpl_semi_sync_master soname 'semisync_master.so';
    安装成功
  • 启动 set global rpl_semi_sync_master_enabled=on;
  • 查看 show variables like '%semi%';
    查看状态

    Slave配置

图和master配置基本一致 就不放图了

  • 安装 install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
  • 启动 set global rpl_semi_sync_slave_enabled=on;
  • 查看 show variables like '%semi%';
  • 重启 stop slave;start slave;

卸载插件

Slave卸载

  1. set global rpl_semi_sync_slave_enabled=off; 关闭同步插件
  2. stop slave; 停止Slave同步
  3. uninstall plugin rpl_semi_sync_slave; 卸载插件
  4. start slave; 启动

Master卸载

  1. set global rpl_semi_sync_master_enabled=off; 关闭同步插件
  2. uninstall plugin rpl_semi_sync_master; 卸载插件

关键参数说明

1
2
3
4
5
6
7
8
9
10
11
12
mysql> show variables like '%semi%';
+-------------------------------------------+------------+
| Variable_name | Value |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.00 sec)
  • rpl_semi_sync_master_enabled 设置为on表示开启了半同步功能
  • rpl_semi_sync_master_timeout 单位是毫秒,表示如果主库等待从库回复消息的时间超过该值,就会自动切换为异步复制模式
  • rpl_semi_sync_master_wait_no_slave 默认是on.表示Master每个事务提交后都要等待Slave的接收确认信号
  • rpl_semi_sync_master_wait_for_slave_count 它控制主库接收多少个从库写事务成功反馈,才返回成功给客户端
  • rpl_semi_sync_master_wait_point 默认值是AFTER_SYNC,含义是主库将每个事务写入binlog,并传递给从库,刷新到中继日志,主库开始等待从库的反馈,接收到从库的回复之后,在提交事务并且返回”commit ok”结果给客户端

set global rpl_semi_sunc_master_wait_point='AFTER_COMMIT'; 设置同步模式

手动主从切换

正常切换

  1. 对主库全库锁定 flush tables with read lock;
  2. 在Master执行 执行 show processlist;查看State是否是Master has sent all binlog to slave; waiting for more updates判断是否发送完毕
  3. 在Slave执行 执行 show processlist;查看State是否是Slave has read all relay log; waiting for more updates判断是否同步完成
  4. 停止Slave IO线程 stop slave io_thread;
  5. 将Slave提升为Master:
    • 停止Slave stop slave;
    • 删除所有的binlog日志文件,并将日志索引文件清空,重新开始所有新的日志文件.reset master;
    • 删除master.info文件和relay-log.info文件以及所有的relay log文件,并重新启用一个新的relay log文件.reset slave;
    • 相对于RESET SLAVE, RESET SLAVE ALL还会删除内存中的连接信息,包括slave账号信息 reset slave all;
  6. 查看Slave是否是只读模式:show variables like 'read_only';
    • 只读模式需要修改my.cnf文件,注释read-only=1并重启mysql服务.
    • 或者不重启使用命令关闭只读,但下次重启后失效:set global read_only=off;
  7. 将原来Master变为Slave
    • 在新的Master上创建同步用户CREATE USER 'slave'@'%' IDENTIFIED BY 'root';GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%'; flush privileges;
    • 将新的Slave设置为只读模式set global read_only=on;
    • 将新的Slave上释放全局锁unlock tables;
    • 在新的Slave上重置binlogreset master;
    • 在新的Slave上配置连接信息change master to master_host='172.17.0.2', master_user='slave', master_password='root', master_port=3306, master_log_file='mysql-bin.000003', master_log_pos= 804, master_connect_retry=30;
    • 在新的Slave上开启start slave;

主机宕机切换

  1. 停止slavestop slave;
  2. 删除所有的binlog日志文件,并将日志索引文件清空,重新开始所有新的日志文件.reset master;
  3. 删除内存中的连接信息,包括slave账号信息 reset slave all;
  4. 查看Slave是否是只读模式:show variables like 'read_only';
    • 只读模式需要修改my.cnf文件,注释read-only=1并重启mysql服务.
    • 或者不重启使用命令关闭只读,但下次重启后失效:set global read_only=off;
  5. 查看新主机状态show master status;
  6. 修改中间件的IP

主从延时分析及解决

在master上删除一条记录,而slave上找不到.

模拟故障场景:

主库:

1
2
3
4
5
6
#建表
CREATE TABLE t_dell (
id INT NOT NULL auto_increment PRIMARY KEY,
c1 VARCHAR ( 20 ));
#插入一条数据
INSERT INTO t_dell ( c1 ) VALUES ( 'a' );

从库:

DELETE FROM t_dell;

主库:

DELETE FROM t_dell;

接下来我们查看一下Slave的状态;show slave status \G;
错误图例1

1
2
Last_Errno: 1032
Last_Error: Could not execute Delete_rows event on table test.t_dell; Can't find record in 't_dell', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-slave-bin.000003, end_log_pos 1854

通过上图我们可以看到 SQL线程已经停止,Last_Error已经出现报错提示.

解决方案:

由于master 要删除一条记录,而slave上找不到故此报错,这种情况主上都将其删除了,那么从库可以直接跳过.

操作命令:

1
2
3
stop slave;
set global sql_slave_skip_counter=1;
start slave;

或者

slave-skip-errors = 1032;#在MySql配置文件中配置,一旦出现1032错误直接跳过,需要重启服务.

然后在查看同步状态就正常了.show slave status \G;

主键重复,在slave已经有该记录,又在master上插入了同一条记录.

模拟故障场景:

主库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 建表
CREATE TABLE t_key (
id INT NOT NULL PRIMARY KEY,
c1 VARCHAR ( 20 ));
# 插入一条数据
INSERT INTO t_key(id,c1) VALUES (1,'a');
# 设置以下操作事件不会被写入binlog
set sql_log_bin=0;
# 删除表
delete from t_key;
# 开启操作事件写入binlog
set sql_log_bin=1;
# 插入一条数据
INSERT INTO t_key(id,c1) VALUES (1,'a');

从库:

show slave status \G;

错误状态2

1
2
Last_Errno: 1062
Last_Error: Could not execute Write_rows event on table test.t_key; Duplicate entry '1' for key 'PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-slave-bin.000003, end_log_pos 2583

解决方法:

登录到从库,删除重复数据

1
2
3
stop slave;
delete from t_key where id=1;
start slave;

在master上更新条记录,而slave上找不到,丢失了数据.

模拟故障场景:

主库:

1
2
3
4
5
6
7
8
9
# 建表
CREATE TABLE t_upd (
id INT NOT NULL PRIMARY KEY,
c1 VARCHAR ( 20 ),
c2 VARCHAR ( 20 ));
# 插入两条数据
INSERT INTO t_upd ( id, c1, c2 ) VALUES
( 1, 'a1', 'a2' ),
( 2, 'b1', 'b2' );

从库:

DELETE FROM t_upd WHERE id = 1;

主库:

UPDATE t_upd SET c1 = 'aa' WHERE id = 1;
错误状态3

1
2
Last_Errno: 1032
Last_Error: Could not execute Update_rows event on table test.t_upd; Can't find record in 't_upd', Error_code: 1032; handler error HA_ERR_KEY_NOT_FOUND; the event's master log mysql-slave-bin.000003, end_log_pos 3368

解决方法:

在master上,用mysqlbinlog分析下出错的binlog日志在3368行是什么语句?

mysqlbinlog --no-defaults --base64-output=DECODE-ROWS -v -v mysql-slave-bin.000003 | grep -A 20 'end_log_pos 3368'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
root@c950e5d85a10:/var/lib/mysql# mysqlbinlog --no-defaults --base64-output=DECODE-ROWS -v -v mysql-slave-bin.000003 | grep -A 20 'end_log_pos 3368'
#200610 5:53:43 server id 2 end_log_pos 3368 CRC32 0x10aef7b4 Update_rows: table id 120 flags: STMT_END_F
### UPDATE `test`.`t_upd`
### WHERE
### @1=1 /* INT meta=0 nullable=0 is_null=0 */
### @2='a1' /* VARSTRING(80) meta=80 nullable=1 is_null=0 */
### @3='a2' /* VARSTRING(80) meta=80 nullable=1 is_null=0 */
### SET
### @1=1 /* INT meta=0 nullable=0 is_null=0 */
### @2='aa' /* VARSTRING(80) meta=80 nullable=1 is_null=0 */
### @3='a2' /* VARSTRING(80) meta=80 nullable=1 is_null=0 */
# at 3368
#200610 5:53:43 server id 2 end_log_pos 3399 CRC32 0xffe1af2f Xid = 215
COMMIT/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

通过binlog日志可以看出来正在执行update语句,然后我们在slave插入缺失的数据

1
2
3
stop slave;
INSERT INTO t_upd(id,c1,c2) VALUES (1,'aa','a2');
start slave;

slave的中继日志relay-bin损坏

模拟故障场景:

从库:
停止sql线程stop slave sql_thread;
主库:

1
2
flush logs;
INSERT INTO t_key(id,c1) VALUES (1,'a');

从库:
删除中继日志,模拟中继日志损坏.
start slave sql_thread;

错误状态4

1
2
Last_Errno: 1593
Last_Error: Error initializing relay log position: Could not open log file

解决方法:

确认同步的binlog和pos点:

  • Slave_IO_Running 接收Master的binlog信息
  • Master_Log_File / Read_Master_Log_Pos 显示当前读取的Master节点binlog文件和位置.

  • Slave_SQL_Running 执行写操作

  • Relay_Log_File / Relay_Log_Pos 显示当前节点Slave节点正在处理的中继日志文件和位置.
  • Relay_Master_Log_File / Exec_Master_Log_Pos 显示当前Slave节点正在处理的中继日志文件和位置

重新同步:

1
2
3
4
5
stop slave
# 重新通过Master_Log_File文件信息,在Exec_Master_Log_Pos节点处开始生成中继日志文件
CHANGE MASTER TO master_log_file = 'mysql-slave-bin.000003',
Master_log_pos = 3399;
start slave;

参考资料

http://my-replication-life.blogspot.com/2013/09/loss-less-semi-synchronous-replication.html