概述
MySQL中提供了主从复制功能,同时主从复制机制也是读写分离实现的基础,还可用于负载均衡,容灾等。
同时MySQL的主从复制十分灵活:
需要注意的是联级复制中需要为从服务器配置log_slave_updates=1,当从服务器从主服务器中收到了命令也会同步到自身的二进制日志中。
搭建
我的搭建环境是:
- docker 18.09.3
- MySQL5.6
- 两台Centos7虚拟机
安装Docker可以参照菜鸟教程。
- ①下拉MySQL 镜像
docker pull mysql:5.6
- ②创建目录
在master虚拟机中创建
//映射数据目录
mkdir -pv /docker/mysql/data
//映射配置文件目录
mkdir -pv /docker/mysql/master
//映射日志目录
mkdir -pv /docker/mysql/log
slave虚拟机中配置文件目录名改成slave。
- ③创建配置文件
在master虚拟机中创建:
vi /docker/mysql/master/my.cnf
内容为:
[mysqld]
log-bin=mysql-bin
server-id=101
slave中创建的配置文件为:
vi /docker/mysql/slave/my.cnf
[mysqld]
log-bin=mysql-bin
server-id=102
注意每一个MySQL服务器中的server-id不允许相同。
- ④创建MySQL容器
master创建代码:
docker run--name master -v /docker/mysql/data:/var/lib/mysql -v /docker/mysql/master:/etc/mysql/conf.d -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 mysql:5.6
slave中相同,只需要改一下配置文件目录名和容器名即可。
- ⑤配置主服务器
进入master的Docker容器中
//docker ps 查看CONTAINER ID
docker exec -it CONTAINER ID /bin/bash
进入MySQL
mysql -uroot -p
执行:
show master status;
需要记录红框内内容,等下配置从服务器会用到。
创建同步用的账户并授权:
//直接复制
SET sql_mode=(SELECT REPLACE(@@sql_mode,’ONLY_FULL_GROUP_BY’,''));
//name为账户名,%表示任何ip均可连接,123456是密码
GRANT REPLICATION SLAVE ON *.* TO 'name'@'%' IDENTIFIED BY '123456';
- ⑥配置从服务器
// 直接复制
SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));
// master_host虚拟机IP,master_user是之前在主服务器中创建的同步账户名,
//password则是密码,master_log_file和,master_log_pos是截图红框的内容。
change master to master_host='虚拟机ip',master_user='name',master_password='123456',master_log_file='mysql-bin.000004',master_log_pos=225195;
//配置完毕后启动
start slave;
查看从服务器状态:
show slave status\G;
显示等待同步即为正常。
- ⑦测试
在主数据库中创建数据库test
刷新从数据库,也同步更新了表结构。
三种主从复制的策略:
(1)同步复制,master的变化,必须等待slave-1,slave-2,…,slave-n完成后才能返回。
(2)异步复制,master只需要完成自己的数据库操作即可,至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。
(3)半同步复制,master只保证slaves中的一个操作成功,就返回,其他slave不管。这个功能,是由google为MYSQL引入的。
原理
简单说: 主库中有个log-bin二进制文件,用于记录执行的sql语句。每当主库更新了文件后就会向从库中同步一份,从库也执行相同的SQL语句来保持一致性。
- 每当有slave连接master时,在master中就会
创建一个线程
用于发送bin-log中的内容到从库
。 - 同时,从库启动主从模式后,也会创建
两个线程
,I/O线程用于接收主库发送的bin-log更新内容,并写入从库的Replay log文件中
。另一个线程读取Relay log中的内容,并解析执行SQL语句
。 - 一个主从复制连接需要三个线程
存在的问题:
**问题:**主库写操作频繁时,从库只有一个线程,写压力大,延时变长。
解决方式: 使用并行复制,增加执行SQL的线程数
set global slave_parallel_workers=10;