天天看点

1、MySql Docker主从复制(一主一从)

Docker 搭建 MySQL 主从复制(一主一从)

使用Docker来搭建MySQL主从复制是很快捷的,只需要拉取镜像,启动2个MySQL容器就行了。而且容器是互相独立的,每个容器都有自己的IP。

基于 Docker 来搭建 MySQL 的主从复制的步骤大致如下:

  1. 拉取MySQL的镜像(本次使用5.7,如果没有安装虚拟机和Docker的话,请自行安装好)
  2. 启动两个MySQL的容器,一主一从;
  3. 配置主服务器(Master)
  4. 配置从服务器(Slave)
  5. 完成Master和Slave链接,开始主从复制
  6. 测试配置是否成功

1、拉取镜像

拉取镜像:docker pull mysql:5.7
查看镜像:docker images
           

2、启动MySQL容器

2.1 命令启动两个MySQL

主Master:

docker run -d -p 3307:3306 --name mysql-master -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
           

命令解释:通过镜像 mysql:5.7 启动一个名为 mysql-master 的 MySQL 服务器,端口号是3306,映射的宿主机端口号是3307,root 账号密码是123456

从Slave:虚拟机的3308映射到容器的3306端口

docker run -d -p 3308:3306 --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
           

命令解释:通过镜像 mysql:5.7 启动一个名为 mysql-slave 的 MySQL 服务器,端口号是3306,映射的宿主机端口号是3308,root 账号密码是123456

启动完成之后,可以通过命令:docker ps 查看运行中的容器,docker ps -a 可以查看所有的容器,包括停止的。

2.2 查看两个容器的IP

命令:

docker inspect --format='{{.NetworkSettings.IPAddress}}' (容器名称|容器ID)
           

查看主Master的IP:

docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-master

#我这里的Master的IP是:172.17.0.4  这个值在后面要用到
           

查看从Slave的IP:

docker inspect --format='{{.NetworkSettings.IPAddress}}' mysql-slave

#我这里的Master的IP是:172.17.0.5
           

3、配置主服务器(Master)

首先,执行下面的命令,进入到 Master 服务器:

docker exec -it mysql-master /bin/bash

#这里的mysql-master是容器的名称,也可以是容器的ID,几乎所有的命令,名称和ID可以互用
           
service mysql status
#进入容器之后,可以使用该命令查看mysql的运行状态和版本,版本是 5.7.30。搭建主从复制时,最好保持版本的一致。

[email protected]:/# service mysql status
[info] MySQL Community Server 5.7.30 is running.
           

其次,修改配置文件:my.cnf,在/etc/mysql下面,有一个mysql的配置文件my.cnf,

[email protected]:/etc/mysql# cd /etc/mysql/
[email protected]:/etc/mysql# ls
conf.d	my.cnf	my.cnf.fallback  mysql.cnf  mysql.conf.d
           

执行命令,修改配置:

vi my.cnf
           

执行之后,可能会报错:bash: vi: command not found

此时就需要执行:apt-get install vim 命令安装vim,如果在这个过程中出现下面的错误:

Building dependency tree       
Reading state information... Done
E: Unable to locate package vim
           

就需要执行:apt-get update ,成功之后,然后再执行 apt-get install vim 命令安装vim

一切就绪之后,在my.cnf文件中添加下面的配置:

#[mysqld]这个不能漏掉了
[mysqld]
## 设置server_id,一般设置为IP,同一局域网内注意要唯一
server_id=1  
## 开启二进制日志功能,可以随便取,最好有含义(关键就是这里了)
log-bin=mysql-bin 
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql  
## 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M  
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed  
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7  
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062  
           

以上这些配置中,只有前面三个是必须要配置的,其他的可以不配置,有默认值的

添加配置,保存退出之后,需要重启mysql服务:

配置完成之后,需要重启mysql服务使配置生效。使用service mysql restart完成重启。

service mysql restart
           

重启mysql服务时会使得docker容器停止,我们还需要docker start mysql-master启动容器。

下一步在Master数据库创建数据同步用户,授予用户 slave REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据。

docker exec -it mysql-master /bin/bash 进入容器
mysql -uroot -p123456 登录mysql

CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
           

4、配置从服务器(Slave)

其他命令操作和Master是一样的,它的主要目的也是为了修改my.cnf配置文件,配置文件修改如下:

