【MySQL管理】:Replication主从复制(一):异步复制

     本教程以MySQL8为主版本。 

     所有MySQL文章的目录为:总目录    https://blog.csdn.net/zyplanke/article/details/102968014     

     本文介绍MySQL中主从复制Replication种最基础也是最重要的异步复制的搭建过程。 包括两级复制(一主、一从),三级复制(一主、一从、再从)。

目录

一、复制架构衍生史

二、易混淆概念区分

三、环境介绍

四、主Master节点(IP:43.201)

1、Master节点配置文件

2、创建Slave连接用的用户

3、备份Master节点,作为Slave的初始数据

五、从Slave节点(IP:43.203)

1、Slave节点配置文件

2、Slave从库导入

3、从库同步设置

六、 一主一从复制效果验证

七、三级复制模式

1、修改节点43.203配置文件

2、修改43.205节点配置文件

3、从43.203导出数据

4、数据导入至43.205

5、取消43.203只读设置

6、从库43.205同步设置

 八、三层复制效果验证


一、复制架构衍生史

    在谈这个特性之前,我们先来看看MySQL的复制架构衍生史。

    在2000年,MySQL 3.23.15版本引入了Replication。Replication作为一种准实时同步方式,得到广泛应用。这个时候的Replicaton的实现涉及到两个线程,一个在Master,一个在Slave。Slave的I/O和SQL功能是作为一个线程,从Master获取到event后直接apply,没有relay log。这种方式使得读取event的速度会被Slave replay速度拖慢,当主备存在较大延迟时候,会导致大量binary log没有备份到Slave端。

    在2002年,MySQL 4.0.2版本将Slave端event读取和执行独立成两个线程(IO线程和SQL线程),同时引入了relay log。IO线程读取event后写入relay log,SQL线程从relay log中读取event然后执行。这样即使SQL线程执行慢,Master的binary log也会尽可能的同步到Slave。当Master宕机,切换到Slave,不会出现大量数据丢失。

    在2010年MySQL 5.5版本之前,一直采用的是这种异步复制的方式。主库的事务执行不会管备库的同步进度,如果备库落后,主库不幸crash,那么就会导致数据丢失。于是在MySQL在5.5中就顺其自然地引入了半同步复制,主库在应答客户端提交的事务前需要保证至少一个从库接收并写到relay log中。那么半同步复制是否可以做到不丢失数据呢?下面分析。

    在2016年,MySQL在5.7.17开始中引入了一个全新的技术,称之为InnoDB Group Replication。全同步技术带来了更多的数据一致性保障。

   根据上面提到的这几种复制协议,分别对应MySQL几种复制类型,分别是异步、半同步、全同步。

【MySQL管理】:Replication主从复制(一):异步复制_第1张图片

注意上图只画出了MySQL 5.7版本之前的AFTER_COMMIT,未画出5.7版本后支持的AFTER_SYNC 

  • 对于异步复制,主库将事务Binlog事件写入到Binlog文件中,此时主库只会通知一下Dump线程发送这些新的Binlog,然后主库就会继续处理提交操作,而此时不会保证这些Binlog传到任何一个从库节点上。
  • 对于全同步复制,当主库提交事务之后,所有的从库节点必须收到,APPLY并且提交这些事务,然后主库线程才能继续做后续操作。这里面有一个很明显的缺点就是,主库完成一个事务的时间被拉长,性能降低。
  • 对于半同步复制,是介于全同步复制和异步复制之间的一种,主库只需要等待至少一个从库节点收到并且Flush Binlog到Relay Log文件即可,主库不需要等待所有从库给主库反馈。同时,这里只是一个收到的反馈,而不是已经完全执行并且提交的反馈,这样就节省了很多时间。

注:在InnoDB双一设置(sync_binlog=1和innodb_flush_log_at_trx_commit=1)时,在commit过程中,redo log是先于binlog写入磁盘的。

