美文网首页
MySQL主从复制探索与故障恢复(二)

MySQL主从复制探索与故障恢复(二)

作者: PurelightMe | 来源:发表于2020-11-21 22:50 被阅读0次

接上篇 MySQL主从复制探索与故障恢复(一)

从库执行写操作会发生什么?

先在 slave1 上执行:

insert into t1(name,age) values('slave1',10);

现在 slave1 上的 test01.t1 表数据是:

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |   20 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | slave1 |   10 |
+----+--------+------+
5 rows in set (0.01 sec)

然后,切到 master 执行 insert 语句:

insert into t1(name,age) values('master',40);

现在 master 上的 test01.t1 表数据是:

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |   20 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
+----+--------+------+
5 rows in set (0.00 sec)

首先看看 slave2 上的数据和同步状态:

数据和状态都正常,符合预期
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

再来看看有执行”写入“操作的slave1:

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |   20 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | slave1 |   10 |
+----+--------+------+
5 rows in set (0.00 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: master
                  Master_User: slave1
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 1128
               Relay_Log_File: ae6b5ad86c4d-relay-bin.000013
                Relay_Log_Pos: 458
        Relay_Master_Log_File: mysql-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 1062
                   Last_Error: Could not execute Write_rows event on table test01.t1; Duplicate entry '5' for key 't1.PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000004, end_log_pos 1097
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 830
              Relay_Log_Space: 1274
              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: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 1062
               Last_SQL_Error: Could not execute Write_rows event on table test01.t1; Duplicate entry '5' for key 't1.PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000004, end_log_pos 1097
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 100
                  Master_UUID: 2ea01898-2987-11eb-84e5-0242ac140002
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State:
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp: 201119 20:22:49
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: 2ea01898-2987-11eb-84e5-0242ac140002:1-15
            Executed_Gtid_Set: 2ea01898-2987-11eb-84e5-0242ac140002:1-14,
80ea294e-298b-11eb-af5c-0242ac140004:1-6
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 1
            Network_Namespace:
1 row in set, 1 warning (0.01 sec)

ERROR:
No query specified

mysql>

果然是出现了问题,id为5的主键已经存在,所以Slave_SQL_Running状态为No。

方案1

这时我们尝试手动删除刚刚插入的id为5的那条记录,然后重启复制:

mysql> delete from t1 where id = 5;
Query OK, 1 row affected (0.03 sec)

mysql> alter table t1 auto_increment = 5;
Query OK, 0 rows affected (0.16 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.03 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: master
                  Master_User: slave1
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 1128
               Relay_Log_File: ae6b5ad86c4d-relay-bin.000014
                Relay_Log_Pos: 458
        Relay_Master_Log_File: mysql-bin.000004
             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: 1128
              Relay_Log_Space: 1274
              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
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 100
                  Master_UUID: 2ea01898-2987-11eb-84e5-0242ac140002
             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: 2ea01898-2987-11eb-84e5-0242ac140002:1-15
            Executed_Gtid_Set: 2ea01898-2987-11eb-84e5-0242ac140002:1-15,
80ea294e-298b-11eb-af5c-0242ac140004:1-8
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 1
            Network_Namespace:
1 row in set, 1 warning (0.01 sec)

ERROR:
No query specified

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |   20 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
+----+--------+------+
5 rows in set (0.00 sec)

修复成功!

方案二

先在 slave1 上执行2条写入语句:

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |   20 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
+----+--------+------+
5 rows in set (0.01 sec)

mysql> update t1 set age = age + 1 where id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> insert into t1(name,age) values('yy',6);
Query OK, 1 row affected (0.01 sec)

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |   21 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
|  6 | yy     |    6 |
+----+--------+------+
6 rows in set (0.01 sec)

mysql>

再去 master 执行:

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |   20 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
+----+--------+------+
5 rows in set (0.00 sec)

mysql> update t1 set age = 100 where id = 1;
Query OK, 1 row affected (0.04 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> insert into t1(name,age) values('xx',19);
Query OK, 1 row affected (0.02 sec)

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |  100 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
|  6 | xx     |   19 |
+----+--------+------+
6 rows in set (0.00 sec)

mysql>

slave2 此时数据自然是:

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |  100 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
|  6 | xx     |   19 |
+----+--------+------+
6 rows in set (0.00 sec)

查看 slave1 状态:

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |  100 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
|  6 | yy     |    6 |
+----+--------+------+
6 rows in set (0.00 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: master
                  Master_User: slave1
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 1739
               Relay_Log_File: ae6b5ad86c4d-relay-bin.000014
                Relay_Log_Pos: 775
        Relay_Master_Log_File: mysql-bin.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 1062
                   Last_Error: Could not execute Write_rows event on table test01.t1; Duplicate entry '6' for key 't1.PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000004, end_log_pos 1708
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 1445
              Relay_Log_Space: 1885
              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: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 1062
               Last_SQL_Error: Could not execute Write_rows event on table test01.t1; Duplicate entry '6' for key 't1.PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000004, end_log_pos 1708
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 100
                  Master_UUID: 2ea01898-2987-11eb-84e5-0242ac140002
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State:
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp: 201122 22:05:36
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set: 2ea01898-2987-11eb-84e5-0242ac140002:1-17
            Executed_Gtid_Set: 2ea01898-2987-11eb-84e5-0242ac140002:1-16,
80ea294e-298b-11eb-af5c-0242ac140004:1-10
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 1
            Network_Namespace:
1 row in set, 1 warning (0.01 sec)

ERROR:
No query specified

mysql>

虽然 id 为6的数据插入不进去,但是 id 为1的 update 可以正常执行成功,这时候可以用 sql_slave_skip_counter 跳过事务,试试:

mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.01 sec)

mysql> set global sql_slave_skip_counter = 1;
ERROR 1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction

看来这个方法在 GTID 模式下不能用,好在提示了我们该怎么做,生成一个与要跳过的事务的GTID相同的空事务。怎么确定发生故障的那个事务的 GTID 是多少?

Last_Error: Could not execute Write_rows event on table test01.t1; Duplicate entry '6' for key 't1.PRIMARY', Error_code: 1062; handler error HA_ERR_FOUND_DUPP_KEY; the event's master log mysql-bin.000004, end_log_pos 1708

这里可以找到 master 的 binlog 相关信息,可以直接去 master 上面去找。

找到对应 GTID 为:2ea01898-2987-11eb-84e5-0242ac140002:17,开始跳过修复:

mysql> stop slave;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> set session gtid_next = '2ea01898-2987-11eb-84e5-0242ac140002:17';
Query OK, 0 rows affected (0.00 sec)

mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> set session gtid_next = AUTOMATIC;
Query OK, 0 rows affected (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected, 1 warning (0.02 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: master
                  Master_User: slave1
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000004
          Read_Master_Log_Pos: 1739
               Relay_Log_File: ae6b5ad86c4d-relay-bin.000015
                Relay_Log_Pos: 458
        Relay_Master_Log_File: mysql-bin.000004
             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: 1739
              Relay_Log_Space: 1587
              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
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 100
                  Master_UUID: 2ea01898-2987-11eb-84e5-0242ac140002
             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: 2ea01898-2987-11eb-84e5-0242ac140002:1-17
            Executed_Gtid_Set: 2ea01898-2987-11eb-84e5-0242ac140002:1-17,
80ea294e-298b-11eb-af5c-0242ac140004:1-10
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
       Master_public_key_path:
        Get_master_public_key: 1
            Network_Namespace:
1 row in set, 1 warning (0.01 sec)

ERROR:
No query specified

mysql>

然后再去 master 执行写入,看看 slave1 能否成功同步过来:

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |  100 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
|  6 | xx     |   19 |
+----+--------+------+
6 rows in set (0.00 sec)

mysql> insert into t1(name,age) values('mm',20);
Query OK, 1 row affected (0.03 sec)

slave1:

mysql> select * from t1;
+----+--------+------+
| id | name   | age  |
+----+--------+------+
|  1 | zc     |  100 |
|  2 | ls     |   17 |
|  3 | ww     |   15 |
|  4 | hl     |   31 |
|  5 | master |   40 |
|  6 | yy     |    6 |
|  7 | mm     |   20 |
+----+--------+------+
7 rows in set (0.00 sec)

成功同步过来了!但是此时 slave1 里面的数据已经跟 master 不一致了,这个在实际操作时候还是要考虑具体情况,能否接受主从数据不一致,以采取对应解决办法。

今天先到这里,改天继续学习~

2020-11-22

相关文章

  • 主从复制高级

    主从复制高级 延时从库 故障恢复 半同步复制 主从复制过滤 gtid的复制 故障:

  • 深入学习Redis高可用架构:哨兵原理及实践

    Redis 主从复制的作用有数据热备、负载均衡、故障恢复等;但主从复制存在的一个问题是故障恢复无法自动化。 本文将...

  • Java高级架构笔记——实现故障恢复自动化:详解Redis哨兵技

    Redis主从复制的作用有数据热备、负载均衡、故障恢复等;但主从复制存在的一个问题是故障恢复无法自动化。本文将要介...

  • 实现故障恢复自动化:详解Redis哨兵技术

    Redis主从复制的作用有数据热备、负载均衡、故障恢复等;但主从复制存在的一个问题是故障恢复无法自动化。本文将要介...

  • MySQL-主从复制&读写分离

    零、本文纲要 一、MySQL主从复制 主从复制 主从复制过程 配置主从复制 二、MySQL读写分离 读写分离 Sh...

  • 深入Redis:哨兵

    前言 在 上一文中曾提到,Redis主从复制的作用有数据热备、负载均衡、故障恢复等;但主从复制存在的一个问题是故障...

  • 主从复制 & MHA

    一,mysql主从复制 (1)场景一(主从复制 _ 全新环境下) (2)场景二(主从复制 _ mysql已经使用一...

  • mysql主从复制架构

    为什么要设计mysql主从复制架构 为了解决mysql中出现单点故障的问题,进而设计了mysql主从架构,保障整体...

  • MySQL-lesson08-主从复制基础

    MySQL-lesson08-主从复制基础 0.企业高可用性标准 *** 0.1 全年无故障率(非计划内故障停机)...

  • redis主从复制原理

    主从复制的作用主要包括: 1、数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。 2、故障恢复...

网友评论

      本文标题:MySQL主从复制探索与故障恢复(二)

      本文链接:https://www.haomeiwen.com/subject/wbipiktx.html