[mysqld]
## 设置server_id,一般设置为IP,注意要唯一
server_id=2
## relay_log配置中继日志
relay_log=mysql-relay-bin
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave1-bin
## 复制过滤:也就是指定哪个数据库不用同步(mysql库一般不同步)
binlog-ignore-db=mysql 
## 为每个session 分配的内存,在事务过程中用来存储二进制日志的缓存
binlog_cache_size=1M
## 主从复制的格式(mixed,statement,row,默认格式是statement)
binlog_format=mixed
## 二进制日志自动删除/过期的天数。默认值为0,表示不自动删除。
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## 防止改变数据(除了特殊的线程)
read_only=1
           

也只有前面三个配置是必须配置的,其他可以不用配置

配置完成后,同样要重启:service mysql restart,同样要重启容器:docker start mysql-slave

5、完成Master和Slave链接,开始主从复制

注意:需要保证 Master 和 Slave 除了不同步的数据库,其他数据库的数据要一致。

5.1 Master主服务器操作

在主Master,首先进入容器,然后进入Mysql数据库

执行命令:show master status;

[[email protected] ~]# docker exec -it mysql-master /bin/bash
[email protected]:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.30-log MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

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

mysql> 
           

**记录下 File 和 Position 字段的值,后面会用到。**在后面的操作完成之前,需要保证Master库不能做任何操作,否则将会引起状态变化,File和Position字段的值变化。

5.2 Slave从服务器操作

在主Master,首先进入容器,然后进入Mysql数据库

执行命令:

change master to master_host='172.17.0.4', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 617, master_connect_retry=30;

# master_host: Master 的IP地址
# master_user: 在 Master 中授权的用于数据同步的用户
# master_password: 同步数据的用户的密码
# master_port: Master的数据库的端口号,不是宿主机映射的端口号
# master_log_file: 指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值
# master_log_pos: 从哪个 Position 开始读,即上文中提到的 Position 字段的值
# master_connect_retry: 当重新建立主从连接时,如果连接失败,重试的时间间隔,单位是秒,默认是60秒。
           
[[email protected] ~]# docker exec -it mysql-slave /bin/bash
[email protected]:/# mysql -uroot -p123456
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.30-log MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> change master to master_host='172.17.0.4', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 617, master_connect_retry=30;
           

在 Slave 的 MySQL 终端执行查看主从同步状态:

show slave status \G;
           
mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 172.17.0.4
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 30
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 617
               Relay_Log_File: edu-mysql-relay-bin.000008
                Relay_Log_Pos: 367
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: mybatis_plus
           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: 617
              Relay_Log_Space: 744
              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: 1
                  Master_UUID: d6ae1b03-9f26-11ea-80e8-0242ac110004
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           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
         Replicate_Rewrite_DB: 
                 Channel_Name: 
           Master_TLS_Version: 
1 row in set (0.00 sec)
           

SlaveIORunning 和 SlaveSQLRunning 是No,表明 Slave 还没有开始复制过程。相反 SlaveIORunning 和 SlaveSQLRunning 是Yes表明已经开始工作了,因为我已经运行过了,所以我的显示的都是 Yes。

执行以下命令,开始开启主从同步:

start slave;
           

正常情况下,执行这个命令之后,SlaveIORunning 和 SlaveSQLRunning 就是Yes了。

slave stop; 关闭主从同步

reset slave; 重置主从同步

5.3 主从复制排错

使用

start slave

开启主从复制过程后,如果SlaveIORunning一直是Connecting,则说明主从复制一直处于连接状态,这种情况一般是下面几种原因造成的,我们可以根据 Last_IO_Error提示予以排除:

  1. 网络不通

    检查ip,端口

  2. 密码不对

    检查是否创建用于同步的用户和用户密码是否正确

  3. pos不对

    检查Master的 Position

6、测试主从同步

可以在主Master中创建数据库,然后新建数据库表,往表里插入数据,修改数据,删除数据等这些操作都会同步到从库中。

注意:

  • 操作从库,比如新增数据,修改数据等不会同步到主库的,主从复制是单向的,主库会影响从库,从库不会影响主库。
  • 查询操作是不会同步的。

下一次讲解:SpringBoot ,MyBatis Plus 项目中,怎么通过代码实现主从复制的读写分离操作。