17.1 MySQL主从介绍


  •  MySQL主从又叫做Replication、AB复制。简单讲就是A和B两台机器做主从后,在A上写数据,另外一台B也会跟着写数据,两者数据实时同步的。

  •  MySQL主从是基于binlog的,主上须开启binlog才能进行主从。

 主从过程大致有3个步骤

 1)主将更改操作记录到binlog里

 2)从将主的binlog事件(sql语句)同步到从本机上并记录在relaylog里

 3)从根据relaylog里面的sql语句按顺序执行

 主上有一个log dump线程,用来和从的I/O线程传递binlog

 从上有两个线程,其中I/O线程用来同步主的binlog并生成relaylog,另外一个SQL线程用来把relaylog里面的sql语句落地


MySQL主从原理图

image.png

原理:从会把主的binlog搞到从上,从会根据binlog生成自己的一份中继日志,然后根据中继日志去执行响应的更改,最终达到数据同步一致。


主从的工作场景:

数据备份-->目的是防止主机器发生意外导致无法正常使用,从而将在主上备份到从上的数据迁移出来,从而使其继续服务运作。

数据备份且在从上读取数据-->从库作为读库,减轻主库读的压力。




17.2 准备工作

准备2台Linux服务器,分别作为主库,从库。

centos7-01主库,centos7-02从库

截图

目的是让2台机器都正常启动mysql,方便后面做实验




17.3 主从配置——配置主

设置主的参数,

1 修改my.cnf,增加server-id=128和log_bin=aminglinux1

[root@centos7-01 src]# vim /etc/my.cnf

 

[mysqld]
datadir=/data/mysql
socket=/tmp/mysql.sock
server-id=128
log_bin=aminglinux1

参数解释:

sever-id为自定义,这里定义的是ip的后缀,方便标记

log_bin名称不能有错误,它是binlog的前缀,不然重启的时候会出现报错。


2 重启mysql

[root@centos7-01 src]# /etc/init.d/mysqld restart
Shutting down MySQL.. SUCCESS! 
Starting MySQL.. SUCCESS!

2.1 重启mysqld后,可以看看data产生的文件

[root@Centos7-01 mysql]# ls -lt /data/mysql/
总用量 110632
-rw-rw---- 1 mysql mysql 50331648 5月  16 21:38 ib_logfile0
-rw-rw---- 1 mysql mysql 12582912 5月  16 21:38 ibdata1
-rw-rw---- 1 mysql mysql    12337 5月  16 21:38 Centos7-01.err
-rw-rw---- 1 mysql mysql        6 5月  16 21:38 Centos7-01.pid
-rw-rw---- 1 mysql mysql      120 5月  16 21:38 aminglinux1.000001
-rw-rw---- 1 mysql mysql       21 5月  16 21:38 aminglinux1.index
-rw-rw---- 1 mysql mysql       56 5月  16 21:32 auto.cnf
drwx------ 2 mysql mysql     4096 5月  16 21:28 mysql
drwx------ 2 mysql mysql     4096 5月  16 21:28 performance_schema
-rw-rw---- 1 mysql mysql 50331648 5月  16 21:28 ib_logfile1
drwx------ 2 mysql mysql        6 5月  16 21:28 test

分析:

其中前缀aminglinux1是binlog文件

aminglinux1.index 索引文件,这个文件必须要有

aminglinux1.000001二进制文件,这个随后还会产生00002,000003....如此类推 

aminglinux1这类文件是实现主从的根本,如果没有aminglinux1这类文件,主从是没办法完成的。

2.2 创建实验数据(此步骤根据实际情况来定义,可做可不做)

[root@Centos7-01 mysql]# mkdir blog
[root@Centos7-01 mysql]# touch 1.txt 2.txt 3.txt 
[root@Centos7-01 mysql]# mv 1.txt 2.txt 3.txt ./blog/
[root@Centos7-01 mysql]# mkdir zrlog1
[root@Centos7-01 mysql]# mkdir mysql2
[root@Centos7-01 mysql]# du -sh mysql2/
64Kmysql2/
[root@Centos7-01 mysql]# du -sh zrlog1/
48Kzrlog1/

2.3 在blog目录的基础上再备份一个出来


[root@Centos7-01 mysql]# mysqldump -uroot -paminglinux blog > /tmp/blog.sql

2.4 创建新库aming,并把刚刚备份的数据恢复至aming

创建新库aming

[root@Centos7-01 mysql]# mysql -uroot -paminglinux -e "create database aming"
Warning: Using a password on the command line interface can be insecure.

2.5 把刚刚备份的数据恢复至aming

[root@Centos7-01 mysql]# mysql -uroot -paminglinux aming < /tmp/blog.sql 
Warning: Using a password on the command line interface can be insecure.

2.6 以aming这个库作为主从参考对象

[root@Centos7-01 mysql]# ls -lt
总用量 110632
drwx------ 2 mysql mysql       20 5月  16 22:07 aming
-rw-rw---- 1 mysql mysql      359 5月  16 22:07 aminglinux1.000001

