基本概念

MySQL数据库支持单向、双向、链式级联、环状等不同业务场景的复制。在复制过程中,一台服务器充当
主服务器(Master),接收来自用户的内容更新,而一个或多个其他的服务器充当从服务器(Slave),接收来自主服务器binlog文件的日志内容,解析出SQL重新更新到从服务器,使得主从服务器数据达到一致。

主从复制的优点

  • 如果主库出现问题,可以快速切换到从库提供服务
  • 可以在从库执行查询操作,降低主库的访问压力。
  • 可以在从库进行备份,以免备份期间影响主库的服务。

注意:由于mysql实现的异步复制,所以主库和从库之间的数据存在一定的差异,在从库执行查询操作需要考虑这些数据的差异,一般只有更新不频繁或者对实时性要求不高的数据可以通过从库查询,实时性要求高的需要从主库查询。

主从复制原理

MySQL主从复制涉及到三个线程,一个运行在主节点(log dump thread),其余两个(I/O thread, SQL
thread)运行在从节点,如下图所示
image.png

主节点 log dump 线程

当从节点连接主节点时,主节点会为其创建一个log dump 线程,用于发送和读取bin-log的内容。在读取
bin-log中的操作时,log dump线程会对主节点上的bin-log加锁,当读取完成,在发送给从节点之前,锁会被释放。主节点会为自己的每一个从节点创建一个log dump 线程。

从节点 I/O线程

当从节点上执行 start slave 命令之后,从节点会创建一个I/O线程用来连接主节点,请求主库中更新的
bin-log。I/O线程接收到主节点的blog dump进程发来的更新之后,保存在本地relay-log(中继日志)中。

从节点 SQL线程

SQL线程负责读取relay-log中的内容,解析成具体的操作并执行,最终保证主从数据的一致性。
对于每一个主从连接,都需要这三个进程来完成。当主节点有多个从节点时,主节点会为每一个当前连接
的从节点建一个log dump 进程,而每个从节点都有自己的I/O进程,SQL进程。从节点用两个线程将从主
库拉取更新和执行分成独立的任务,这样在执行同步数据任务的时候,不会降低读操作的性能。比如,如
果从节点没有运行,此时I/O进程可以很快从主节点获取更新,尽管SQL进程还没有执行。如果在SQL进程
执行之前从节点服务停止,至少I/O进程已经从主节点拉取到了最新的变更并且保存在本地relay日志中,当服务再次起来之后,就可以完成数据的同步。
要实施复制,首先必须打开Master端的binary log(bin-log)功能,否则无法实现。
整个复制过程实际上就是Slave 从Master 端获取该日志然后再在自己身上完全顺序的执行日志中所记录的各种操作。如下图所示:
image.png

复制的基本过程

  1. 在从节点上执行sart slave命令开启主从复制开关,开始进行主从复制。从节点上的I/O 进程连接主节 点,并请求从指定日志文件的指定位置(或者从最开始的日志)之后的日志内容;
  2. 主节点接收到来自从节点的I/O请求后,通过负责复制的I/O进程(log dump 线程)根据请求信息读取 指定日志指定位置之后的日志信息,返回给从节点。返回信息中除了日志所包含的信息之外,还包括 本次返回的信息的bin-log file 的以及bin-log position(bin-log中的下一个指定更新位置);
  3. 从节点的I/O进程接收到主节点发送过来的日志内容、日志文件及位置点后,将接收到的日志内容更新 到本机的relay-log(中继日志)的文件(Mysql-relay-bin.xxx)的最末端,并将读取到的binary log(bin-log)文件名和位置保存到master-info 文件中,以便在下一次读取的时候能够清楚的告Master“我需要从某个bin-log 的哪个位置开始往后的日志内容,请发给我”;
  4. Slave 的 SQL线程检测到relay-log 中新增加了内容后,会将relay-log的内容解析成在主节点上实际执行过SQL语句,然后在本数据库中按照解析出来的顺序执行,并在relay-log.info中记录当前应用中继日志的文件名和位置点。

    主从复制实现方式

    image.png

    Master节点配置

    1. /*创建账号sql: create user 'username'@'localhost' identified by 'password'; 授权grant [权限] on *.* to 'username'@'localhost' identified by 'password'; */
    2. mysql> CREATE USER 'slave'@'192.168.81.%' IDENTIFIED WITH mysql_native_password BY 'slave'; Query OK, 0 rows affected (0.04 sec)
    3. mysql> select user,host from mysql.user;
    4. mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave'@'192.168.81.%'; Query OK, 0 rows affected, 1 warning (0.00 sec)
    1. mysql> show global variables like '%log_bin%';

    image.png

    1. [mysqld]
    2. log-bin=mysql-bin
    3. server-id=1

    Slave节点配置

    1. [mysqld]
    2. server-id = 2
    3. relay_log = /usr/local/mysql/data/mysql-relay-bin
    4. relay_log-index = /usr/local/mysql/data/mysql-relay-bin.index
    5. log_slave_updates = 1
    6. log-bin=mysql-bin
    7. read_only = 1

    参数介绍:

  5. server_id:这是服务id,系统会自动命名的,但如果机器重启可能会导致问题。可以将主库和备库上的log-bin设置为相同的值。

  6. relay_log:指定中继日志的位置和命名
    1. mysql> change master to master_host='192.168.29.102',master_port=3306,master_user='slave',master_password='slav e',master_log_file='mysqlbin.000002',master_log_pos=155;
    2. Query OK, 0 rows affected, 2 warnings (0.02 sec)
    1. mysql> start slave;
    2. Query OK, 0 rows affected (0.01 sec)
    1. mysql> show slave status \G;
    image.png