数据库-主从复制

原理作用详解

MySQL集群高可用架构

MySQL主从架构

在这里插入图片描述
特点:成本低,布置快速,方便;读写分离;可以通过及时增加从库减少读库压力;主库单点故障;数据一致性问题

MySQL+DRDB架构

通过DRBD基于block块的复制模式,快速进行双主故障切换,很大程度上解决主库单点故障问题
在这里插入图片描述
架构特点:
1、高可用软件可使用Heartbeat,全面负责VIP、数据与DRBD服务的管理
2、主故障后可自动快速切换,并且从库仍然能通过VIP与新主库进行数据同步
3、从库也支持读写分离,可使用中间件或程序实现

MySQL+MHA架构

在mysql故障切换过程中,MHA能做到快速自动切换操作,而且还能最大限度保持数据的一致性
在这里插入图片描述
架构特点:
1、安装布署简单,不影响现有架构
2、自动监控和故障转移
3、保障数据一致性
4、故障切换方式可使用手动或自动多向选择
5、适应范围大(适用任何存储引擎)

MySQL+MMM架构

MMM即Master-Master Replication Manager for MySQL(mysql主主复制管理器),是关于mysql主主复制配置的监控、故障转移和管理的一套可伸缩的脚本套件
在这里插入图片描述
架构特点:
1、安全、稳定性较高,可扩展性好
2、 对服务器数量要求至少三台及以上
3、 对双主(主从复制性要求较高)
4、 同样可实现读写分离

主从复制

可以将主服务器(master)上的数据复制到从服务器(slave)上。

mysql支持的复制类型

1、基于语句(statement)的复制:在主服务器上执行SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。
2、基于行(row)的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍。从MySQL 5.0开始支持。
3、混合型(mixed)的复制:默认采用基于语句的复制,一旦发现基于语句的无法精确复制时,就会采用基于行的复制。

主从复制的作用

灾备
数据分布
负载平衡
读写分离
提高并发能力

主从复制原理

主要基于MySQL二进制日志
主要包括三个线程(2个I/O线程,1个SQL线程)

1、MySQL将数据变化记录到二进制日志中;
2、Slave将MySQL的二进制日志拷贝到Slave的中继日志中;
3、Slave将中继日志中的事件在做一次,将数据变化,反应到自身(Slave)的数据库

步骤:

1、主库开启bin_log日志并授权一个用户
2、检查是否授权一个用户
3、从库执行start slave(开启主从)
4、从库将主库的bin_log日志复制到自己的relay-log(中继日志)中
5、SQL线程从中继日志中取出上一次的之后的执行语句并执行

详细步骤:

1、从库通过执行change master to 语句连接主库,提供了连接的用户一切条件(user 、 password、port、ip),并且让从库知道,二进制日志的起点位置(file名 position 号); start slave 
2、从库的IO线程和主库的dump线程建立连接。 
3、从库根据change master to 语句提供的file名和position号,IO线程向主库发起binlog的请求。 
4、主库dump线程根据从库的请求,将本地binlog以events的方式发给从库IO线程。 
5、从库IO线程接收binlog events,并存放到本地relay-log中,传送过来的信息,会记录到 master.info中 
6、从库SQL线程应用relay-log,并且把应用过的记录到relay-log.info中,默认情况下,已经应用过的 relay 会自动被清理purge

MySQL复制常用的拓扑结构
主从类型(Master-Slave)
主主类型(Master-Master)
级联类型(Master-Slave-Slave)A是B的主,B是C的主

主从复制的操作

主:master
从:slave 多实例:3306,3307

1、在从服务器上开启多实例

主服务器配置

1、开启binlog日志
[root@master ~]# vim /etc/my.cnf
log_bin=mysql-bin
server_id=1

2、进入数据库授权用户
[root@master ~]# mysql -uroot -p123456
mysql> grant replication slave on *.* to rep@'192.168.16.%' identified by '123456';

3、锁表
mysql> flush tables with read lock;

4、查看当前日志文件位置
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |      447 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

5、备份数据
[root@master mysql]# mysqldump -uroot -p123456 -A -B | gzip > /backup/mysql/mysql_bak.$(date +%F).sql.gz
mysqldump: [Warning] Using a password on the command line interface can be insecure.

6、解锁
mysql> unlock tables;

7、将数据复制到从库上
[root@master ~]# scp /backup/mysql/mysql_bak.2021-01-25.sql.gz 192.168.16.130:/tmp
root@192.168.16.130's password: 
mysql_bak.2021-01-25.sql.gz                                    100%  204KB   1.1MB/s   00:00  

从库上配置(多实例前提下)

多实例安装链接

1、开启服务
[root@slave ~]# mysqld_multi start 3306,3307

2、查看服务是否开启
[root@slave ~]# netstat -lnupt | grep 330
tcp6       0      0 :::3306                 :::*                    LISTEN      16232/mysqld        
tcp6       0      0 :::3307                 :::*                    LISTEN      16400/mysqld 

3、将复制过来的数据导入数据库
[root@slave ~]# zcat /tmp/mysql_bak.2021-01-25.sql.gz | mysql -uroot -p123456 -S /mysql/3306/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@slave ~]# zcat /tmp/mysql_bak.2021-01-25.sql.gz | mysql -uroot -p123456 -S /mysql/3307/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.

