6

Mysql主从、双主及主从同步1236错误

 10 months ago
source link: https://chegva.com/5767.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Mysql主从、双主及主从同步1236错误

最近迁机房,Mysql集群换到新环境出现主从不一致的情况,具体为1236报错,集群架构采用的是双主+keepalived高可用,测试了几种恢复的方法,记录一下。

Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Slave has more GTIDs than the master has, using the master's SERVER_UUID. This may indicate that the end of the binary log was truncated or that the last binary log file was lost, e.g., after a power or disk failure when sync_binlog != 1. The master may or may not have rolled back transactions that were already replica'
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'could not find next log; the first event '' at 4, the last event read from './slave-bin.000135' at 234, the last byte read from './slave-bin.000135' at 234.'

先回忆下Mysql主从同步:

Mysql主从、双主及主从同步1236错误

主从复制中分为「主服务器(master)「和」从服务器(slave)」「主服务器负责写,而从服务器负责读」,MySQL的主从复制的过程是一个「异步的过程」。这样读写分离的过程,能够使整体的服务性能大大提升,即使写操作时间比较长,也不影响读操作的进行。

MySQL的主从复制中主要有三个线程:master(binlog dump thread)、slave(I/O thread 、SQL thread,Master一条线程和Slave中的两条线程。

主从复制大致步骤如下:

在从库上执行 change master to,将主库的信息保存到从库中的 master.info 文件中,再执行 start slave,开启 I/O ThreadSQL Thread,主从复制开始

1. I/O Thread 通过 master.info 文件中主库的连接信息去连接主库,连接成功后主库就会开启 Dump Thread

2. Dump Thread 读取主库新产生的二进制日志,然后投递给 I/O Thread

3. I/O Thread 接收 Dump Thread 投递的新的二进制日志,将日志写入到中继日志 relay log 中,I/O Thread 就会等待主库 Dump Thread 主动把新产生的二进制日志投递

4. SQL Thread 会将 relay log 新产生的日志恢复到数据库,写到磁盘

Mysql < 5.7 dump_thread 读binlog与主库写binlog是串行的操作,5.7+ dump_thread读与写binlog是并行的,主从延迟高可以配置并行复制和增强半同步复制

MySQL半同步复制是介于异步和全同步之间,主库只需要等待至少一个从节点,收到并且flush binlog到relay log文件即可。主库不需要等待所有从库给主库反馈,主库只需要收到任意一个从库反馈,而且并不是从库已经完成并提交的反馈,而是从库只用完成io_thread内容即可反馈,无需等到sql_thread的执行完成。

Mysql主从、双主及主从同步1236错误

图片来源

常用命令:

start slave; #开启io_thread和sql_thread

start slave io_thread;

start slave sql_thread;

stop slave; #关闭io_thread和sql_thread

stop slave io_thread;

stop slave sql_thread;

reset slave; #删除master.info,relay-log.info数据;删除所有relay log;将延迟选项master_delay设为0

reset master; #删除所有二进制日志文件

show master status; #查看主库状态

show global variables like '%gtid%';

show binary logs;

show processlist;

show binlog events;

从库状态详解:

show slave status \G; #查看从库状态

mysql> SHOW SLAVE STATUS\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.16.11.22        #主库IP
                  Master_User: repl                #主库用户
                  Master_Port: 3306                #主库端口号
                Connect_Retry: 60
              Master_Log_File: master-bin.000002   #当前从库io_thread正在读取主库的二进制日志文件
          Read_Master_Log_Pos: 775058446           #当前从库io_thread正在读取主库二进制文件的位置
               Relay_Log_File: relay.000004        #当前从库sql_thread正在读取从库的中继日志文件
                Relay_Log_Pos: 407                 #当前sql_thread正在读取从库中继日志文件的位置
        Relay_Master_Log_File: master-bin.000002   #当前从库sql_thread从relay log中读取的正在进行的sql语句,对应主库的sql语句是在哪个binlog中
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 0
                   Last_Error: 
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 775058446           #从库sql_thread当前执行的事件,对应主库的binlog中的position
              Relay_Log_Space: 691
              Until_Condition: None
               Until_Log_File: 
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File: 
           Master_SSL_CA_Path: 
              Master_SSL_Cert: 
            Master_SSL_Cipher: 
               Master_SSL_Key: 
        Seconds_Behind_Master: 0                   #主从复制延迟的时间(s),如果是0表示主从无延迟
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0                   #最后一次IO线程错误信息
                Last_IO_Error: 
               Last_SQL_Errno: 0                   #最后一次SQL线程错误信息
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 2
                  Master_UUID: a67d2e10-b10c-11ed-948f-fa163e521e8a
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0                   #延迟复制
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind: 
      Last_IO_Error_Timestamp: 
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: a67d2e10-b10c-11ed-948f-fa163e521e8a:6-11        #当前io_thread已经接受到的binlog
            Executed_Gtid_Set: a66803a8-b10c-11ed-be14-fa163e8dddf7:1-2410271,  #当前从库sql_thread执行的二进制日志位置
a67d2e10-b10c-11ed-948f-fa163e521e8a:6-11
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)

