MySQL-主从复制

MySQL 主从复制

以下是 linux 版本的搭建

简介

以下来自另一篇 blog

基本原理

slave 会从 master 读取 binlog 来进行数据同步

三步骤

  1. master 将该表记录到二进制日志 (binary log). 这些记录过程叫做二进制日志事件, binary log events;
  2. slave 将 master 的 binary log events 拷贝到它的中继日志 (relay log);
  3. slava 重做中继日志中的事件, 将改变应用到自己的数据库中. MySQL 复制是异步的且串行化的

基本规则

  • 每个 slave 只有一个 master
  • 每个 slave 只能有一个唯一的服务器 ID
  • 每个 master 可以有多个 slave

最大问题

延时

搭建步骤

启动服务

首先在 docker 中启动两个 MySQL 服务, 这里使用的是 5.7 版本

1
2
3
4
yiqings-laptop:~ yiqing$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
747fe7f90035 2c9028880e58 "docker-entrypoint.s…" 3 hours ago Up 3 hours 3306/tcp, 33060/tcp, 0.0.0.0:3307->3307/tcp, :::3307->3307/tcp mysql-slave
7df9dd80af21 2c9028880e58 "docker-entrypoint.s…" 2 months ago Up 6 minutes 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql

修改主库

  1. 首先进入主库, 修改 my.cnf 文件
1
vim /etc/mysql/my.cnf

如果没有 vim 命令, 需要安装

1
2
apt-get update # 更新软件源列表
apt-get -y install vim # 安装 vim
  1. 在 my.cnf 文件中添加
1
2
3
4
5
6
7
8
9
[mysqld]
#开启log-bin二进制日志
log-bin=/var/log/mysql/mysql-bin
#配置唯一的服务器ID
server-id=1
#下面这两个不是必须要配置
#主要是为了使用带事务的InnoDB进行复制设置时尽可能提高持久性和一致性
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
  1. 创建日志目录
1
2
mkdir /var/log/mysql
chown myslq:mysql /var/log/mysql
  1. 重启数据库查看配置,这里是直接重启 docker
1
docker restart 7df9dd80af21

如果是centos,直接重启服务systemctl start mysql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
mysql> show variables like 'server_id';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id | 1 |
+---------------+-------+
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> show variables like '%skip_networking%'; #skip_networking默认是OFF关闭状态,启用后主从将无法通信
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| skip_networking | OFF |
+-----------------+-------+
1 row in set (0.00 sec)
  1. 在主库上建立用于主从复制的账号

    1
    2
    3
    mysql> CREATE USER 'replication'@'%';
    mysql> GRANT REPLICATION SLAVE ON *.* TO 'replication'@'%' identified by '123456';
    mysql> flush privileges;
  2. 查看主库的二进制日志的名字

    1
    2
    3
    4
    5
    6
    7
    mysql> show master status;
    +------------------+----------+--------------+------------------+-------------------+
    | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
    +------------------+----------+--------------+------------------+-------------------+
    | mysql-bin.000001 | 801 | | | |
    +------------------+----------+--------------+------------------+-------------------+
    1 row in set (0.00 sec)

    记住这里的 file 和 position

  3. 关闭防火墙

    由于 docker 不是 centos, 所以我跳过这一步

    如果有: service iptables stop

修改从库

  1. 关闭防火墙(同上)

  2. 设置配置文件 my.cnf

    1
    2
    [mysqld]
    server-id=2
  3. 配置主从复制参数

    1
    2
    3
    4
    5
    mysql> CHANGE MASTER TO MASTER_HOST='172.17.0.2',
    MASTER_USER='replication',
    MASTER_PASSWORD='123456',
    MASTER_LOG_FILE='mysql-bin.000001',
    MASTER_LOG_POS=801;

    这里的 ip 写的是 docker 的容器的 ip

    docker 容器的 ip 查看方法: docker inspect <container id>

  4. 启动

    1
    mysql> start slave;
  5. 查看 slave 状态

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    mysql> show slave status\G; # \G 表示用 kv 键值对输出
    *************************** 1. row ***************************
    Slave_IO_State: Waiting for master to send event
    Master_Host: 172.17.0.2
    Master_User: replication
    Master_Port: 3306
    Connect_Retry: 60
    Master_Log_File: mysql-bin.000001
    Read_Master_Log_Pos: 801
    Relay_Log_File: 747fe7f90035-relay-bin.000002
    Relay_Log_Pos: 320
    Relay_Master_Log_File: mysql-bin.000001
    Slave_IO_Running: Yes # 这个一定要为 yes
    Slave_SQL_Running: Yes # 这个一定要为 yes
  6. 如果有问题, 清理配置

    1
    2
    stop slave;
    reset slave all;

测试

  1. 在主库新增一个 test_rep 数据库

    1
    2
    mysql> create database test_rep;
    Query OK, 1 row affected (0.01 sec)
  2. 查看从库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    mysql> show databases;
    +--------------------+
    | Database |
    +--------------------+
    | information_schema |
    | mysql |
    | performance_schema |
    | sys |
    | test_rep |
    +--------------------+
    5 rows in set (0.00 sec)

    可以看到从库也新增了一个 test_rep 数据库