基于Docker的MySQL主从搭建

环境

以下所有操作,均是在Macbook上进行的。其他系统请自行做适应性调整。

Docker安装

brew cask install docker
# 安装后验证
docker -v
# 安装成功会输出版本号,本机为:Docker version 19.03.8, build afacb8b

安装之前建议先将brew的源设置为阿里云的,这样下载快一些。

设置指南请参考 https://blog.csdn.net/AWEI1024/article/details/107445498

MySQL镜像下载

docker pull mysql/mysql-server:5.7

到此环境准备完毕。

MySQL主从搭建

创建MySQL网络

# 创建 mysql 网络, 网络请自行定义,与本机不冲突即可
docker network create --subnet 172.170.0.0/16 mysql-cluster

MySQL容器脚本

#!/bin/bash
if [ ! $# -eq 2 ];then
	echo -e "请输入参数: Usage: $0 port server_id "
	exit
fi
PORT=$1

echo -e "Mysql容器映射端口号 = ${PORT} \n"

BASE_PATH="${HOME}/container/mysql/${PORT}"

echo -e "[目录映射] >>> Mysql容器初始化,工作根目录为: ${BASE_PATH}\n"
if [ ! -d ${BASE_PATH} ]; then

	conf_data="\
	[mysqld] \n \
	skip-host-cache \n \
	skip-name-resolve \n \
	\n \
	\n \
	datadir=/var/lib/mysql \n \
	socket=/var/lib/mysql/mysql.sock \n \
	secure-file-priv=/var/lib/mysql-files \n \
	\n \
	\n \
	user=mysql \n \
	symbolic-links=0 \n \
	\n \
	\n \
	log-error=/var/log/mysqld.log \n \
	pid-file=/var/run/mysqld/mysqld.pid \n \
	\n \
	\n \
	# 慢查询设置 \n \
	slow-query-log=1 #启用慢查询日志 \n \
	slow_query_log_file=slow_query.log # 慢查询文件 \n \
	long_query_time=10 # 查询时间超过10s 判定为慢查询 \n \
	\n \
	\n \
	# binlog 日志设置 \n \
	server-id=$2 \n \
	\n
	# 原本目录要设定为/var/lib/mysql/binlog/mysql-bin,但由于不会自动创建binlog,因此采用这种简单的方式. \n \
	log-bin = /var/lib/mysql/mysql-bin \n \
	binlog-format=ROW \n \
	# binlog 同步刷盘
	sync_binlog=1 \n \
	# slave 重放日志时记录binlog
	log-slave-updates=on \n \
	# 从节点重启禁止自动启动复制,建议设置此选项,改为手动进行
	skip-slave-start \n \
	enforce-gtid-consistency=on \n \
	# 启用GTID模式
	gtid_mode=on \n \

	\n
	\n
	# innodb 设置 \n \
	#### 1:意味着在事务提交前日志已被写入磁盘, 事务可以运行更长以及服务崩溃后的修复能力. \n \
	#### 0:如果你愿意减弱这个安全,或你运行的是比较小的事务处理,以减少写日志文件的磁盘 I/O。这个选项默认设置为 0。 \n \
	innodb_flush_log_at_trx_commit=1 \n \
	\n \
	\n \
	#### InnoDB 用来高速缓冲数据和索引内存缓冲大小。 更大的设置可以使访问数据时减少磁盘 I/O \n \
	#innodb_buffer_pool_size=8M \n \
	\n \
	\n \
	#### 日志组中的每个日志文件的大小(单位 MB)。可以减少刷新缓冲池的次数,从而减少磁盘 I/O。但是大的日志文件意味着在崩溃时需要更长的时间来恢复数据 \n \
	#innodb_log_file_size=48M \n \
	"
	mkdir -p ${BASE_PATH}
	echo -e "[目录映射] 根目录不存在,自动创建根目录: >> ${BASE_PATH}\n"
	cd ${BASE_PATH}
	curr_dir=$(pwd)
	echo -e "[目录映射] 切换到根目录: >> ${curr_dir}\n"
	echo -e "[目录映射] >>>>>>>>>>>>>>>> \n"
	mkdir data
	echo -e "[目录映射] 创建子目录: >> data \n"
	# mkdir mysqld
	# echo -e "[目录映射] 创建子目录: >> mysqld \n"
	# mkdir mysql-files
	# echo -e "[目录映射] 创建子目录: >> mysql-files \n"
	mkdir log
	echo -e "[目录映射] 创建子目录: >> log \n"
	# mkdir -p binlog/mysql-bin
	# echo -e "[目录映射] 创建子目录: >> binlog/mysql-bin \n"
	mkdir conf
	echo -e "[目录映射] 创建子目录: >> conf \n"

	echo -e "[目录映射] 创建配置文件: my.cnf \n"
	echo -e "[目录映射] 配置文件(my.cnf)内容如下:\n"
	echo -e ${conf_data}
	echo -e ${conf_data} > ./conf/my.cnf

	echo -e "[>>>>>>>>>>>>> 开始制作Dockerfile >>>>>>>>>>>>>>>]\n"
	df_data=" \
	FROM mysql/mysql-server:5.7 \n \
	MAINTAINER caoawei@aliyun.com \n \

	RUN mkdir -p /var/lib/mysql/binlog \n \
	RUN chmod -R a+rw /var/lib/mysql/binlog \n \
	"

fi

#容器名
C_NAME="mysql_${PORT}"
echo -e "将要创建的容器名为:  >>  ${C_NAME}  << \n"

# -v ${BASE_PATH}/binlog/mysql-bin:/var/lib/mysql/binlog/mysql-bin \
# -v ${BASE_PATH}/mysqld:/var/run/mysqld \
# -v ${BASE_PATH}/mysql-files:/var/lib/mysql-files \

docker run \
-d \
-v ${BASE_PATH}/data:/var/lib/mysql \
-v ${BASE_PATH}/conf/my.cnf:/etc/mysql/my.cnf \
-v ${BASE_PATH}/log:/var/log \
-p "${PORT}":3306 \
-e MYSQL_ROOT_PASSWORD=root \
--name "${C_NAME}" \
mysql/mysql-server:5.7

请在本地机器创建以下脚本:

# 脚本内容为上面的内容
vim mysql-docker-init.sh
chmod -R +x mysql-docker-init.sh

上述脚本将按照以下目录自动创建

(注意:上述脚本只是根据mysql镜像创建容器,容器的启动和停止请使用docker start 和docker stop)

${HOME}/container/mysql/${port}
# 例如本机为: /Users/dasouche/container/mysql/3601
# 其中 ${HOME} 为/Users/dasouche, 容器端口为3601
# 在上述目录下,脚本会自动创建以下脚本,是为到容器的目录映射
${HOME}\
-----container\
-------------mysql\
-----------------3601\
--------------------conf\
--------------------data\
--------------------log\
-----------------3602\
--------------------conf\
--------------------data\
--------------------log\

# conf: 为my.cnf配置文件所在目录,脚本自动生成
# data: mysql数据目录以及binlog存储所在目录
# log: 为mysql 的运行日志文件所在目录

创建MySQL主从容器

创建MySQL主节点

# 本人已将mysql-docker-init.sh加入到PATH下
# 脚本参数: [端口] [server.id]
# 这里的端口为本地机器的端口, 脚本将此端口映射到mysql容器中3306端口上
mysql-docker-init.sh 3601 1
# 容器名为 mysql_端口号

#进入到主节点容器
docker exec -it mysql_3601 bash

#进入到容器后,登录到mysql,root 密码为root,在容器脚本中有指定
mysql -u root -p

#登录到mysql后,执行以下语句: 目的为了外部可通过3601端口以及root账户访问容器中的mysql
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root' WITH GRANT OPTION;

# 创建复制账号
create user 'repl'@'%' identified by 'repl';
grant replication slave on *.* to 'repl'@'%' identified by 'repl';

创建MySQL从节点

# 端口和server.id 设置为与主节点不同即可
mysql-docker-init.sh 3602 1001
# 按照上述创建mysql主节点的方式,执行一遍上述操作.推荐也创建复制账号.这里就不过多介绍

加入网络

下面的操作是将MySQL主从节点加入到同一个网络,以能够访问。

# 将MySQL主从节点容器加入到上面所创建的网络中
# 主节点加入到网络中,指定具体的IP地址
docker network connect --ip 172.170.0.10 mysql-cluster mysql_3601
# 从点加入到网络中,指定具体的IP地址
docker network connect --ip 172.170.0.11 mysql-cluster mysql_3602

# 验证一下
docker network inspect mysql-cluster

MySQL主从关系建立

# 登录到mysql 从节点后,执行以下操作
# 设置为只读
SET @@GLOBAL.read_only = ON;

# 建立主从关系
# 下面的host 为主节点在mysql-cluster网络中的IP,端口号为3306,复制账号即为上述创建主节点时所创建的复制账号
CHANGE MASTER TO
     >     MASTER_HOST = '172.170.0.10',
     >     MASTER_PORT = 3306,
     >     MASTER_USER = 'reol',
     >     MASTER_PASSWORD = 'repl',
     >     MASTER_AUTO_POSITION = 1;

# 启动复制
start slave;

# 验证是否成功
# 观察下面两项是否为Yes
# Slave_IO_Running: Yes
# Slave_SQL_Running: Yes

show slave status \G;

问题

按照上面的步骤操作,一般不会存在问题。本人在操做过程中,由于失误,导致最后生成的my.cnf配置文件没有开启二进制。紧接着在建立主从关系后,没有查验是否建立成功,就在主节点上创建数据库以及表,结果因没有开启binlog,从节点未进行同步。

发现问题后,就修改了脚本(对已存在容器不会产生影响),并修改主从容器目录下生成的my.cnf配置文件,将binlog进行开启, 然后重启主从节点。登录到从节点,通过 start slave命令启动复制,并查看从节点是否同步主节点之前的数据库及表,结果是没有同步。这是因为,binlog中并没有日志,所以从节点无数据可同步。

然后,删除mysql主节点上的数据库及表(之前手动创建的),然后到从节点重新启动复制,结果依然是失败。通过show slave status命令查看,是因为从节点并没有主节点上被删除的数据库及表,导致复制失败(复制自此之后便会中断)。

由于开启了gtid模式, 本人通过以下方法处理了这个问题:

# 进入到从节点容器
docker exec -it mysql_3602 bash
# 登录到mysql
mysql -u root -p
# 设置会话变量 @@session.gtid_next
# 下面的值为binlog文件中最后一个有效的值,因为在这个案例中,所有的都要忽略掉
set @@session.gtid_next='1ba8300e-3062-11eb-9a93-0242ac110002:1';

# 执行一个空事务
begin;
commit;

# 恢复会话变量 @@session.gtid_next为自动模式
set @@session.gtid_next='AUTOMATIC';

# 启动复制
start slave;

下面的截图为MySQL主节点binlog文件的解析内容(删除数据库产生的binlog)

在这里插入图片描述

结束语

大家在操作过程中遇到什么问题,欢迎下方评论,进行探讨。

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值