Mysql之基于日志的主从复制

1.  Mysql主从复制

    1.  什么是mysql主从复制?

         mysql主从复制是mysql自带的功能,通过逻辑的binlog日志复制到要同步的服务器本地,然后由本地的线程读取日志里面的SQL语句,重新应用到mysql数据库中。

    2.  主从复制的结构

         单向复制:一主一从  一主两从  一主多从  多主一从  多主多从

         双向复制:互为主从

         链式复制:类似A-->B-->C

         环式复制:生产场景很少用

         在生产工作中,mysql主从复制都是异步的复制方式。不是严格的实时数据同步。

    3.  主从复制的应用场景

        1.  从服务器作为主服务器的实时数据备份

        2.  主从服务器实现读写分离,从服务器实现负载均衡LVS。

            从服务器仅仅处理用户的select查询请求,降低用户查询响应时间。

            对于更新的数据(update,insert,delete语句),交给主服务器处理。

            结构图:

            

       3.  把多个从服务器根据业务重要性进行拆分访问

            有为外部用户提供查询服务的从服务器,

            有内部DBA用来数据备份的从服务器,

            为内部人员提供访问的日志分析及供开发人员查询的从服务器。

            结构图:

            

        4.  实现mysql主从读写分离的方案

           1.  通过程序代码实现(PHP和java),生产应用场景最多。

           2.  通过开源的软件(mysql-proxy,amoeba)实现读写分离,这种方式稳定性差,生产不建议使用。

           3.  大型门户网站自己开发dbproxy。

2.  mysql主从复制原理

    1.  介绍

      mysql的主从复制是一个异步的复制过程,数据将从master复制到slave,由三个线程参与完成。其中sql线程和I/O线程在slave,另外一个I/O在master.  

      要实现mysql的主从复制,首先必须打开master的binlog记录功能,否则无法实现。因为整个复制过程就是slave从master获取binlog日志,然后在slave上以相同顺序执行获取的binlog日志中所记录的各种sql操作。

      要打开mysql的binlog记录功能,通过在mysql配置文件my.cnf中的mysqld模块增加"log-bin"参数选项来实现,具体如下:

      [mysqld]

      log-bin=/data/mysql/mysql-bin

    2.  mysql主从复制原理过程详细描述

      1)  master服务器上打开binlog记录功能。

      2)  在slave服务器执行start slave命令开启主从复制开关,开始进行主从复制。

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

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

      5)  当slave服务器的I/O线程获取到master服务器上I/O线程发送的日志内容,日志文件及位置后,会将binlog日志内容依次写到slave自身的relay log,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master新binlog日志时能够告诉master服务器从新binlog日志的指定文件及位置开始请求新的binlog日志内容。

      6)  slave的sql线程会实时监测relay log中的内容,把它解析成sql语句。

3.  mysql主从复制的配置过程

      1.  在主服务器上打开log-bin,在my.cnf配置文件的mysqld模块下。

          log-bin=/data/3306/mysql-bin 

          log-bin=/data/3307/mysql-bin(如果只是从数据库,不需要配置log-bin;如果是要做级联,需要打开log-bin)

      2.  配置主从的server-id,要不同啊。

          server-id=3306

          server-id=3307

      3.  配置好以后,要重启mysql服务。

          /data/3306/mysql restart

          /data/3307/mysql restart

      4.  检查配置参数后的结果。

          egrep "log-bin|server-id" /data/3306/my.cnf

          egrep "log-bin|server-id" /data/3307/my.cnf

      5.  登录数据库查看

          mysql -uroot -p -S /data/3306/mysql.sock

mysql> show variables like 'server_id';  查看server-id
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 3306  |
+---------------+-------+
1 row in set (0.94 sec)


mysql> show variables like 'log_bin';  查看binlog是否开启
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+
1 row in set (0.03 sec)

      6.  在主库创建用于主从复制的帐号

          grant replication slave on *.* to 'rep'@'192.168.0.%' identified by '123';

          flush privileges;

          查看一下select user,host from mysql.user;

          show grants for 'rep'@'192.168.0.%';

      7.  实现对主数据库锁表

          flush table with read lock;

      8.  备份主数据库服务器

          mysqldump -uroot -p -S /data/3306/mysql.sock --events -A -B | gzip >/opt/mysql_bak.$(date +%F).sql.gz

          -A  备份所有的库

          -B  直接覆盖原有的库

          mysqldump -uroot -p -A --master-data=2  > /tmp/crm2.sql  文件中会出现带有注释的-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=6245095;

          mysqldump -uroot -pJn9V2pI5\!0R8wY1L -A --master-data=1  > /tmp/crm1.sql  文件中会出现不带有注释的CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=6247969;

      9.  解锁主库

          unlock tables;

          查看主库的binlog的position

          show master status;

          show master logs;

      10.  把备份的数据库导入到从服务器上。

          使用scp或者rsync命令复制到从服务器上。

          rsync  -avz mysql_bak.2018-07-05.sql.gz /data/3307/

          gzip -d mysql_bak.2018-07-05.sql.gz

      11.  在从库上的操作,修改配置文件

          server-id 一定不能跟主相同,一定是唯一的。

          如果不做级联,就不用开启binlog,因为会消耗磁盘I/O

          有两种情况需要开启binlog:

          1.  级联

          2.  从库是备份服务器

      12.  在从服务器上还原备份的数据库

          mysql -uroot -p -S /data/3307/mysql.sock <mysql_bak.2018-07-05.sql 

      13.  在从服务器上,登录mysql,执行change master    