二、易混淆概念区分

  涉及到以下几个参数或概念

  bin_log: 数据库服务器(Master和Slave)自身的数据变化,而记录的event二进制数据。 既bin_log是自身节点上的数据操作(变更)而记录的自己的二进制文件。

  reley_log: 自己作为从节点,从主节点(别的节点)上拷贝过来的event二进制日志,该日志文件,可以理解为是主节点数据的拷贝,目的是为了使应用该日志,使自己保持与主节点数据一致。

  log_slave_updates:自己作为从节点,在应用上面的relay_log的同时,把这些relay_log上的event视为自身节点上的数据操作(变更),记录仅自己的二进制文件。 目的是实现二进制日志文件的多级传递,比如B是A的从节点,C是B的从节点。则B需要开启本参数,以实现从A收到的relay_log在应用后,还同时记录入B的binlog,然后C从B获得的二进制文件(C的relay_log)里面才可以包含A节点的bin_log内容

三、环境介绍

IP 操作系统 数据库版本 用途
192.168.43.201 CentOS 7.7 x64bit MySQL 8.0.18,已有数据 作为Master主节点
192.168.43.203 CentOS 7.7 x64bit MySQL 8.0.18,全新库 先作为201的Slave从节点,然后再作为205的主节点
192.168.43.205 CentOS 7.7 x64bit MySQL 8.0.18,全新库 作为203的Slave从节点

主从复制环境,应保证操作系统和数据库版本一致,减少出问题的概率。

四、主Master节点(IP:43.201)

1、Master节点配置文件

确保Master 和 Slave 的 server_id 不能相同,并且Master开启binlog二进制日志(设置文件名前缀为binlog),并在每次commit的同时sync写到binlog文件中。因此编辑/etc/my.cnf文件,增加配置。

[mysqld]
server_id=201
log_bin=binlog
sync_binlog=1
binlog_format=ROW
binlog_rows_query_log_events=ON


#另外还有其他参数,酌情选择设置
#log_bin_trust_function_creators=ON  # 是否同步函数(默认OFF)
#binlog_expire_logs_seconds=2592000  #binlog日志文件留存多少秒(默认为30天,之前的expire_logs_day参数已经作废。)
#binlog_cache_size=1M  #默认32K,根据业务繁忙程度设置,通常1~4MB

注1:配置文件中参数中的“中划线”和“下划线”都可以。无论是哪种划线(甚至混合也可以),最后显示的变量都是下划线。

注2:对于老版本MySQL5.x,关闭binlog使用“log_bin=OFF”或者“log_bin=0”即可关闭。在MySQL8中,这种方式已无法关闭binlog,需要使用:“disable_log_bin”配置关闭。

注3:binlog_format为ROW或MIX时,对于涉及Temporary临时表的操作,主库不会记录binlog,所以涉及临时表的操作主库不会复制给从库。 若format为STATEMENT,主库记录binlog,会复制给从库。  从复制数据的可靠性考虑,通常format都会选择ROW。

然后重启主节点的mysqld服务。

2、创建Slave连接用的用户

在Master节点上,创建一个用户,用于数据同步Slave从节点连接Master的用户。 (限制该用户只能从本局域网登录)

mysql> CREATE USER 'replica'@'192.168.43.%' IDENTIFIED BY 'Replica_999';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO 'replica'@'192.168.43.%';
Query OK, 0 rows affected (0.00 sec)

注:该复制用户在主库、从库均需要存在(下文通过备份实现了从库也有此用户,因此在从库无需再手动建立此用户)

3、备份Master节点,作为Slave的初始数据

【注】因复制只复制关联建立后的数据,对于之前的数据不会复制。所以需要人工通过备份恢复方式,形成主、从机器的初始数据时一致的。

备份的方式可以多样:

  •  如果数据量不大,备份耗时可以接收,则使用mysqldump工具进行逻辑备份
  •  如果数据量比较大备份耗时,且Master节点可以停止,在停止后使用操作系统文件拷贝传输至Slave节点进行物理备份(这种方式最快)。

下文以mysqldump方式进行说明。

   a、为保证备份期间数据一致性,对主库执行以下命令,将主库设置为禁止写操作。

mysql> FLUSH TABLES WITH READ LOCK;
Query OK, 0 rows affected (0.00 sec)

mysql> SET GLOBAL read_only=ON; 
Query OK, 0 rows affected (0.00 sec)