主从搭建详见:


双主搭建:

Mysql主从、双主及主从同步1236错误

图片来源

1.双主Master ⇌ Standby,my.cnf配置文件中 server-id 设置要不同,配置上log_slave_updates

2.auto_increment_offset、auto_increment_increment差开,防止两个节点双写时出现主键冲突。

  • auto_increment_offset 自增字段起始值,设置为 2 表示自增字段从 2 开始算

  • auto_increment_increment 自增字段步增数值,设置为 2 表示每次递增 2,根据主节点设置,自增字段的值可能是这样的: 1,3,5,7...

  • log_slave_updates 将复制事件写入 binlog, 一台服务器既做主库又做从库此选项必须要开启, 这里在 Master 和 Standby 开启

从库开启log-bin参数,如果直接往从库写数据,是可以记录log-bin日志的,但是从库通过I0线程读取主库二进制日志文件,然后通过SQL线程写入的数据,是不会记录binlog日志的。也就是说从库从主库上复制的数据,是不写入从库的binlog日志的。所以从库做为其他从库的主库时需要在配置文件中添加log-slave-updates参数。

双主配置参考:

1236报错修复测试结果:

1.standby执行reset slave,master上没有执行reset slave
主从同步不报错,master同步到standby没有问题,standby写入有时不会同步到master,两边数据会有可能造成不一致
stop slave;
CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001',MASTER_LOG_POS=34978,master_auto_position=0;
start slave;

2.standby和master都执行reset slave
master,standby两边写入都能正常同步,两边写入数据没有看到不一致的情况
stop slave;
reset slave;
CHANGE MASTER TO MASTER_LOG_FILE='slave-bin.000001',MASTER_LOG_POS=126974,master_auto_position=0;
start slave;

3.standby执行reset slave & reset master(这种情况是从库的binlog已经无效了,所以要执行这个命令清空binlog,在从库执行), master 执行reset slave
master,standby两边写入都能正常同步,两边写入数据没有看到不一致的情况

4.standby和master都执行reset slave & reset master,再change master(危险操作,线上慎用可能丢数据)
master,standby两边写入都能正常同步,两边写入数据没有看到不一致的情况

生产建议:

1. 备节点最好动态设置只读(set global read_only = 0|1,主节点 read_only=0,备节点 read_only=1),Keepalived设置为非抢占模式,切换时,备节点要等待主节点同步完成。

2. 迁移时停服务最好是先停Standby,再停Master;启动先启Master,再启Standby。

测试数据:

Master执行:
create database mytest;
use mytest;
CREATE TABLE `test1` (
  `id` int(10) NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `name` varchar(125) NOT NULL,
  `age` int(3) DEFAULT NULL
);

insert into test1 values (0, 'a', 16);
insert into test1 values (0, 'b', 24);
insert into test1 values (0, 'c', 18);

mysql> SHOW TABLES;
+------------------+
| Tables_in_mytest |
+------------------+
| test1            |
+------------------+
1 row in set (0.00 sec)

mysql> insert into test1 values (0, 'a', 16);
Query OK, 1 row affected (0.02 sec)

mysql> insert into test1 values (0, 'b', 24);
Query OK, 1 row affected (0.01 sec)

mysql> insert into test1 values (0, 'c', 18);
Query OK, 1 row affected (0.01 sec)

mysql> select * from test1;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | a    |   16 |
|  3 | b    |   24 |
|  5 | c    |   18 |
+----+------+------+
3 rows in set (0.00 sec)

Standby执行:
insert into test1 values (0, 'e', 16);
insert into test1 values (0, 'f', 24);
insert into test1 values (0, 'g', 18);

mysql> select * from test1;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | a    |   16 |
|  3 | b    |   24 |
|  5 | c    |   18 |
+----+------+------+
3 rows in set (0.01 sec)


mysql> insert into test1 values (0, 'e', 16);
Query OK, 1 row affected (0.01 sec)

mysql> insert into test1 values (0, 'f', 24);
Query OK, 1 row affected (0.02 sec)

mysql> insert into test1 values (0, 'g', 18);
Query OK, 1 row affected (0.01 sec)

mysql> select * from test1;
+----+------+------+
| id | name | age  |
+----+------+------+
|  1 | a    |   16 |
|  3 | b    |   24 |
|  5 | c    |   18 |
|  6 | e    |   16 |
|  8 | f    |   24 |
| 10 | g    |   18 |
+----+------+------+
6 rows in set (0.00 sec)
安志合个人博客,版权所有 丨 如未注明,均为原创 丨 转载请注明转自:https://chegva.com/5767.html | ☆★★每天进步一点点,加油!★★☆ | 

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK