Mysql主从复制(重置版)

  MySQL Replication是Mysql自带的一种功能,能够实现将数据从一台数据库服务器(master)复制到一台或多台数据库服务器(slave),默认状况下属于异步复制,无需维持长链接。经过配置能够复制全部的库或者其中几个库,又或者库中的一部分表。
(1).工做原理
  简单的说就是master服务器将数据库的改变写入二进制日志(binary log),slave服务器同步这些二进制日志事件(binary log events)到它的中继日志(relay log),而后slave服务器重作中继日志中的事件进行数据操做。
  注意:是由slave服务器开启一个I/O线程拉取数据。单master对单slave状况下slave服务器上压力更大,但单master对多slave状况下master服务器上压力更大。
(2).做用
  1.故障切换
  2.备份服务,没法对SQL语句执行产生的故障恢复,有限的备份
  3.高性能,能够多台slave,实现读写分离
(3).常见方案
  1.一主多从,一个master对应多个slave,I/O压力集中在master上。
  2.M-S-S,中间那个S是slave中继,为了缓解master服务器的I/O压力在中间加了一个slave中继。
  3.M-M,双主互备,互为主从
  4.M-M-M,基本没用
  5.一从多主,这是为了节约成本,将多个master数据自动整合,但数据修改会很是多,从服务器压力大。html

(4)主从复制时mysql配置文件会遇到的相关参数mysql

server-id = 1 数据库的ID号,值必须为1到2^32–1之间的一个正整数值,且惟一。master和slave都必须存在。
log-bin=mysql-bin 启用并指定二进制日志文件,能够是相对路径(基于datadir),也能够是绝对路径。master必须存在,slave能够存在。
relay_log=mysql-relay-bin 启用并指定中继日志,能够是相对路径(基于datadir),也能够是绝对路径。slave参数。
log-slave-updates=1 将复制事件写入本身的二进制日志。slave参数。
read_only=1 数据库只读,slave参数,通常用于读写分离时使用。
sync-binlog=1 实时写入二进制日志文件与磁盘同步
binlog-format=[STATEMENT|ROW|MIXED] 三个值分别表明基于SQL语句复制(STATEMENT),基于行的复制(ROW),混合模式复制(MIXED)。详细查看:http://www.javashuo.com/article/p-buidscij-ba.html sql

 

若是如下两个参数都没指定,则slave默认复制全部数据库
binlog-do-db=data 同步的二进制数据库名,master参数
binlog-ignore-db=mysql 不一样步的二进制数据库名,master参数数据库

 

explicit_defaults_for_timestamp=true 这是为了取消TIMESTAMP字符类型(时间戳)随更新而自动更新的操做(必须在建立timestamp字符类型前写入配置文件,不然须要修改列参数),默认是off,没用到TIMESTAMP字符类型不用设置。explicit_defaults_for_timestamp参数详细查看:http://www.javashuo.com/article/p-orfwkmfp-k.htmlvim

 

slave-skip-errors有四个可选值,off、all、ddl_exist_errors和错误代码([list of error codes]),默认为off
slave-skip-errors=1062,1053 跳过指定错误代码的错误,继续执行复制
slave-skip-errors=all 跳过全部错误
slave-skip-errors=ddl_exist_errors 这是一系列错误代码:1007,1008,1050,1051,1054,1060,1061,1068,1094,1146
说明:
  1007:数据库已存在,建立数据库失败
  1008:数据库不存在,删除数据库失败
  1050:数据表已存在,建立数据表失败
  1050:数据表不存在,删除数据表失败
  1054:字段不存在,或程序文件跟数据库有冲突
  1060:字段重复,致使没法插入
  1061:重复键名
  1068:定义了多个主键
  1094:位置线程ID
  1146:数据表缺失,请恢复数据库服务器

(4).部署M-S(一主一从)异步

实验环境:youxi1  192.168.5.101  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Master
     youxi2  192.168.5.102  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Slavetcp

1)master服务器上的操做ide

  建立一个用于复制所需的用户性能

mysql> grant replication slave on *.* to repl@192.168.5.102 identified by '12345678';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> flush privileges;  //刷新权限表

  建立一个用于复制的数据库

mysql> create database test_db;
Query OK, 1 row affected (0.00 sec)

  修改配置文件,在[mysqld]模块下操做。而后重启mysqld

[root@youxi1 ~]# vim /etc/my.cnf
server-id=1  //添加或修改
log-bin=mysql-bin-master
binlog-do-db=test_db
slave-skip-errors=all  //我的建议跳过错误,这样slave就不会运行这些错误语句 [root@youxi1 ~]# systemctl restart mysqld

  查看master状态,记录当前日志文件名和当前节点。

mysql> show master status\G  //这是查看master的状态
*************************** 1. row ***************************
             File: mysql-bin-master.000001  //当前日志文件
         Position: 154  //当前节点
     Binlog_Do_DB: test_db  //同步的数据库
 Binlog_Ignore_DB:   //不一样步的数据库
Executed_Gtid_Set: 
1 row in set (0.00 sec)

mysql> show binlog events\G  //这是查看二进制日志信息
*************************** 1. row ***************************
   Log_name: mysql-bin-master.000001  //日志文件名
        Pos: 4  //开始节点
 Event_type: Format_desc  //事件类型
  Server_id: 1  //执行服务器标识
End_log_pos: 123  //结束节点
       Info: Server ver: 5.7.16-log, Binlog ver: 4  //信息,更多的是执行的SQL语句
*************************** 2. row ***************************
   Log_name: mysql-bin-master.000001
        Pos: 123
 Event_type: Previous_gtids
  Server_id: 1
End_log_pos: 154
       Info: 
2 rows in set (0.00 sec)

说明:show binlog events [IN 'log_name'] [FROM pos] [LIMIT [offset,] row_count]
    IN 'log_name' 指定要查询的binlog文件名(不指定就是第一个binlog文件)
    FROM pos 指定从哪一个pos起始点开始查起(不指定就是从整个文件首个pos点开始算)
    LIMIT [offset,] 偏移量(不指定就是0)
    row_count 查询总条数(不指定就是全部行)

  注意:若是防火墙是打开的,记得添加mysql的端口号。

[root@youxi1 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp
success
[root@youxi1 ~]# firewall-cmd --reload 
success
[root@youxi1 ~]# firewall-cmd --zone=public --list-ports 
3306/tcp

 2)slave服务器上的操做

  master和slave必须保证数据库版本一致,复制的数据库在二进制日志记录操做前如出一辙。

  创建与master须要复制的如出一辙的数据库,能够从master导出再导入到slave,也能够手动建立。

mysql> create database test_db;
Query OK, 1 row affected (0.01 sec)

  修改配置文件,在[mysqld]模块下操做。而后重启mysqld。

[root@youxi2 ~]# vim /etc/my.cnf
server-id=2    //若是没有更多的需求(例如M-S-S,M-M,读写分离,MHA等),这样就能够了
[root@youxi2 ~]# systemctl restart mysqld

  指定master的配置信息

mysql> stop slave;  //若是是第一次配置slave,能够不须要
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> change master to master_host='192.168.5.101',  //master的IP地址
    -> master_port=3306,   //端口号,默认3306
    -> master_user='repl',  //用户名
    -> master_password='12345678',  //密码
    -> master_log_file='mysql-bin-master.000001',  //从哪一个二进制日志文件读取
    -> master_log_pos=154;  //从二进制日志文件的哪一个pos点开始读取
Query OK, 0 rows affected, 2 warnings (0.06 sec)
//若是没有master_log_file和master_log_pos则默认从第一个二进制日志文件的0pos点开始
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

  注意:若是在出错后从新配置master信息,这时master的IP地址、端口号、用户名、密码没有改变能够不用从新配置,只需指定master_log_file和master_log_pos便可。

  查看slave的状态

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.101
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-master.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: youxi2-relay-bin.000003
                Relay_Log_Pos: 327
        Relay_Master_Log_File: mysql-bin-master.000001
             Slave_IO_Running: Yes  //这两行都是Yes时就是配置正确了
            Slave_SQL_Running: Yes

3)测试

  在master上建立表,并添加数据

mysql> use test_db;
Database changed
mysql> create table user_id(id int,name varchar(20));
Query OK, 0 rows affected (0.05 sec)

mysql> insert into user_id values(1,'zhangsan');
Query OK, 1 row affected (0.02 sec)

  在slave上查看

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
+------+----------+
1 row in set (0.00 sec)

(5).部署M-M

  M-M其实就是基于M-S再作一个反向主从。我就接着上面的M-S往下作了

1)在youxi2(原salve)上操做

  建立复制用户

mysql> grant replication slave on *.* to repl@192.168.5.101 identified by '12345678';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> flush privileges;      
Query OK, 0 rows affected (0.00 sec)

  修改配置文件,在[mysqld]模块下操做。而后重启mysqld。

[root@youxi2 ~]# vim /etc/my.cnf
log-bin=mysql-bin-slave  //添加或修改
binlog-do-db=test_db
[root@youxi2 ~]# systemctl restart mysqld

  查看master状态

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin-slave.000001
         Position: 154
     Binlog_Do_DB: test_db
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

  注意:若是防火墙是打开的,记得添加mysql的端口号。