注:①set global read_only是全局级别的参数(不是锁),置为ON之后,普通用户只能读不能写,具有super权限的用户仍可以写。 此属性设置在从节点上,不会影响binlog的relay和应用,既在从节点上设置此属性为只读,从节点salve仍然会读取master上的日志,并且在slave库中应用日志,保证主从数据库同步一致。

     ②FLUSH TABLES WITH READ LOCK(FTWRL)是表级别的锁(tables指所有表,还可以指定具体的表),执行之后,包括具有super权限的所有用户都不能写表。一直锁定直到unlock。 在从节点执行FTWRL后,由于表都被锁住,从节点对binlog的relay应用也无法写到表中,影响从节点的数据同步。   因此FTWRL通常仅在临时彻底只读时使用。

  b、查看当前Master主节点binlog日志名和pos偏移量(因上步已设置为只读,在只读期间偏移量不会变化)

mysql> show master status;
+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000003 |      155 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

  c、全库备份。

[zyplanke@centosb ~]$ mysqldump -h 192.168.43.201 -u root -p --all-databases --single-transaction > dump_of_master.sql
Enter password: 


[zyplanke@centosb ~]$ ls -l dump_of_master.sql
-rw-rw-r--. 1 zyplanke zyplanke 15943508 May  6 00:11 dump_of_master.sql

d、备份完毕后,对主库执行以下命令,恢复Master主节点写操作。

mysql> SET GLOBAL read_only=OFF; 
Query OK, 0 rows affected (0.00 sec)

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

五、从Slave节点(IP:43.203)

1、Slave节点配置文件

Slave 的 server_id 不能与主节点相同。

[mysqld]
server_id=203
read_only=ON

注:若从节点不用于写入用途,则将从节点设置为只读(如上)。 若从节点将用于写入用途,则不要设置为只读,并且开启写从节点自身的binlog(既log_bin=binlog和sysc_binlog=1两个参数)。从节点自身的binlog记录的是写操作对从节点的自身binlog,而不是从主节点复制过来的relaylog

注:如果从节点可能接替Master,升为主节点,则Slave节点的应设置为read_only=OFF。

如果已经启动了GTID模式,还需要删除从节点datadir目录下的auto.cnf文件(删除后,重启时会自动新生成UUID),避免与主节点具有相同的UUID。

然后重启从节点的mysqld服务。  (如果重启之前已经配置了同步设置,则在配置文件中增加skip-slave-start参数,这样启动后不会立即从主库上进行同步。)

2、Slave从库导入

[zyplanke@centosb ~]$ mysql -h 192.168.43.203 -u root -p < dump_of_master.sql                                 
Enter password: 

注:即使将从库设置read_only属性,也能导入成功,因为导入使用的root用户具有super权限。 read_only不限制具有super权限的用户进行写操作。

   导入完毕后,检查导入后的数据库。

3、从库同步设置

   在43.203从库中,执行以下语句连接到master主库:

mysql> change master to 
       master_host='192.168.43.201',
       master_port=3306,
       master_user='replica',
       master_password='Replica_999',
       get_master_public_key=1,
       master_log_file='binlog.000003',
       master_log_pos=155
       for channel 'channel_201_3306';


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

  启动slave后,立即能看到slave的状态

   【说明】MySQL8.0版本开始由于用户默认使用caching_sha2_password认证,该认证除了密码字符串加密方式不同外,还要求客户端与服务端之间必须通过secure connection安全连接访问。上面的replica复制专用用户需要与主库建立连接,也需要使用安全连接,否则会报:Authentication plugin 'caching_sha2_password' reported error: Authentication requires secure connection 错误。对此,通常有三种解决办法:

①将replica用户认证方式由默认的“caching_sha2_password”改为“mysql_native_password”(在主库、从库对该用户均需修改),直接避免此问题。

②如上,在change master指令中启用“get_master_public_key”使在该用户在连接主库自动获得主库的公钥  

将主库公钥文件拷贝至从机上,在change master指令中“master_public_key_path”指向拷贝得到公钥文件。

注:若MySQL服务端(这里即主库)重启时,其公钥会自动重新生成,则客户端(这里即从库)也需要重新连接以获得最新公钥才能成功连接。 对于从库会以Connect_Retry的秒数自动重连。

mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.43.201
                  Master_User: replica
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: binlog.000003
          Read_Master_Log_Pos: 155
               Relay_Log_File: centosb-relay-bin.000002
                Relay_Log_Pos: 319
        Relay_Master_Log_File: binlog.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: 155
              Relay_Log_Space: 529
              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: 201
                  Master_UUID: aa951098-207f-11ea-94ec-000c29939c22
             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: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
       Master_public_key_path: 
        Get_master_public_key: 1
            Network_Namespace: 
1 row in set (0.00 sec)

  分别查看主库和从库上面的process。

#  以下为43.201的信息:
mysql> show processlist;
+----+-----------------+----------------------+------+-------------+------+---------------------------------------------------------------+------------------+
| Id | User            | Host                 | db   | Command     | Time | State                                                         | Info             |
+----+-----------------+----------------------+------+-------------+------+---------------------------------------------------------------+------------------+
|  4 | event_scheduler | localhost            | NULL | Daemon      |  525 | Waiting on empty queue                                        | NULL             |
|  8 | root            | localhost            | NULL | Query       |    0 | starting                                                      | show processlist |
| 11 | replica         | 192.168.43.203:54456 | NULL | Binlog Dump |  109 | Master has sent all binlog to slave; waiting for more updates | NULL             |
+----+-----------------+----------------------+------+-------------+------+---------------------------------------------------------------+------------------+
3 rows in set (0.00 sec)



#  以下为43.203的信息:
mysql>  show processlist;
+----+-----------------+-----------------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User            | Host            | db   | Command | Time | State                                                  | Info             |
+----+-----------------+-----------------+------+---------+------+--------------------------------------------------------+------------------+
|  4 | event_scheduler | localhost       | NULL | Daemon  | 1686 | Waiting on empty queue                                 | NULL             |
| 20 | system user     | connecting host | NULL | Connect |  176 | Waiting for master to send event                       | NULL             |
| 21 | system user     |                 | NULL | Query   |  116 | Slave has read all relay log; waiting for more updates | NULL             |
| 22 | root            | centosb:51818   | NULL | Query   |    0 | starting                                               | show processlist |
+----+-----------------+-----------------+------+---------+------+--------------------------------------------------------+------------------+
4 rows in set (0.00 sec)

六、 一主一从复制效果验证

    在主库上更新一条数据后,在从库上几乎立即就能看到更新后的结果,而且从库的show slave status中,log_pos的值也发生了变化。 说明主从数据同步已经能正常运行。

------- 至此,一主一从复制搭建完毕 --------

-------------------------------------------------------------------------

-------   下面搭建三级复制 --------

七、三级复制模式

在上面一主一从的基础上,我们搭建三级复制模式。既:

43.201作为主节点  →→复制→→  43.203作为43.201从节点 →→复制→→ 43.205作为43.203从节点

1、修改节点43.203配置文件

[mysqld]
server_id=205
read_only=ON
log_slave_updates=ON
log_bin=binlog
sync_binlog=1
binlog_format=ROW
binlog_rows_query_log_events=ON

#其他参数参考Master酌情设置

     由于43.203是43.201的从节点的同时,还作为43.205的主节点,所以须在43.203配置中增加参数:

log_slave_updates=ON

    该ON表示43.203从43.201复制binlog后,在应用43.201写入43.203本地库时,同步在43.203上生成binlog(如果参数值为OFF则表示不写入binlog)。这样43.203的binlog的包括全部的数据(包括43.201的数据),下游节点只需从43.203读取binlog即可。

2、修改43.205节点配置文件

[mysqld]
server_id=205
read_only=ON

注:若从节点不用于写入用途,则将从节点设置为只读(如上)。 若从节点将用于写入用途,则不要设置为只读,并且开启写从节点自身的binlog(既log_bin=binlog和sysc_binlog=1两个参数)。从节点自身的binlog记录的是写操作对从节点的自身binlog,而不是从主节点复制过来的relaylog

如果已经启动了GTID模式,还需要删除从节点datadir目录下的auto.cnf文件(删除后,重启时会自动新生成UUID),避免与主节点具有相同的UUID。

然后重启从节点的mysqld服务。  (如果重启之前已经配置了同步设置,则在配置文件中增加skip-slave-start参数,这样启动后不会立即从主库上进行同步。)