恢复完数据后,可以看得出aminglinux1.000001这个文件容量在慢慢增大


3 创建用作同步数据的用户

进入mysql
mysql>grant replication slave on *.* to 'repl'@192.168.189.129 identified by 'aminglinux111';

解释:

replication slave          给与从权限

*.*                 所有的库,所有的表

'repl'               针对这个用户

@slave_ip             针对从的ip

 identified by 'password'     密码

4 锁表,让数据停止更新(主从配置完成后,需要开启)

mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)

5 查看主的状态

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

记住File和Position的参数内容,稍后会用上它。

6 同步数据库

其中mysql目录不做备份,因为里面太多密码文件,涉及安全性。

[root@Centos7-01 mysql]# ls -lt
总用量 110632
drwxr-xr-x 2 root  root        45 5月  16 22:39 zrlog1
drwxr-xr-x 2 root  root        58 5月  16 22:38 mysql2
-rw-rw---- 1 mysql mysql      571 5月  16 22:23 aminglinux1.000001
drwx------ 2 mysql mysql       20 5月  16 22:07 aming
drwxr-xr-x 2 root  root        45 5月  16 21:57 blog
-rw-rw---- 1 mysql mysql 50331648 5月  16 21:38 ib_logfile0
-rw-rw---- 1 mysql mysql 12582912 5月  16 21:38 ibdata1
-rw-rw---- 1 mysql mysql    12337 5月  16 21:38 Centos7-01.err
-rw-rw---- 1 mysql mysql        6 5月  16 21:38 Centos7-01.pid
-rw-rw---- 1 mysql mysql       21 5月  16 21:38 aminglinux1.index
-rw-rw---- 1 mysql mysql       56 5月  16 21:32 auto.cnf
drwx------ 2 mysql mysql     4096 5月  16 21:28 mysql
drwx------ 2 mysql mysql     4096 5月  16 21:28 performance_schema
-rw-rw---- 1 mysql mysql 50331648 5月  16 21:28 ib_logfile1
drwx------ 2 mysql mysql        6 5月  16 21:28 test

同步数据库mysql2,zrlog1

[root@Centos7-01 mysql]# mysqldump -uroot -paminglinux mysql2 > /tmp/my2.sql
Warning: Using a password on the command line interface can be insecure.
[root@Centos7-01 mysql]# mysqldump -uroot -paminglinux zrlog1 > /tmp/zr1.sql
Warning: Using a password on the command line interface can be insecure.




17.4 主从配置——配置

1 设置从的参数

增加server-id,不需要填写bin_log

[root@Centos7-02 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/tmp/mysql.sock
server-id=129


1.1 增加完server-id之后,重启服务

[root@Centos7-02 ~]# /etc/init.d/mysqld stop
Shutting down MySQL.. SUCCESS! 
[root@Centos7-02 ~]# /etc/init.d/mysqld start
Starting MySQL. SUCCESS!

2 把刚刚做的主上库同步到从上

[root@Centos7-02 ~]# scp 192.168.189.128:/tmp/*.sql /tmp/
blog.sql                           100% 1258   941.3KB/s   00:00    
my2.sql                            100% 1260   963.6KB/s   00:00    
zr1.sql                            100% 1260     1.2MB/s   00:00

3 进入mysql创建4个库:aming,zrlog1,blog,mysql2.

mysql> create database aming;
Query OK, 1 row affected (0.00 sec)
mysql> create database zrlog1;
Query OK, 1 row affected (0.00 sec)
mysql> create database blog;
Query OK, 1 row affected (0.01 sec)
mysql> create database mysql2;
Query OK, 1 row affected (0.00 sec)


4 创建库后,恢复数据-->指定数据至指定的名称,

[root@Centos7-02 ~]# mysql -uroot blog < /tmp/blog.sql 
[root@Centos7-02 ~]# mysql -uroot zrlog1 < /tmp/zr1.sql 
[root@Centos7-02 ~]# mysql -uroot aming< /tmp/blog.sql 
[root@Centos7-02 ~]# mysql -uroot mysql2< /tmp/my2.sql

4.1 主和从的mysql建立的数据都要一致(针对刚刚创建的4个库)

[root@Centos7-02 mysql]# ls -lt /data/mysql/
总用量 110644
drwx------. 2 mysql mysql       20 5月  16 23:27 mysql2
drwx------. 2 mysql mysql       20 5月  16 23:25 blog
drwx------. 2 mysql mysql       20 5月  16 23:25 zrlog1
drwx------. 2 mysql mysql       20 5月  16 23:25 aming
[root@Centos7-01 mysql]# ls -lt
总用量 110632
drwxr-xr-x 2 root  root        45 5月  16 22:39 zrlog1
drwxr-xr-x 2 root  root        58 5月  16 22:38 mysql2
-rw-rw---- 1 mysql mysql      571 5月  16 22:23 aminglinux1.000001
drwx------ 2 mysql mysql       20 5月  16 22:07 aming
drwxr-xr-x 2 root  root        45 5月  16 21:57 blog

因为从上面是没有bin_log文件的所以,aminglinux1.000001只会在主上,不会出现在从上。


5 实现主从

5.1 登录mysql

mysql> stop slave;

5.2 实现主从关键一步的命令

mysql> change master to master_host='192.168.189.128', master_user='repl', master_password='aminglinux111', master_log_file='aminglinux1.000001', master_log_pos=571;
Query OK, 0 rows affected, 2 warnings (0.03 sec)

******主上的show mater status信息 

+--------------------+----------+--------------+------------------+-------------------+
| File               | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+--------------------+----------+--------------+------------------+-------------------+
| aminglinux1.000001 |      571 |              |                  |                   |
+--------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)