4、编辑配置文件
[root@slave ~]# mysql -uroot -p123456 -S /mysql/3306/mysql.sock
[root@slave ~]# mysql -uroot -p123456 -S /mysql/3307/mysql.sock
[root@slave ~]# vim /etc/my.cnf
[mysqld_multi]
mysqld = /usr/local/mysql/bin/mysqld_safe
mysqladmin = /usr/local/mysql/bin/mysqladmin
user = root
pass = 123456

[mysqld3306]
socket = /mysql/3306/mysql.sock
port = 3306
pid-file = /mysql/3306/mysql.pid
datadir = /mysql/3306/data
basedir = /usr/local/mysql
server_id=3306

[mysqld3307]
socket = /mysql/3307/mysql.sock
port = 3307
pid-file = /mysql/3307/mysql.pid
datadir = /mysql/3307/data
basedir = /usr/local/mysql
server_id=3307


5、重启服务
[root@slave ~]# mysqld_multi stop 3306,3307
[root@slave ~]# netstat -lnupt | grep 330
[root@slave ~]# mysqld_multi start 3306,3307
[root@slave ~]# netstat -lnupt | grep 330
tcp6       0      0 :::3306                 :::*                    LISTEN      16918/mysqld        
tcp6       0      0 :::3307                 :::*                    LISTEN      16921/mysqld   

6、进入3306数据库进行主从复制
[root@slave ~]# mysql -uroot -p123456 -S /mysql/3306/mysql.sock
mysql> change master to
    -> master_host='192.168.16.128',
    -> master_user='rep',
    -> master_password='123456',
    -> master_log_file='mysql-bin.000003',
    -> master_log_pos=447;
[root@slave ~]# mysql -uroot -p123456 -S /mysql/3307/mysql.sock
mysql> change master to
    -> master_host='192.168.16.128',
    -> master_user='rep',
    -> master_password='123456',
    -> master_log_file='mysql-bin.000003',
    -> master_log_pos=447;

7、开启主从复制
mysql> start slave;


8、查看主从状况监测主要参数 
Slave_IO_Running: IO线程是否打开 YES/No/NULL 
Slave_SQL_Running: SQL线程是否打开 YES/No/NULL 
Seconds_Behind_Master: NULL #和主库比同步的延迟的秒数

主从复制出现错误

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Connecting to master
                  Master_Host: 192.168.16.128
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 154
               Relay_Log_File: slave-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Connecting     连接中
            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: 154
              Relay_Log_Space: 154
              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: 2003
                Last_IO_Error: error connecting to master '[email protected]:3306' - retry-time: 60  r
               Last_SQL_Errno: 0
               Last_SQL_Error: 
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 0
                  Master_UUID: 
             Master_Info_File: /mysql/3307/data/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: 210126 09:23:41
     Last_SQL_Error_Timestamp: 
               Master_SSL_Crl: 
           Master_SSL_Crlpath: 
           Retrieved_Gtid_Set: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 

从库上上测试能否访问主库服务器

[root@slave ~]# ping 192.168.16.128
PING 192.168.16.128 (192.168.16.128) 56(84) bytes of data.
64 bytes from 192.168.16.128: icmp_seq=1 ttl=64 time=0.710 ms
64 bytes from 192.168.16.128: icmp_seq=2 ttl=64 time=0.842 ms

出错原因:
没有关闭防火墙与Selinux

修正错误

主从库分别关闭防火墙和Selinux
[root@master ~]# systemctl stop firewalld.service 
[root@master ~]# setenforce 0
[root@slave ~]# systemctl stop firewalld.service 
[root@slave ~]# setenforce 0

重启主从复制
mysql> stop slave;
mysql> start slave;

查看
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.16.128
                  Master_User: rep
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 447
               Relay_Log_File: slave-relay-bin.000002
                Relay_Log_Pos: 613
        Relay_Master_Log_File: mysql-bin.000003
             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: 447
              Relay_Log_Space: 820
              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: 1
                  Master_UUID: a74aedab-554e-11eb-b297-000c296550da
             Master_Info_File: /mysql/3307/data/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: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 

9、测试
主库:
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| school             |
| sys                |
+--------------------+
5 rows in set (0.10 sec)

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

从库:3306
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| school             |
| sys                |
| xxx                |
+--------------------+

3307
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| school             |
| sys                |
| xxx                |
+--------------------+
6 rows in set (0.00 sec)

其他错误原因

主从时钟是否一致 
网络通信是否存在延迟 
是否和日志类型,数据过大有关 从库性能,
有没开启binlog 从库查询是否优化

常见状态错误排除
发现IO进程错误,检查日志,排除故障:# tail localhost.localdomain.err

错误一示例:

show slave status;
错误现象:
[ERROR] Slave I/O: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work. Error_code: 1593

原因:从5.6开始复制引入了uuid的概念,各个复制结构中的server_uuid得保证不一样 

解决方法:(从库是克隆机器) 修改从库的uuid 
# vim auto.cnf 
server-uuid=

错误二示例:

show slave status;
报错:Error xxx doesn’t exist 
解决方法: 
stop slave; 
set global sql_slave_skip_counter = 1; 
start slave;

猜你喜欢

转载自blog.csdn.net/m0_46289868/article/details/113031175
今日推荐