3、从43.203导出数据

   因43.205的主节点43.203,因此导入的数据来源因为43.203。   

   首先,再43.203上创建用于43.205连接的用户replica(如有,无需重复创建)

   然后,对43.203设置FTWRL和global read_only, 使43.203禁止写入。然后从43.203备份数据(操作步骤见上)

   还需,在43.203上执行show master status命令,获得43.203上的当前的binlog日志文件名和pos值。

4、数据导入至43.205

[zyplanke@centosb ~]$ mysql -h 192.168.43.205 -u root -p < dump_of_master.sql                                 
Enter password: 

   导入完毕后,检查导入后的数据库。

5、取消43.203只读设置

  在43.203中,取消FTWRL和global read_only设置

6、从库43.205同步设置

   在43.205从库中,执行以下语句连接到master主库:

mysql> change master to 
       master_host='192.168.43.203',
       master_port=3306,
       master_user='replica',
       master_password='Replica_999',
       get_master_public_key=1,
       master_log_file='binlog.000008',
       master_log_pos=653;


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

  启动slave后,(稍等几秒钟后)查看slave的状态

mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.43.203
                  Master_User: replica
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: binlog.000008
          Read_Master_Log_Pos: 826
               Relay_Log_File: centosc-relay-bin.000003
                Relay_Log_Pos: 492
        Relay_Master_Log_File: binlog.000008
             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: 826
              Relay_Log_Space: 702
              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: 203
                  Master_UUID: 79e9dd41-8edb-11ea-b317-000c29859ed1
             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: 
            Executed_Gtid_Set: 
                Auto_Position: 0
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
       Master_public_key_path: 
        Get_master_public_key: 1
            Network_Namespace: 
1 row in set (0.00 sec)

  分别查看43.203和43.205上面的process。

#  以下为43.203的信息:
mysql> show processlist;
+----+-----------------+----------------------+--------+-------------+------+---------------------------------------------------------------+------------------+
| Id | User            | Host                 | db     | Command     | Time | State                                                         | Info             |
+----+-----------------+----------------------+--------+-------------+------+---------------------------------------------------------------+------------------+
|  4 | event_scheduler | localhost            | NULL   | Daemon      | 1774 | Waiting on empty queue                                        | NULL             |
| 24 | root            | centosb:44912        | dbtest | Query       |    0 | starting                                                      | show processlist |
| 36 | replica         | 192.168.43.205:56658 | NULL   | Binlog Dump |  139 | Master has sent all binlog to slave; waiting for more updates | NULL             |
| 37 | system user     | connecting host      | NULL   | Connect     |   25 | Waiting for master to send event                              | NULL             |
| 38 | system user     |                      | NULL   | Query       |   36 | Slave has read all relay log; waiting for more updates        | NULL             |
+----+-----------------+----------------------+--------+-------------+------+---------------------------------------------------------------+------------------+
5 rows in set (0.00 sec)



#  以下为43.205的信息:
mysql> show processlist;
+----+-----------------+-----------------+--------+---------+------+--------------------------------------------------------+------------------+
| Id | User            | Host            | db     | Command | Time | State                                                  | Info             |
+----+-----------------+-----------------+--------+---------+------+--------------------------------------------------------+------------------+
|  4 | event_scheduler | localhost       | NULL   | Daemon  |  283 | Waiting on empty queue                                 | NULL             |
| 11 | system user     | connecting host | NULL   | Connect |  261 | Waiting for master to send event                       | NULL             |
| 12 | system user     |                 | NULL   | Query   |   98 | Slave has read all relay log; waiting for more updates | NULL             |
| 16 | root            | centosc:57348   | dbtest | Query   |    0 | starting                                               | show processlist |
+----+-----------------+-----------------+--------+---------+------+--------------------------------------------------------+------------------+
4 rows in set (0.00 sec)

 八、三层复制效果验证

在43.201上新建表并inset一条数据,在43.203和43.205上上几乎立即就能看到同步的最新结果,而且从库的show slave status中,log_pos的值也发生了变化。 说明主从数据同步已经能正常运行。

同时,若在43.203上执行stop slave 暂停43.201至43.203的同步后,这时在43.201上变更数据,无法在43.203和43.205看到最新结果,而一旦在43.203上执行start slave启动后,几乎立即在43.203和43.205上就能看到最新结果。 这说明43.205的数据来源的确是从43.203复制过来的。

你可能感兴趣的:(MySQL,mysql)