主从复制环境搭建好后,对我们来说并不是没有下文或没有后顾之忧了。再好的程序都可能出错,只是概率的问题,换句话说,这个世上没有亘古不变的事,只有变幻莫测的人心,哈哈哈。突然想到了一个牛逼的定律----墨菲定律:如果一件事有出错的可能性,那么这件事一定会出错。突然感觉自己也挺有内涵的,瞬间提升了自己的档次。好了回到我们的主题上来,看看主从复制的IO线程故障和解决办法。

查看主从状态
通过show slave status\G 查看从服务器运行状态,主要状态信息如下:

show slave status\G

Slave_IO_Running: Yes     #IO线程状态
Slave_SQL_Running: Yes     #SQL线程状态
Last_IO_Errno: 0      #IO线程最后一次错误代码
Last_IO_Error:         #IO线程错误说明
Last_SQL_Errno: 0      #SQL线程最后一次错误代码
Last_SQL_Error:        #SQL线程错误说明

 

IO线程故障:IO线程向主库请求二进制日志,并且接受二进制日志。

  • 主库连接不上
    原因:

    (1)user、password、port、ip 错误
            解决:重新配置信息,然后执行以下命令
                      stop slave;
                      reset slave all;
                      change master to ...;
                      start slave;
    (2)防火墙
    (3)网络不通
    (4)skip-name-resolve
             解决:配置skip-name-resolve,然后执行:
                       stop slave;
                       start slave;
  • 主库二进制日志丢失或损坏
    解决:
             stop slave;
             reset slave all;
             重新备份恢复;
             change master to ...;
             start slave;

 

SQL线程故障:从relaylog中获取最新的未执行的日志来执行​​(从库做写入操作,都可能会导致以下问题出现)

  • 删除、修改对象的操作时,没有这个对象
  • 创建对象时,对象已存在
  • 主键冲突

模拟故障:

(1)从库3308中创建数据库db01;

[root@db01 data]# mysql -S /data/3308/mysql.sock 

mysql> create database db01;
Query OK, 1 row affected (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| db01               |
| fxw                |
| mysql              |
| performance_schema |
| test               |
+--------------------+
6 rows in set (0.01 sec)

(2)主库3307中创建数据库db01;

[root@db01 ~]# mysql -S /data/3307/mysql.sock 

mysql> create database db01;
Query OK, 1 row affected (0.01 sec)

# 看似一切安好
(3)从库3308中查看状态;

mysql> show slave status\G
*************************** 1. row ***************************
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1007
                   Last_Error: Error 'Can't create database 'db01'; database exists' on query. Default database: 'db01'. Query: 'create database db01'
                           .
                           .
                           .
               Last_SQL_Errno: 1007
               Last_SQL_Error: Error 'Can't create database 'db01'; database exists' on query. Default database: 'db01'. Query: 'create database db01'
                           .
                           .

#这是我们可以看见Slave_SQL_Running: No,以及Last_Error,Last_SQL_Error等,也就是我们在3308中已经创建过db01,当3308通过二进制日志在此创建想通的数据库db01时发生冲突。
 

解决方法(1)
直接在3308中执行:

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

mysql> set global sql_slave_skip_counter = 1;
Query OK, 0 rows affected (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 10.0.0.20
                  Master_User: repl
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
                           .
                           .
                        省略部分
                           .
                           .
                Last_IO_Errno: 0
                Last_IO_Error: 
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
ERROR: 
No query specified

# 此时错误已经消失
#
global sql_slave_skip_counter = 1 ,表示跳过错误,命令详情请参看https://www.iteye.com/blog/dinglin-1236330
 

解决方法(2)
在从库3308的配置文件中加入以下代码:

vim /data/3308/my.cnf

[mysqld]
slave-skip-errors = 1032,1062,1007    

#slave-skip-errors 表示从库忽略错误代码为1032,1062,1007的错误

1007:数据库已存在,创建数据库失败
1008:数据库不存在,删除数据库失败
1050:数据表已存在,创建数据表失败
1050:数据表不存在,删除数据表失败
1054:字段不存在,或程序文件跟数据库有冲突
1060:字段重复,导致无法插入
1061:重复键名
1068:定义了多个主键
1094:位置线程ID
1146:数据表缺失,请恢复数据库

 

解决方法(3)
直接在从库命令行执行:set global read_only=1; 设置从库为只读

mysql> set global read_only=1;
Query OK, 0 rows affected (0.00 sec)

或者在配置文件中:

vim /data/3308/my.cnf

[mysqld]
read_only=1           ###只能控制普通用户,管理用户无效


 

主从延时过长:主从数据库之间并非同步,但是如果延时过长也是问题

Seconds_Behind_Master 即为主从时间间隔时间

mysql> show slave status\G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  .
                  .
                  .
        Seconds_Behind_Master: 0
                  .
                  .
                  .
1 row in set (0.00 sec)

ERROR: 
No query specified

# 目前时间间隔为0秒,但是如果网络波动或其他原因会导致时间过长,我们会希望Seconds_Behind_Master值越小越好。
# 默认主从复制机制是异步过程

  • 主库原因:
    (1)主库做修改操作之后,才会记录二进制日志。
            sync_binlog=0/1,默认0,
            0 表示操作系统缓存机制控制, 
            1 表示立即写入二进制日志,每次commit后刷新到binlog,是最安全的机制,所以主从复制下,设置为1

    (2)主库的压力特别大(大事务,多事务)

    (3)从库数量较多,导致dump线程繁忙
     
  • 从库原因:
    (1)relay-log写入慢
    (2)SQL线程慢(主从硬件差异较大)
     
  • 尽可能避免主从延时
    (1)sync_binlog=1
    (2)大事务拆成小事务,多事务进行分离
    (3)使用多级主从,分库分表架构
    (4)将binlog放到ssd或者flash上,高性能存储
    (5)将relay放到ssd或者flash上
    (6)尽量选择和主库一致硬件和配置
最后修改于 2019-08-22 13:52:38
如果觉得我的文章对你有用,请随意赞赏
扫一扫支付
上一篇