[root@youxi2 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp
success
[root@youxi2 ~]# firewall-cmd --reload 
success
[root@youxi2 ~]# firewall-cmd --zone=public --list-ports 
3306/tcp

2)在youxi1(原master)上操做

  指定master配置信息

mysql> stop slave;  //若是第一次配置slave,能够不须要
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> change master to master_host='192.168.5.102',master_user='repl',master_password='12345678',master_log_file='mysql-bin-slave.000001',master_log_pos=154;
Query OK, 0 rows affected, 2 warnings (0.02 sec)

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

  查看slave状态

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.102
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-slave.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: youxi1-relay-bin.000002
                Relay_Log_Pos: 326
        Relay_Master_Log_File: mysql-bin-slave.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

3)测试

  在youxi2上插入数据

mysql> use test_db;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> insert into user_id values(2,'lisi');
Query OK, 1 row affected (0.01 sec)

  在youxi1上查看

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
|    2 | lisi     |
+------+----------+
2 rows in set (0.01 sec)

(6).部署M-S-S

实验环境:youxi1  192.168.5.101  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Master
     youxi2  192.168.5.102  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Slave中继
     youxi3  192.168.5.103  CentOS7.5  Mysql5.7.16  Mysql端口3306  作Slave

1)master服务器上的操做

  建立一个用于复制所需的用户

mysql> grant replication slave on *.* to repl@192.168.5.102 identified by '12345678';
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> flush privileges;  //刷新权限表

  建立一个用于复制的数据库

mysql> create database test_db;
Query OK, 1 row affected (0.00 sec)

  修改配置文件,在[mysqld]模块下操做。而后重启mysqld

[root@youxi1 ~]# vim /etc/my.cnf
server-id=1
log-bin=mysql-bin-master
binlog-do-db=test_db
sync-binlog=1
binlog-format=row
[root@youxi1 ~]# systemctl restart mysqld

  查看master状态,记录当前日志文件名和当前节点

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin-master.000001
         Position: 154
     Binlog_Do_DB: test_db
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

mysql> show binlog events\G
*************************** 1. row ***************************
   Log_name: mysql-bin-master.000001
        Pos: 4
 Event_type: Format_desc
  Server_id: 1
End_log_pos: 123
       Info: Server ver: 5.7.16-log, Binlog ver: 4
*************************** 2. row ***************************
   Log_name: mysql-bin-master.000001
        Pos: 123
 Event_type: Previous_gtids
  Server_id: 1
End_log_pos: 154
       Info: 
2 rows in set (0.01 sec)

  注意:若是防火墙是打开的,记得添加mysql的端口号。

[root@youxi1 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp
success
[root@youxi1 ~]# firewall-cmd --reload 
success
[root@youxi1 ~]# firewall-cmd --zone=public --list-ports 
3306/tcp

2)在slave中继服务器上的操做

  slave中继服务器是master服务器的从服务器,也是slave服务器的主服务器,因此其自己便是从,又是主。

  建立一个用于复制的用户

mysql> grant replication slave on *.* to repl@192.168.5.103 identified by '12345678';
Query OK, 0 rows affected, 1 warning (0.01 sec)

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

  创建与master服务器相同的数据库,能够从master导出再导入到slave,也能够手动建立。

mysql> create database test_db;
Query OK, 1 row affected (0.00 sec)

  修改配置文件,由于是slave中继服务器,自己并不会产生数据,因此二进制日志文件里都是从master服务器上拉取的事件,也就没有指定同步或不一样步的数据库。

[root@youxi2 ~]# vim /etc/my.cnf
server-id=2
log-bin=mysql-bin-slave1  //开启二进制日志文件
log-slave-updates=1  //复制事件写入到二进制日志文件
binlog-format=row
[root@youxi2 ~]# systemctl restart mysqld

  指定master的配置信息

mysql> stop slave;  //若是是第一次配置slave,能够不须要
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> change master to master_host='192.168.5.101',  //master的IP地址
    -> master_user='repl',  //用户名
    -> master_password='12345678',  //密码
    -> master_log_file='mysql-bin-master.000001',  //从哪一个二进制日志文件读取
    -> master_log_pos=154;  //从二进制日志文件的哪一个pos点开始读取
Query OK, 0 rows affected, 2 warnings (0.06 sec)
//若是没有master_log_file和master_log_pos则默认从第一个二进制日志文件的0pos点开始
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

  查看master状态,记录当前日志文件名和当前节点

