zoukankan      html  css  js  c++  java
  • MySQL主从复制原理及配置过程

    一、Mysql数据库的主从复制原理过程:

    (多实例的安装请参考我的另一篇文章:https://www.cnblogs.com/Template/p/9258500.html

    Mysql的主从复制是一个异步的复制过程,数据将从一个Mysql数据库(master)复制到另一个Mysql数据库(slave),在Master和Slave之间实现整个主从复制的过程是由三个线程参与完成的。其中有两个线程(SQL线程和I/O线程)在Slave端,另外一个线程(I/O线程)在Master端 ,要实现Mysql的主从复制,首先必须打开Master端的binlog记录功能,否则就无法实现。因为整个复制过程实际上就是Slave从Master获取binlog日志,然后再在Slave上以相同顺序执行获取的binlog日志中所记录的各种SQL操作 要打开Mysql的binlog记录功能,可以通过在Mysql的配置文件my.cnf中的mysqld模块([mysqld])增加"log-bin"参数选项来实现,具体信息如下:

    [mysqld]
    log-bin = /data/3306/mysql-bin

     二、Mysql主从复制过程描述

    1、在Slave服务器上执行start slave命令开启主从复制开关,开始进行主从复制。

    2、此时,Slave服务器的I/O线程会通过在Master上已经授权的复制用户权限请求连接Master服务器,并请求从指定的binlog日志文件的指定位置
    (日志文件名和位置就是在配置主从复制服务时执行change master 命令指定的)之后开始发送binlog日志内容

    3、Master服务器接收到来自Slave服务器的I/O线程的请求后,其上负责复制的I/O线程会根据Slave服务器I/O线程请求的信息分批读取指定
    binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的I/O线程,返回的信息中除了binlog日志内容外,还有Master服务器端记录的新的binlog
    文件名称,以及在新的binlog中的下一个指定更新位置

    4、当Slave服务器的I/O线程获取到master服务器上的I/O线程发送的日志内容、日志文件以及位置点后,会将binlog日志内容依次写到Slave端自身的Relay log
    (即中继日志)文件(MySQL-relay-bin.xxxxxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取Master端新binlog日志时能够
    告诉Master服务器从新的binlog日志的指定文件及位置开始请求新的binlog日志内容

    5、Slave服务器的SQL线程会实时检测本地RelayLog中I/O线程新增加的日志内容,然后及时的吧RelayLog文件中的内容解析成SQL语句,并在Slave服务器上按解析SQL语句的位置顺序执行应用这些SQL语句,并在relay-log.info中记录当前应用中继日志的文件名及位置点

     经过上面的过程,就可以确保Master端和Slave端执行了同样的SQL语句,当复制状态正常时,Master端和Slave端的数据是完全一样的

    三、主从配置过程(以实例都在一台服务器上说明)

    #####在Mysql主库上执行的操作过程

    vim /data/3306/my.cnf
    修改[mysqld]下的两行
    log-bin = /data/3306/mysql-bin
    
    server-id = 6
    [root@localhost ~]# egrep "server-id|log-bin" /data/3306/my.cnf 
    log-bin = /data/3306/mysql-bin
    server-id = 6
    [root@localhost ~]# /data/3306/mysql restart  #重启Mysql主库
    mysql -u root -p123456 -S /data/3306/mysql.sock
    mysql> show variables like 'server_id';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | server_id     | 6     |
    +---------------+-------+
    1 row in set (0.00 sec)
    
    mysql> show variables like 'log_bin';
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | log_bin       | ON    |
    +---------------+-------+
    1 row in set (0.00 sec)

    #根据主从复制的原理,从库想要和主库同步,必须要有一个可以连接主库的账号,并且这个账号是主库上面创建的,权限是允许从库连接并同步数据

     mysql> grant replication slave on *.* to 'rep'@'192.168.56.%' identified by '123456'; 

    Query OK, 0 rows affected (0.00 sec)

    #刷新权限
    mysql> flush privileges;
    Query OK, 0 rows affected (0.01 sec)

    #检查主库创建的rep账号
    mysql> select user,host from mysql.user;
    +------+-----------------------+
    | user | host |
    +------+-----------------------+
    | root | 127.0.0.1 |
    | rep | 192.168.56.% |
    | root | ::1

    #检查权限
    mysql> show grants for rep@'192.168.56.%';
    +---------------------------------------------------------------------------------------------------------------------------+
    | Grants for rep@192.168.56.% |
    +---------------------------------------------------------------------------------------------------------------------------+
    | GRANT REPLICATION SLAVE ON *.* TO 'rep'@'192.168.56.%' IDENTIFIED BY PASSWORD '*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9' |
    +---------------------------------------------------------------------------------------------------------------------------+
    1 row in set (0.00 sec)

    #对主数据库锁表只读
    mysql> flush table with read lock;
    Query OK, 0 rows affected (0.00 sec)

    #查看自动解锁时长
    mysql> show variables like '%timeout%';
    +----------------------------+----------+
    | Variable_name | Value |
    +----------------------------+----------+
    | connect_timeout | 10 |
    | delayed_insert_timeout | 300 |
    | innodb_lock_wait_timeout | 120 |
    | innodb_rollback_on_timeout | OFF |
    | interactive_timeout | 28800 |
    | lock_wait_timeout | 31536000 |
    | net_read_timeout | 30 |
    | net_write_timeout | 60 |
    | slave_net_timeout | 3600 |
    | wait_timeout | 28800 |
    +----------------------------+----------+
    10 rows in set (0.00 sec)

    #锁表后查看主库状态,命令显示的信息要记录在案,后面的从库导入全备后,继续和主库复制时就是要从这个位置开始

    mysql> show master status;
    +------------------+----------+--------------+------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
    +------------------+----------+--------------+------------------+
    | mysql-bin.000001 | 334 | | |
    +------------------+----------+--------------+------------------+
    1 row in set (0.00 sec)

    ##或者使用mysql -uroot -p123456 -S /data/3306/mysql.sock -e "show master status"

    #锁表后,一定单开一个新的ssh窗口,导出数据库的所有数据,如果数据量很大(50G以上),并且允许停机,可以停库直接打包数据文件进行迁移,那样更快

    #新开一个窗口,备份数据库,以备迁移数据到从库


    [root@localhost ~]# mkdir /server/backup -p

    [root@localhost ~]# mysqldump -uroot -p123456 -S /data/3306/mysql.sock --events -A -B | gzip > /server/backup/mysql_bak.$(date +%F).sql.gz

    #-A表示备份所有库;-B 表示增加use DB和drop等(导库时会直接覆盖原有的)

    #导出数据完毕后,解锁主库,恢复可写,因为主库还要对外提供服务,不能一直锁定不让用户访问

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

    ######在Mysql从库上执行的操作过程

    设置server-id
    并关闭binlog功能(如果从库不做级联复制,并且不作为备份用,就不要开启binlog,开起了反而会增加从库磁盘I/O等的压力)

    vim /data/3307/my.cnf
    server-id = 7      #(参数要放在[mysqld]模块下,且参数不能重复)
    [root@localhost 3306]# egrep "server-id|log-bin" /data/3307/my.cnf 
    #log-bin = /data/3307/mysql-bin
    server-id = 7

    /data/3307/mysql restart
    mysql -uroot -p123456 -S /data/3307/mysql.sock
    
    mysql> show variables like "server_id";
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | server_id     | 7     |
    +---------------+-------+
    1 row in set (0.00 sec)
    
    
    mysql> show variables like "log_bin";
    +---------------+-------+
    | Variable_name | Value |
    +---------------+-------+
    | log_bin       | OFF   |
    +---------------+-------+
    1 row in set (0.00 sec)


    #把从主库导出的数据恢复到从库
    cd /server/backup/
    gzip -d mysql_bak.2018-07-03.sql.gz (-d 解压后删除源文件)

    #还原数据库
    [root@localhost backup]# mysql -uroot -p123456 -S /data/3307/mysql.sock < mysql_bak.2018-07-03.sql

    提示:如果备份时使用了-A参数,则在还原数据到3307实例时,登录3307实例的密码也会和3306主库的密码一致,因为3307实例的授权表Mysql也被覆盖了 

    #登录3307从库,配置复制参数
    mysql -uroot -p123456 -S /data/3307/mysql.sock

    mysql> CHANGE MASTER TO MASTER_HOST='192.168.56.11', #主库的IP
    -> MASTER_PORT=3306, #主库的端口,从库端口可以和主库不同
    -> MASTER_USER='rep', #主库上建立的用于复制的用户rep
    -> MASTER_PASSWORD='123456', #rep用户的密码
    -> MASTER_LOG_FILE='mysql-bin.000001', #show master status时查看到的二进制日志文件名称,注意不能有空格
    -> MASTER_LOG_POS=334; #show master status时查看到的二进制日志偏移量,不能多空格
    Query OK, 0 rows affected (0.01 sec)

    提示:字符串用单引号括起来,数值不用引号,注意内容后面不能有空格

    #启动从库主从复制开关,并查看复制状态
    mysql -uroot -p'123456' -S /data/3307/mysql.sock -e "start slave;"

    [root@localhost backup]# mysql -uroot -p'123456' -S /data/3307/mysql.sock -e "show slave statusG;"

    [root@localhost backup]# mysql -uroot -p'123456' -S /data/3307/mysql.sock -e "show slave statusG;"| egrep "IO_Running|SQL_Running|_Behind_Master"
    Slave_IO_Running: Yes
    Slave_SQL_Running: Yes
    Seconds_Behind_Master: 0

    Slave_IO_Running: Yes
    #这个是I/O线程状态,I/O线程负责从从库到主库读取binlog日志,并写入从库的中继日志,状态为Yes表示I/O线程工作正常

    Slave_SQL_Running: Yes
    #这个是SQL线程状态,SQL线程负责读取中继日志(relay-log)中的数据并转换为SQL语句应用到从数据库中,状态为YES表示I/O线程工作正常

    Seconds_Behind_Master: 0
    #这个是复制过程中从库比主库延迟的秒数,这个参数很重要,但企业里更准确的判断主从延迟的方法为:在主库写时间戳,然后从库中读取时间戳,和当前数据库时间进行比较,从而认定是否延迟

    在主库上写入数据,然后观察从库的数据状况:
    mysql -uroot -p123456 -S /data/3306/mysql.sock -e "create database template;"

    [root@localhost backup]# mysql -uroot -p123456 -S /data/3307/mysql.sock -e "show databases like 'template';"
    +---------------------+
    | Database (template) |
    +---------------------+
    | template |
    +---------------------+

    mysql -uroot -p123456 -S /data/3306/mysql.sock -e "drop database template;"
    mysql -uroot -p123456 -S /data/3307/mysql.sock -e "show databases like 'template';"

    #根据测试可以判断,主从库是同步的

    #####生产场景下部署MySQL主从复制
    1、快速配置MySQL主从复制
    步骤如下:
    
    1、安装好要配置从库的数据库,配置好log-bin和server-id参数
    
    2、无需配置主库my.cnf文件,主库的log-bin和server-id参数默认就是配置好的
    
    3、登录主库,增加从库连接主库同步的账户,例如:rep,并授权replication slave 同步的权限
    
    4、使用曾经在半夜通过mysqldump 带-x和--master-data=1的命令及参数定时备份的全备数据文件,把它恢复到从库。
    
    5、在从库中执行change master to...语句,无需binlog文件及对应位置点
    
    6、从库开启同步开关,start slave
    
    7、从库show slave statusG,检查同步状态,并在主库进行更新测试。
    
    配置过程如下:
    1、半夜在主库上通过定时任务执行如下命令,备份导出主库数据: mysqldump -uroot -p123456 -S /data/3306/mysql.sock -A --events -B -x --master-data=1 | gzip >/opt/$(date +%F).sql.gz --master-data=1参数会在备份数据里增加如下语句 --Position to start replication or point-in-time recovery from CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000005',MASTER_LOG_POS=107; 2、白天找机会在需要做复制的从库上导入全备做从库,命令如下 gzip -d 2018-07-03.sql.gz mysql -uroot -p123456 -S /data/3308/mysql.sock < 2018-07-03.sql mysql -uroot -p123456 -S /data/3308/mysql.sock <<EOF CHANGE MASTER TO MASTER_HOST='192.168.56.11',MASTER_PORT=3306,MASTER_USER='rep',MASTER_PASSWORD='123456'; EOF 这里的CHANGE MASTER后面无需指定binlog文件名及具体位置,因为这部分已经在还原数据时提前应用到数据库里了(备份时--master-data=1的功劳) start slave; #开启主从复制开关 show slave statusG; #查看主从复制状态

    ######MYSQL主从复制线程状态说明及用途

    1、登录数据库查看MySQL线程的同步状态
    
    root@localhost ~]# mysql -u root -p123456 -S /data/3306/mysql.sock -e "show processlistG"
    *************************** 1. row ***************************
         Id: 6
       User: rep
       Host: 192.168.56.11:43114
         db: NULL
    Command: Binlog Dump
       Time: 3850
      State: Master has sent all binlog to slave; waiting for binlog to be updated
       Info: NULL
    
    提示:上述状态的意思是线程已经从binlog日志读取所有的更新,并已经发送到了从数据库服务器。线程目前为空闲状态,等待由主服务器上二进制日志中的新事件更新

    主库I/O线程工作状态

    主库I/O线程工作状态 解释说明
    Sending binlog event to slave 线程已经从二进制binlog日志读取了一个事件并且正将它发送到服务器
    Finished reading one binlog:switching to next binlog 线程已经读完二进制binlog日志文件,并且正打开下一个要发送到从服务器的binlog日志文件
    Has sent all binlog to slave;waiting for binlog to be updated 线程已经从binlog日志读取所有更新并已经发送到了从服务器。线程目前为空闲状态,等待由主服务器上二进制binlog日志中的新事件更新
    Waiting to finalize termination

    线程停止时发生的一个很简单的状态

    #登录从数据库查看Mysql线程工作状态

    从库有两个线程,即I/O和SQL线程。

    ##从库I/O线程的状态如下:

    [root@localhost ~]# mysql -u root -p123456 -S /data/3307/mysql.sock -e "show processlistG" 
    *************************** 1. row ***************************
         Id: 5
       User: system user
       Host: 
         db: NULL
    Command: Connect
       Time: 3918
      State: Waiting for master to send event
       Info: NULL

    从服务器I/O线程的State列的最常见状态。该状态也出现在Slave_IO_State列,由SHOW SLAVE STATUS显示

    从库I/O线程的工作状态 解释说明
    Connecting to master 线程正试图连接主服务器
    Checking master version 同主服务器之间建立连接后临时出现的状态
    Registering slave on master 同主服务器之间建立连接后临时出现的状态
    Requesting binlog dump 建立同主服务器之间的连接后临时出现的状态。线程向主服务器发送一条请求,索取从请求的二进制binlog日志文件名和位置开始的二进制binlog日志的内容
    Waiting to reconnect after a failed binlog dump request 如果二进制binlog日志转储请求失败,线程进入睡眠状态,然后定期尝试重新连接,可以使用--master-connect-retry 选项指定重试时间的间隔
    Reconnecting after a failed binlog dump request 线程正尝试重新连接主服务器
    Waiting for master to send event 线程已经连上主服务器,正等待二进制binlog日志事件到达
    Queueing master event to the relay log 线程已经读取一个事件,正将它复制到中继日志供SQL线程来处理  
    Waiting to reconnect after a failed master event read   读取时(由于没有连接)出现错误。线程试图重新连接前将睡眠master-connect-retry秒
    Reconnecting after failed master event read 线程正尝试重新连接主服务器。当连接重新重新建立后,状态变为Waiting for master to send event

    #从库SQL线程的状态如下:

    *************************** 2. row ***************************
    Id: 6
    User: system user
    Host: 
    db: NULL
    Command: Connect
    Time: 3077
    State: Slave has read all relay log; waiting for the slave I/O thread to update it
    Info: NULL

    从库SQL线程的状态

    从库SQL线程状态 解释说明
    Reading event from the relay log 线程已经从中继日志读取一个事件,可以对事件进行处理了
    Has read all relay log;waiting for the slave I/O thread to update it  线程已经处理了中继日志文件中的所有事件,现在正等待I/O线程将新事件写入中继日志
    Waiting for slave mutex on exit 线程停止时发生的一个很简单的状态
  • 相关阅读:
    discuz论坛X3升级时 文件下载出现问题,请查看您的服务器网络以及data目录是否有写权限
    discuz管理中心无法登陆
    在Windows 7下面IIS7的安装和 配置ASP的正确方法
    window.open
    linux下的vmware虚拟机如何回收虚拟磁盘空间
    CentOS7 安装lamp 3分钟脚本
    pyhon 编译C++安装需要 c99 模式
    条件判断
    python字符串杂项
    RIPv1&v2
  • 原文地址:https://www.cnblogs.com/Template/p/9260506.html
Copyright © 2011-2022 走看看