创建目录及配置文件
创建目录结构如下,之后用于挂载数据卷:
├── 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_format
为ROW
。
binlog
有以下三种模式:
-
ROW
:每条记录的修改都会被记录。优点:不存在数据不一致的情况。
缺点:一旦修改表结构( alter table) 会出现 binlog 暴涨现象。
-
STATEMENT
:每执行一条导致值变化的 sql 就会记录到 binlog 中。优点: 仅仅记录了SQL,不会记录执行结果,减少了 binlog 日志量,节约了 IO,提高了性能
缺点:会出现数据不一致的情况。
-
MIXED
:以上两种模式混合使用。
我们可以通过编辑./master/conf/my.cnf
文件,添加一行binlog_format = MIXED
来修改binlog
模式。
MySQL 主从同步原理
主从同步原理图:
MySQL 默认的复制方式是异步
的,主库把日志发送给从库后不关心从库是否已经处理,这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库后,日志就丢失了。可以根据情况调整同步策略:
- 全同步复制:主库写入 binlog 后强制同步日志到从库,
所有的从库
都执行完成后才返回给客户端。性能会受到严重影响。 - 半同步复制:从库写入日志成功后返回 ACK 确认给主库,主库收到至少一个从库的确认就认为写操作完成。
主从延迟:主库与从库之间数据同步肯定是有延时的(网络)。解决方案是:部分查询强制走主库,主库肯定是最新的数据。