mysql> show master status\G
*************************** 1. row ***************************
             File: mysql-bin-slave1.000001
         Position: 322
     Binlog_Do_DB: 
 Binlog_Ignore_DB: 
Executed_Gtid_Set: 
1 row in set (0.00 sec)

  查看slave状态

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.101
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-master.000001
          Read_Master_Log_Pos: 154
               Relay_Log_File: youxi2-relay-bin.000002
                Relay_Log_Pos: 327
        Relay_Master_Log_File: mysql-bin-master.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

  注意:若是防火墙是打开的,记得添加mysql的端口号。

[root@youxi2 ~]# firewall-cmd --permanent --zone=public --add-port=3306/tcp
success
[root@youxi2 ~]# firewall-cmd --reload 
success
[root@youxi2 ~]# firewall-cmd --zone=public --list-ports 
3306/tcp

3)配置slave服务器

  建立和master同样的数据库,能够从master导出再导入到slave,也能够手动建立。

mysql> create database test_db;
Query OK, 1 row affected (0.00 sec)

  修改配置文件,在[mysqld]模块下操做。而后重启mysqld。

[root@youxi3 ~]# vim /etc/my.cnf
server-id = 3
binlog-format=row
[root@youxi3 ~]# systemctl restart mysqld

  指定master的配置信息

mysql> stop slave;  //若是是第一次配置slave,能够不须要
Query OK, 0 rows affected, 1 warning (0.00 sec)
 
mysql> change master to master_host='192.168.5.102',  //master的IP地址
    -> master_user='repl',  //用户名
    -> master_password='12345678',  //密码
    -> master_log_file='mysql-bin-slave1.000001',  //从哪一个二进制日志文件读取
    -> master_log_pos=322;  //从二进制日志文件的哪一个pos点开始读取
Query OK, 0 rows affected, 2 warnings (0.06 sec)
//若是没有master_log_file和master_log_pos则默认从第一个二进制日志文件的0pos点开始
mysql> start slave;
Query OK, 0 rows affected (0.02 sec)

  查看slave的状态

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.102
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-slave1.000001
          Read_Master_Log_Pos: 322
               Relay_Log_File: youxi3-relay-bin.000005
                Relay_Log_Pos: 327
        Relay_Master_Log_File: mysql-bin-slave1.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

4)测试

  在master服务器上建立表,并添加数据

mysql>  use test_db;
Database changed
mysql> create table user_id(id int,name varchar(20));
Query OK, 0 rows affected (0.03 sec)

mysql> insert into user_id values(1,'zhangsan');
Query OK, 1 row affected (0.05 sec)

  在slave中继服务器上查看

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
+------+----------+
1 row in set (0.00 sec)

  在slave服务器上查看

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
+------+----------+
1 row in set (0.00 sec)

5)若是不想slave中继服务器同步数据,但又不影响slave服务器该怎么作

  首先修改slave中继服务器上表的引擎为黑洞引擎

mysql> set sql_log_bin=off;  //关闭二进制日志
Query OK, 0 rows affected (0.00 sec)

mysql> alter table test_db.user_id ENGINE=blackhole;
Query OK, 1 row affected (0.03 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> set sql_log_bin=on;  //打开二进制日志
Query OK, 0 rows affected (0.00 sec)

  而后查看下slave服务器的slave状态

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.5.102
                  Master_User: repl
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin-slave1.000001
          Read_Master_Log_Pos: 776
               Relay_Log_File: youxi3-relay-bin.000006
                Relay_Log_Pos: 327
        Relay_Master_Log_File: mysql-bin-slave1.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes

  再到master服务器上插入数据测试

mysql> insert into user_id values(2,'lisi');
Query OK, 1 row affected (0.02 sec)

  查看slave中继服务器的数据

mysql> select * from test_db.user_id;
Empty set (0.00 sec)

  查看slave服务器数据

mysql> select * from test_db.user_id;
+------+----------+
| id   | name     |
+------+----------+
|    1 | zhangsan |
|    2 | lisi     |
+------+----------+
2 rows in set (0.00 sec)

(7).扩展:mysql的1593报错

  在作主从复制时,因为我是克隆的服务器,致使了mysql的uuid相同,因此出现了1593报错。

  当出现1593报错时,使用SHOW VARIABLES LIKE '%server_%';查看两个mysql的id和uuid。若是是server_id相同,进入/etc/my.cnf修改server_id的值。若是是server_uuid相同,使用SELECT uuid();随机获取一个uuid,而后进入$datadir/auto.cnf修改uuid的值。最后都须要重启mysqld。

相关文章
相关标签/搜索