docker-compose部署MySQL主从

docker-compose部署MySQL主从

leo 749 2021-04-10

创建目录及配置文件

创建目录结构如下,之后用于挂载数据卷:

├── master
│   ├── conf
│   └── data
├── slaver0
│   ├── conf
│   └── data
└── slaver1
    ├── conf
    └── data

进入./master/conf目录,创建文件vi my.cnf,内容如下:

[mysqld]
# 集群服务器id,不可重复
server-id = 1
# 同步(binlog)文件名称
log-bin = mysql-bin
# 1055异常处理
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"

进入./slaver0/conf目录,创建文件vi my.cnf,内容如下:

[mysqld]
# 集群服务器id,不可重复
server-id = 11
# 1055异常处理
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"

进入./slaver1/conf目录,创建文件vi my.cnf,内容如下:

[mysqld]
# 集群服务器id,不可重复
server-id = 12
# 1055异常处理
sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"

docker-compose.yml

创建docker-compose.yml文件,内容如下:

version: '3'
services:
  # 主库
  mysql-master:
    image: "mysql:5.7"
    restart: always
    ports:
      - "3306:3306"
    container_name: mysql-master
    environment:
       MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - ./master/conf/my.cnf:/etc/mysql/conf.d/mysql.cnf
      - ./master/data:/var/lib/mysql
  # 从库0
  mysql-slaver0:
    image: "mysql:5.7"
    restart: always
    ports:
      - "3307:3306"
    container_name: mysql-slaver0
    environment:
       MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - ./slaver0/conf/my.cnf:/etc/mysql/conf.d/mysql.cnf
      - ./slaver0/data:/var/lib/mysql
  # 从库1
  mysql-slaver1:
    image: "mysql:5.7"
    restart: always
    ports:
      - "3308:3306"
    container_name: mysql-slaver1
    environment:
       MYSQL_ROOT_PASSWORD: 123456
    volumes:
      - ./slaver1/conf/my.cnf:/etc/mysql/conf.d/mysql.cnf
      - ./slaver1/data:/var/lib/mysql

运行docker-compose up -d启动容器。

配置步骤

主库

docker exec -it mysql-master bash进入主库,mysql -u root -p 123456进入mysql

创建用户 slaver作为从库同步主库数据时的用户:

create user 'slaver'@'%' identified by '123456';

授予权限:

grant replication slave on *.* to 'slaver'@'%';

刷新权限:

flush privileges;

查看binlog相关配置:

show global variables like 'binlog%';
mysql> show global variables like 'binlog%';
+--------------------------------------------+--------------+
| Variable_name                              | Value        |
+--------------------------------------------+--------------+
| binlog_cache_size                          | 32768        |
| binlog_checksum                            | CRC32        |
| binlog_direct_non_transactional_updates    | OFF          |
| binlog_error_action                        | ABORT_SERVER |
| binlog_format                              | ROW          |
| binlog_group_commit_sync_delay             | 0            |
| binlog_group_commit_sync_no_delay_count    | 0            |
| binlog_gtid_simple_recovery                | ON           |
| binlog_max_flush_queue_time                | 0            |
| binlog_order_commits                       | ON           |
| binlog_row_image                           | FULL         |
| binlog_rows_query_log_events               | OFF          |
| binlog_stmt_cache_size                     | 32768        |
| binlog_transaction_dependency_history_size | 25000        |
| binlog_transaction_dependency_tracking     | COMMIT_ORDER |
+--------------------------------------------+--------------+
15 rows in set (0.01 sec)

查看 server 相关配置:

show global variables like 'server%';
mysql> show global variables like 'server%';
+----------------+--------------------------------------+
| Variable_name  | Value                                |
+----------------+--------------------------------------+
| server_id      | 1                                    |
| server_id_bits | 32                                   |
| server_uuid    | 25410417-5643-11eb-9ef1-0242ac130005 |
+----------------+--------------------------------------+
3 rows in set (0.00 sec)

查看主库状态:

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

从库

连接从库mysql-slaver0

# 设置 master 连接参数
change master to 
    master_host='mysql-master',  # 主库的IP,由于docker的原因,可以使用容器名来当主机名
	master_user='slaver',    # 主库同步的用户
	master_password='123456', # 密码
	master_port=3306, # 主库的端口
	master_log_file='mysql-bin.000001', # 同步的文件 通过show master status来获取
	master_log_pos=154; # 开始从第几行同步 通过show master status来获取
	
# 启动同步
start slave;

# 查看 slave 状态
show slave status; # 看到 Slave_IO_Running 和 Slave_SQL_Running 都为 Yes 即为配置成功

对从库mysql-slaver1做相同操作。

还可以使用stop slave;停止同步。

binlog 模式

前面通过show global variables like 'binlog%';命令可以看到binlog_formatROW

binlog有以下三种模式:

  • ROW:每条记录的修改都会被记录。

    优点:不存在数据不一致的情况。

    缺点:一旦修改表结构( alter table) 会出现 binlog 暴涨现象。

  • STATEMENT:每执行一条导致值变化的 sql 就会记录到 binlog 中。

    优点: 仅仅记录了SQL,不会记录执行结果,减少了 binlog 日志量,节约了 IO,提高了性能

    缺点:会出现数据不一致的情况。

  • MIXED:以上两种模式混合使用。

我们可以通过编辑./master/conf/my.cnf文件,添加一行binlog_format = MIXED来修改binlog模式。

MySQL 主从同步原理

主从同步原理图:

mysql主从同步原理图

MySQL 默认的复制方式是异步的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。可以根据情况调整同步策略:

  • 全同步复制:主库写入 binlog 后强制同步日志到从库,所有的从库都执行完成后才返回给客户端。性能会受到严重影响。
  • 半同步复制:从库写入日志成功后返回 ACK 确认给主库,主库收到至少一个从库的确认就认为写操作完成。

主从延迟:主库与从库之间数据同步肯定是有延时的(网络)。解决方案是:部分查询强制走主库,主库肯定是最新的数据。