docker官网mysql镜像
https://hub.docker.com/_/mysql
A:主库
可以下最新的,也可以下固定版本,这里下载5.7版本
docker pull mysql:5.7
启动容器
启动之前可以先建好这三个目录,防止启动失败
/mydata/mysql/log
/mydata/mysql/data
/mydata/mysql/conf
执行以下命令
docker run -p 3306:3306 --name mysql-master \
--privileged=true \
-v /mydata/mysql/log:/var/log/mysql \
-v /mydata/mysql/data:/var/lib/mysql \
-v /mydata/mysql/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
-p 3306:3306:将容器的 3306(后) 端口映射到主机的 3306(前) 端口
–name:容器名称 mysql-master
-v /mydata/mysql/conf:/etc/mysql/conf.d:将配置文件夹挂载到主机
-v /mydata/mysql/log:/var/log/mysql:将日志文件夹挂载到主机
-v /mydata/mysql/data:/var/lib/mysql:将数据文件夹挂载到主机
-e MYSQL_ROOT_PASSWORD=root:初始化 root 用户的密码
-d 是后台启动
-v文件挂载之后,修改主机目录下配置会同步到容器的配置
修改配置
查看配置文件是否存在,不存在则新建
cd /mydata/mysql/conf
touch my.cnf
新增配置信息
[client]
default-character-set=utf8
# 客户端编码格式
[mysql]
default-character-set=utf8
# 服务端编码格式
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
# skip-name-resolve 跳过解析,加快连接 mysql
# 添加 master 主从复制配置
# 每个mysql服务的id不能相同
server_id=1
# 开启二进制文件,这个是主从复制的核心文件,记录sql执行的
log-bin=mysql-bin
# 可读可写
read-only=0
# 需要同步的库名
binlog-do-db=mytest1
binlog-do-db=mytest2
# 不需要同步的库名
binlog-ignore-db=mysql
binlog-ignore-db=sys
binlog-ignore-db=information_schema
binlog-ignore-db=performance_schema
重启mysql容器
docker restart mysql-master
连接mysql
docker exec -it mysql-master mysql -uroot -proot
创建配置文件中需要同步的两个数据库mytest1,mytest2
CREATE DATABASE IF NOT EXISTS mytest1
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_general_ci;
CREATE DATABASE IF NOT EXISTS mytest2
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_general_ci;
B:从库
安装同主库:这里省略
启动从库mysql容器
docker run -p 3307:3306 --name mysql-slaver-01 \
-v /mydata/mysql/slaver/log:/var/log/mysql \
-v /mydata/mysql/slaver/data:/var/lib/mysql \
-v /mydata/mysql/slaver/conf:/etc/mysql/conf.d \
-e MYSQL_ROOT_PASSWORD=root \
-d mysql:5.7
修改配置文件my.cnf,除了server_id其他一样
[client]
default-character-set=utf8
# 客户端编码格式
[mysql]
default-character-set=utf8
# 服务端编码格式
[mysqld]
init_connect='SET collation_connection = utf8_unicode_ci'
init_connect='SET NAMES utf8'
character-set-server=utf8
collation-server=utf8_unicode_ci
skip-character-set-client-handshake
skip-name-resolve
# skip-name-resolve 跳过解析,加快连接 mysql
# 添加 master 主从复制配置
# 每个mysql服务的id不能相同
server_id=2
# 开启二进制文件,这个是主从复制的核心文件,记录sql执行的
log-bin=mysql-bin
# 可读可写
read-only=0
# 需要同步的库名
replicate-do-db=mytest1
replicate-do-db=mytest2
# 不需要同步的库名
replicate-ignore-db=mysql
replicate-ignore-db=sys
replicate-ignore-db=information_schema
replicate-ignore-db=performance_schema
重启mysql容器
docker restart mysql-slaver-01
连接mysql
docker exec -it mysql-slaver-01 mysql -uroot -proot
创建配置文件中需要同步的两个数据库mytest1,mytest2
CREATE DATABASE IF NOT EXISTS mytest1
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_general_ci;
CREATE DATABASE IF NOT EXISTS mytest2
DEFAULT CHARACTER SET utf8mb4
DEFAULT COLLATE utf8mb4_general_ci;
配置主从同步
进入主库mysql
docker exec -it mysql-master mysql -uroot -proot
创建用来同步的用户并授权
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT ALL PRIVILEGES ON *.* TO 'slave'@'%';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* to 'slave'@'%';
FLUSH PRIVILEGES;
查看主库状态
show master status;
记住File和Position的值
用navicat或者其他工具连接从库,并执行以下语句
change master to master_host='192.168.86.99',master_port=3306,master_user='slave',master_password='123456',master_log_file='mysql-bin.000005',master_log_pos=1466 ;
master_host:主库的地址
master_user:刚才主库创建的用来备份的用户名
master_password:备份用户的密码
master_log_file:show master status查出来的File
master_log_pos:show master status查出来的Position
master_port:主库端口
然后开启主从复制,并查看从库状态
start slave;
show slave status;
如上,如果两个都是yes表示成功
问题解决
如果Slave_SQL_Running是no的话,可以执行先停掉复制
stop slave ;
跳过事件
set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
再次启动复制
start slave ;
如果上面不行的话,可以去主库查看下状态,重新记录File和Position的值,并停掉从库的复制再次执行
change master to master_host='192.168.86.99',master_port=3306,master_user='slave',master_password='123456',master_log_file='mysql-bin.000005',master_log_pos=1466 ;
测试主库插入两条数据
一定要在主库插入
查看一下从库
OK了!
三种复制模式
- 基于行的复制(row-based replication,RBR):
bin-log中可以不记录执行的sql语句的上下文相关信息,仅仅需要记录哪一条记录被修改了,修改成什么信样了,所以row的日志内容会非常清楚的记录下每一行数据修改的细节,非常容易理解。而且不会出现在某些特定情况下的存储过程和function,以及trigger的调用和处罚无法被正确问题 - 基于SQL语句的复制(statement-based replication,SBR)
基于实际执行的SQL语句的复制模式,该复制模式简单实现了数据同步,但在执行跨库更新等SQL语句时容易出现主从库的数据不一致问题 - 混合模式复制(mixed-based replication,MBR)
根据SQL语句的不同来判断是否需要使用row格式,当出现可能造成主从库数据不一致的SQL语句时(例如:用户自定义函数、跨库SQL语句等),binlog自动转为row格式记录
修改复制模式的方式:
set global binlog_format=statement;
set global binlog_format=mixed;
set global binlog_format=row;
三种同步方式
-
异步复制
slave会启动两个线程,IO Thread 和 SQL Thread
IO Thread 负责从master拉取binlog 日志,并写入relay中继日志
SQL Thread 负责将relay中继日志中的变更进行重放,更新数据来达到跟master保持数据一致的目的 -
半同步复制
事务在主库写完binlog后,需要从库返回一个已接收,才能返回给客户端
确保事务提交后binlog至少传输到一个从库
不保证从库应用完这个事务的binlog
优点:利用数据库原生功能,比较简单
缺点:主库的写请求时延会增长,吞吐量会降低 -
同步复制
全同步复制必须收到所有从库的ack,才会提交事务。主库的事务提交依赖于后面所有的从库,这样一来性能就会明显得下降!