CHANGE MASTER TO 
MASTER_HOST='192.168.0.200',
MASTER_PORT=3306,
MASTER_USER='rep',
MASTER_PASSWORD='123',
MASTER_LOG_FILE='mysql-bin.000008',
MASTER_LOG_POS=406;

      14.  在从服务器上,也可以不登陆mysql,执行下面的命令   

mysql -uroot -p -S /data/3307/mysql.sock<<EOF
CHANGE MASTER TO 
MASTER_HOST='192.168.0.200',
MASTER_PORT=3306,
MASTER_USER='rep',
MASTER_PASSWORD='123',
MASTER_LOG_FILE='mysql-bin.000008',
MASTER_LOG_POS=406;
EOF

      15.  在从服务器上,登录mysql,执行

          start slave;

          show slave status\G;

          查看最关键的3个参数 

 Slave_IO_Running: Yes
 Slave_SQL_Running: Yes
 Seconds_Behind_Master: 0

      16.  在从服务器上,也可以不登陆mysql

          mysql -uroot -p /data/3307/mysql.sock -e "start slave;"

          mysql -uroot -p /data/3307/mysql.sock -e "show slave status\G;"

4.  一主多从 主宕机 从切换为主 继续同步

    1.  检查所有从库

        show processlist;

mysql> show processlist \G
*************************** 1. row ***************************
     Id: 10
   User: system user
   Host: 
     db: NULL
Command: Connect
   Time: 529
  State: Waiting for master to send event
   Info: NULL
*************************** 2. row ***************************
     Id: 11
   User: system user
   Host: 
     db: NULL
Command: Connect
   Time: 528
  State: Slave has read all relay log; waiting for the slave I/O thread to update it
   Info: NULL

    2.  检查所有从库的master.info

        看哪个更新,选择最大的bin-log和位置点

[root@nfs-server data]# cat master.info 
23
mysql-bin.000011
464
192.168.0.200
rep
123
3306
60
0





0
1800.000

0
a027a03c-7df9-11e8-92fc-000c296cbf3b
86400


0

    3.  确保所有relay log全部更新完毕

        在每个从库上执行stop slave io_thread;

        show processlist \G;  直到看到下面的信息

     Id: 11
   User: system user
   Host: 
     db: NULL
Command: Connect
   Time: 833
  State: Slave has read all relay log; waiting for the slave I/O thread to update it
   Info: NULL

    4.  登录从库

        stop slave;

        reset master

    5.  进入数据库数据目录,删除master.info relay-log.info

       检查授权表,清除read-only参数

    6.  开启bin-log,如果存在log-slave-updates read-only一定要注释掉

        /data/3307/mysql restart

    7.  如果主库没有宕机,需要去主库拉取binlog补全提升主库的从库

    8.  其他从库配置

        stop slave;    

CHANGE MASTER TO 
MASTER_HOST='192.168.0.200',  指向新的主库

        start slave;

        show slave status \G;

    9.  修改web前端代码的数据库连接串地址

    10.  修理损坏的主库,作为新主库的从库. 

5.  主从复制忽略数据库和表

    1.  在主库上指定主库二进制日志记录的库或忽略的库

vim  /etc/my.cnf
    ...
    binlog-do-db=xxxx   二进制日志记录的数据库
    binlog-ignore-db=xxxx 二进制日志中忽略数据库
    以上任意指定其中一行参数就行,如果需要忽略多个库,则添加多行

重启mysql

    2.  在从库上指定复制哪些库或者不负责哪些库

#编辑my.cnf,在mysqld字段添加如下内容:
  
replicate-do-db=test    设定需要复制的数据库
replicate-ignore-db 设定需要忽略的复制数据库
replicate-do-table  设定需要复制的表
replicate-ignore-table 设定需要忽略的复制表
replicate-wild-do-table 同replication-do-table功能一样,但是可以通配符
replicate-wild-ignore-table 同replication-ignore-table功能一样,但是可以加通配符
一库一行,一表一行
重启mysql服务

    3.  以上方法选其中之一即可。 

posted @ 2022-01-19 16:24  奋斗史  阅读(176)  评论(0)    收藏  举报