解释:

master_host=''主的ip

master_user='repl'主的用户

master_password=''住的用户密码

master_log_file='', 主的日志文件(show master status的file)

master_log_pos=xx,主的日日志position(show master status的position),此处的数值不用加''符号

5.3 启动从

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

5.4 判断主从是否配置成功

mysql> show slave status;
mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.189.128
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: aminglinux1.000001
          Read_Master_Log_Pos: 571
               Relay_Log_File: Centos7-02-relay-bin.000002
                Relay_Log_Pos: 285
        Relay_Master_Log_File: aminglinux1.000001
             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: 571
              Relay_Log_Space: 463
              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: 128
                  Master_UUID: a69f92e6-590d-11e8-a239-000c2916c3f2
             Master_Info_File: /data/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
           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
1 row in set (0.00 sec)

内容解释:

特别关注这两个参数,两个Yes为成功简历主从状态,如果其中一个不是Yes都不是正确的状态。

Slave_IO_Running: Yes

Slave_SQL_Running: Yes

如果发现其中一个状态为Connecting的,请前往链接:https://blog.51cto.com/13578154/2117258 根据实际环境进行参考解决

Seconds_Behind_Master: 0  //为主从延迟的时间

Last_IO_Errno: 0

Last_IO_Error:

Last_SQL_Errno: 0

Last_SQL_Error:


6 到主上执行 unlock tables

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


总结从上操作:

  • sever-id 跟主不同

  • 主数据同步到从上 

  • stop,change,start 三个动作

  • 主上执行unlock tables




17.5 测试主从同步


1 假如在从上删掉aming库,可能导致主从不一致

mysql>drop database aming;
Query OK, 0 rows affected (0.03 sec)


2 检查从的状态

mysql> show slave status\G
Slave_IO_Running: Yes
Slave_SQL_Running: Yes

从状态虽然显示没出现问题,但是理论主从是不一致的,

3 再到主上drop aming库操作,

mysql> drop database aming;
Query OK, 0 rows affected (0.00 sec)

4 回到从上检查状态

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.189.128
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: aminglinux1.000001
          Read_Master_Log_Pos: 658
               Relay_Log_File: Centos7-02-relay-bin.000002
                Relay_Log_Pos: 285
        Relay_Master_Log_File: aminglinux1.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: 
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1008
                   Last_Error: Error 'Can't drop database 'aming'; database doesn't exist' on query. 
Default database: 'aming'. Query: 'drop database aming'

可以看到两个Yes状态其中SQL已经是No了,

而且还有错误信息:aming库不存在。-->因为在从上已经把database干掉了,所以在主上删除,

此时aming库不存在的,所以不能被删除的。

如果遇到问题,主从会马上断掉。

5 修复方法:

两种方法

5.1 第一种是:stop slave,start slave.

5.2 第二种是:重新做主从

5.2.1 在主上获取主的状态信息

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

5.2.2 从上操作

先停止slave


mysql> stop slave;

再change

mysql> change master to master_host='192.168.189.128', master_user='repl', master_password='aminglinux111', master_log_file='aminglinux1.000001', master_log_pos=658;

然后start slave

mysql> start slave;

查看slave状态

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.189.128
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: aminglinux1.000001
          Read_Master_Log_Pos: 658
               Relay_Log_File: Centos7-02-relay-bin.000002
                Relay_Log_Pos: 285
        Relay_Master_Log_File: aminglinux1.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

Slave_IO_Running和Slave_SQL_Running的状态都是Yes,成功再次主从同步。


总结:

假如主从同步出错了,需要进行再次做主从的前提是,需要保持数据都要一致,

如果数据不一致,需要重新做多次备份同步,然后再change master。 


可以在my.cnf定义的几个配置参数

主服务器上
 binlog-do-db=      //仅同步指定的库
 binlog-ignore-db= //忽略指定库
 从服务器上
 replicate_do_db=
 replicate_ignore_db=
 replicate_do_table=
 replicate_ignore_table=
 replicate_wild_do_table=   //如aming.%, 支持通配符% 
 replicate_wild_ignore_table=