前言
最近在学习有关 MyCAT 相关的知识,但是使用 MyCAT 前提是得部署多个 MySQL 实例,由于只有一台服务器,
所以就使用了 Docker 。本博客实现了 MySQL 一主两从。
本篇博客的操作有:
① 拉取 MySQL 官方镜像
② MySQL 主从配置
③ 运行 MySQL 容器
④ 在从库中配置主从同步命令
⑤ 验证
拉取 MySQL 官方镜像
1. 输入命令 systemctl start docker.service -> 启动 Docker 服务
2. 输入命令 docker pull mysql:5.7 -> 拉取 MySQL 镜像
配置 MySQL 在宿主机上的配置文件,数据日志目录以及初始化 sql 文件
准备工作
1. 首先在宿主机上为此次配置创建相应的目录
2. 输入命令 cd /usr/local/ -> 进入目录
3. 输入命令 mkdir docker -> 创建文件夹
4. 输入命令 cd docker/ -> 进入目录
5. 输入命令 mkdir mysql_master_3306 -> 创建主库文件夹
6. 轮流输入命令 cd mysql_master_3306、mkdir conf、mkdir data、mkdir log、mkdir sql -> 创建相关
文件夹
7. 输入命令 cd .. -> 回到上级目录
8. 还有两个从库的文件夹目录结构大致相同,所以使用 cp -r 命令来创建
9. 输入命令 cp -r mysql_master_3306/ mysql_slave_3307/ -> 复制创建第一个从库目录
10. 输入命令 cp -r mysql_master_3306/ mysql_slave_3308/ -> 复制创建第二个从库目录
配置文件 - master 主库
1. 输入命令 cd /usr/local/docker/mysql_master_3306/conf/ -> 进入目录
2. 输入命令 touch my.cnf -> 新建文件
3. 输入命令 vim my.cnf -> 编辑文件,粘贴下面内容
[client]
default-character-set=utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
server-id=1 # 数据库唯一 ID,主从的标识号绝对不能重复。
log-bin=/var/log/mysql/binlog # 开启 bin-log,并指定文件目录和文件名前缀
binlog-do-db=masterSlaveDB # 需要同步的数据库。如果是多个同步库,就以此格式另写几行即可。如果不指明对某个具体库同步,就去掉此行,表示同步所有库(除了 ignore 忽略的库)。
binlog-ignore-db=mysql # 不同步mysql系统数据库。如果是多个不同步库,就以此格式另写几行;也可以在一行,中间逗号隔开。
sync_binlog = 1 # 确保 binlog 日志写入后与硬盘同步
binlog_checksum = none # 跳过现有的采用 checksum 的事件,mysql5.6.5 以后的版本中 binlog_checksum=crc32,而低版本都是 binlog_checksum=none
binlog_format = mixed # bin-log 日志文件格式,设置为 MIXED 可以防止主键重复。
[mysql]
default-character-set=utf8mb4
4. 轮流输入命令 esc -> shift + 冒号 -> wq -> 回车
配置文件 - slave 从库
1. 输入命令 cd /usr/local/docker/mysql_slave_3307/conf/ -> 进入目录
2. 输入命令 touch my.cnf -> 新建文件
3. 输入命令 vim my.cnf -> 编辑文件,粘贴下面内容
[client]
default-character-set=utf8mb4
[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
server-id=2 # 数据库唯一 ID,主从的标识号绝对不能重复。
log-bin=/var/log/mysql/binlog # 开启 bin-log,并指定文件目录和文件名前缀
binlog-do-db=masterSlaveDB # 需要同步的数据库。如果是多个同步库,就以此格式另写几行即可。如果不指明对某个具体库同步,就去掉此行,表示同步所有库(除了 ignore 忽略的库)。
binlog-ignore-db=mysql # 不同步 mysql 系统数据库。如果是多个不同步库,就以此格式另写几行;也可以在一行,中间逗号隔开。
slave-skip-errors = all # 跳过所有的错误错误,继续执行复制操作
[mysql]
default-character-set=utf8mb4
4. 轮流输入命令 esc -> shift + 冒号 -> wq -> 回车
5. 还有一个 mysql_slave_3308 从库除了 server-id 不一致以外,其他基本一致,这里不再赘述
6. mysql_slave_3308/conf/my.cnf -> server-id=3
数据目录
1. 此时在启动 MySQL 容器前,此目录都是空的
日志目录
1. 此时在启动 MySQL 容器前,此目录也都是空的
初始化 sql 文件
1. 输入命令 cd /usr/local/docker/mysql_master_3306/sql/ -> 进入目录
2. 输入命令 touch init.sql -> 新建文件
3. 输入命令 vim init.sql -> 编辑文件,粘贴下面内容
-- 创建数据库
DROP database IF EXISTS `masterSlaveDB`;
CREATE DATABASE `masterSlaveDB` default character set utf8mb4 collate utf8mb4_unicode_ci;
-- 切换数据库
USE masterSlaveDB;
-- 创建表
DROP TABLE IF EXISTS `masterSlaveTable` ;
CREATE TABLE `masterSlaveTable` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`type` varchar(2) DEFAULT NULL COMMENT '生活用品类别:1. 家电类 2. 厨具',
`name` varchar(50) DEFAULT NULL COMMENT '生活用品名称',
`description` varchar(200) DEFAULT NULL COMMENT '生活用品描述',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='MySQL 主从同步测试表';
INSERT INTO masterSlaveTable ( type , name , description )
VALUES ('1','电饭煲','用来蒸饭'),('1','电热壶','用来烧水'),('1','空调','用来制冷或制热'),('2','菜刀','用来切菜'),('2','刨子','用来剥皮'),('2','打蛋器','用来搅拌鸡蛋');
4. 轮流输入命令 esc -> shift + 冒号 -> wq -> 回车
5. 一主两从中的初始化 sql 文件都一样,所以这里使用 cp 命令来创建从库的初始化 sql 文件
6. 输入命令 cp init.sql ../../mysql_slave_3307/sql/ -> 复制文件
7. 输入命令 cp init.sql ../../mysql_slave_3308/sql/ -> 复制文件
运行 MySQL 容器
1. 输入命令 docker images -> 查看构建的镜像
2. 输入命令
docker run -p 3306:3306 --name mysql-master-3306 -v /usr/local/docker/mysql_master_3306/conf/my.cnf:/etc/mysql/conf.d/my.cnf -v /usr/local/docker/mysql_master_3306/data/:/var/lib/mysql/ -v /usr/local/docker/mysql_master_3306/sql/:/docker-entrypoint-initdb.d/ -v /usr/local/docker/mysql_master_3306/log/:/var/log/mysql/ -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
- -p:端口映射(宿主机端口:容器端口)
- --name:启动后的容器名称
- -v:第一个 -v 为映射配置文件(宿主机目录:容器目录)
- -v:第二个 -v 为映射数据目录,相当于把容器中的数据备份到宿主机指定的目录(宿主机目录:容器目录)
- -v:第三个 -v 为初始化 sql 目录(宿主机目录:容器目录)
- -v:第四个 -v 为日志目录(宿主机目录:容器目录)
- -e MYSQL_ROOT_PASSWORD=123456:设置 root 连接密码
- 映射实际上是把宿主机和容器相连通
- 容器中映射目录的文件发生改变时,宿主机中映射目录的文件也发生变化
- -d:后台启动
- mysql:5.7:启动的镜像
3. 还有两个从库启动与主库启动类似,分别为
docker run -p 3307:3306 --name mysql-slave-3307 -v /usr/local/docker/mysql_slave_3307/conf/my.cnf:/etc/mysql/conf.d/my.cnf -v /usr/local/docker/mysql_slave_3307/data/:/var/lib/mysql/ -v /usr/local/docker/mysql_slave_3307/sql/:/docker-entrypoint-initdb.d/ -v /usr/local/docker/mysql_slave_3307/log/:/var/log/mysql/ -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
docker run -p 3308:3306 --name mysql-slave-3308 -v /usr/local/docker/mysql_slave_3308/conf/my.cnf:/etc/mysql/conf.d/my.cnf -v /usr/local/docker/mysql_slave_3308/data/:/var/lib/mysql/ -v /usr/local/docker/mysql_slave_3308/sql/:/docker-entrypoint-initdb.d/ -v /usr/local/docker/mysql_slave_3308/log/:/var/log/mysql/ -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
4. 全部启动后,输入命令 docker ps -a -> 查看容器运行情况
5. 发现容器并没有启动成功,状态(STAUTS)为:Exited,使用命令 docker logs CONTAINER ID 查看
容器启动日志,核心错误内容如下
mysqld: File '/var/log/mysql/binlog.index' not found (Errcode: 13 - Permission denied)
6. 权限不足,得把 log 文件夹设置 '读写执' 权限
7. 输入命令 cd /usr/local/docker/mysql_master_3306/ -> 进入目录
8. 输入命令 chmod -R 777 log/ -> 设置 log 文件夹 '读写执' 权限
9. 输入命令 cd /usr/local/docker/mysql_slave_3307/ -> 进入目录
10. 输入命令 chmod -R 777 log/ -> 设置 log 文件夹 '读写执' 权限
11. 输入命令 cd /usr/local/docker/mysql_slave_3308/ -> 进入目录
12. 输入命令 chmod -R 777 log/ -> 设置 log 文件夹 '读写执' 权限
13. 输入命令 docker rm CONTAINER ID -> 删除刚刚启动失败的容器
14. 再把上面步骤 2,3 中的命令再执行一遍
15. 输入命令 docker ps -a -> 查看容器运行情况,所有容器都成功启动
在从库中配置主从同步命令
进入 master 主库容器
1. 输入命令 docker ps -a -> 查看容器运行情况
2. 输入命令 docker exec -it CONTAINER ID bash -> 进入容器,注意此 CONTAINER ID 为 主库容器 ID
3. 输入命令 mysql -u root -p -> 登录 MySQL
4. 回车,输入启动容器时配置的密码(123456)
5. 连接上主库后,输入命令 show master status; -> 查看 master 主库状态
mysql> show master status;
+---------------+----------+---------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+---------------+------------------+-------------------+
| binlog.000003 | 150 | masterSlaveDB | mysql | |
+---------------+----------+---------------+------------------+-------------------+
1 row in set (0.00 sec)
6. 其中 File 和 Position 是从库配置需要的参数
进入 slave 从库容器
1. 输入命令 docker ps -a -> 查看容器运行情况
2. 输入命令 docker exec -it CONTAINER ID bash -> 进入容器,注意此 CONTAINER ID 为 从库容器 ID
3. 输入命令 mysql -u root -p -> 登录 MySQL
4. 回车,输入启动容器时配置的密码(123456)
5. 输入命令 stop slave; -> 先停止 slave
6. 输入命令
change master to master_host='xxx.xxx.xxx.xxx',master_user='root',master_password='123456',master_log_file='binlog.000003',master_log_pos=150;
- master_host:主库服务器 ip 地址
- master_user:主库 MySQL 用户名
- master_password:主库 MySQL 密码
- master_log_file:为上面查询的主库 File 值 -> binlog.000003
- master_log_pos:为上面查询的主库 Position 值 -> 150
7. 输入命令 start slave; -> 开启 slave
8. 输入命令 show slave status \G; -> 查看从库状态
9. 如果它们两个状态为 Yes,就证明主从已实现同步
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
验证
1. 回到上面 master 主库的容器,查看一下 masterSlaveDB 库中的 masterSlaveTable 表中的数据
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| masterSlaveDB |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> use masterSlaveDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-------------------------+
| Tables_in_masterSlaveDB |
+-------------------------+
| masterSlaveTable |
+-------------------------+
1 row in set (0.00 sec)
mysql> select * from masterSlaveTable;
+----+------+-----------+-----------------------+
| id | type | name | description |
+----+------+-----------+-----------------------+
| 1 | 1 | 电饭煲 | 用来蒸饭 |
| 2 | 1 | 电热壶 | 用来烧水 |
| 3 | 1 | 空调 | 用来制冷或制热 |
| 4 | 2 | 菜刀 | 用来切菜 |
| 5 | 2 | 刨子 | 用来剥皮 |
| 6 | 2 | 打蛋器 | 用来搅拌鸡蛋 |
+----+------+-----------+-----------------------+
6 rows in set (0.00 sec)
mysql>
2. 回到上面 slave 从库的容器,查看一下 masterSlaveDB 库中的 masterSlaveTable 表中的数据
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| masterSlaveDB |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
mysql> use masterSlaveDB;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A
Database changed
mysql> show tables;
+-------------------------+
| Tables_in_masterSlaveDB |
+-------------------------+
| masterSlaveTable |
+-------------------------+
1 row in set (0.00 sec)
mysql> select * from masterSlaveTable;
+----+------+-----------+-----------------------+
| id | type | name | description |
+----+------+-----------+-----------------------+
| 1 | 1 | 电饭煲 | 用来蒸饭 |
| 2 | 1 | 电热壶 | 用来烧水 |
| 3 | 1 | 空调 | 用来制冷或制热 |
| 4 | 2 | 菜刀 | 用来切菜 |
| 5 | 2 | 刨子 | 用来剥皮 |
| 6 | 2 | 打蛋器 | 用来搅拌鸡蛋 |
+----+------+-----------+-----------------------+
6 rows in set (0.00 sec)
mysql>
3. 目前主从库中数据都是一致的
4. 现在来删除主库中的一条数据
5. 再次回到上面 master 主库的容器,使用 SQL 删除一条记录
mysql> delete from masterSlaveTable where id = 3;
Query OK, 1 row affected (0.00 sec)
mysql> select * from masterSlaveTable;
+----+------+-----------+--------------------+
| id | type | name | description |
+----+------+-----------+--------------------+
| 1 | 1 | 电饭煲 | 用来蒸饭 |
| 2 | 1 | 电热壶 | 用来烧水 |
| 4 | 2 | 菜刀 | 用来切菜 |
| 5 | 2 | 刨子 | 用来剥皮 |
| 6 | 2 | 打蛋器 | 用来搅拌鸡蛋 |
+----+------+-----------+--------------------+
5 rows in set (0.00 sec)
mysql>
6. 再次回到上面 slave 从库的容器,查询数据
mysql> select * from masterSlaveTable;
+----+------+-----------+--------------------+
| id | type | name | description |
+----+------+-----------+--------------------+
| 1 | 1 | 电饭煲 | 用来蒸饭 |
| 2 | 1 | 电热壶 | 用来烧水 |
| 4 | 2 | 菜刀 | 用来切菜 |
| 5 | 2 | 刨子 | 用来剥皮 |
| 6 | 2 | 打蛋器 | 用来搅拌鸡蛋 |
+----+------+-----------+--------------------+
5 rows in set (0.00 sec)
mysql>
7. 证明从库数据与主库同步成功
8. 上面的验证也可以在 Windows 本地使用 Navicat 远程连接后操作,那样的话就要开启端口的操作
安全组
注:如果服务器是在阿里云租用的需要设置安全组
1. 登录到阿里云
2. 进入到 '云服务器 ECS' 控制台
3. 左侧栏中选择 '实例'
4. 进入实例详情,点击左侧栏中 '本实例安全组'
5. 点击安全组中的 '配置规则'
6. 点击 '添加安全组规则' 按钮
7. 配置 3306、3307 和 3308 端口
防火墙
注:如果服务器是在阿里云租用的需要开启防火墙。服务器是默认不开启防火墙的,感觉不安全
1. 输入命令 systemctl status firewalld -> 查看防火墙状态
2. 输入命令 systemctl start firewalld -> 开启防火墙
3. 如果你不想开防火墙的话,那就输入命令 systemctl stop firewalld -> 关闭防火墙
4. 输入命令 systemctl restart firewalld.service -> 重启防火墙
端口
注:端口操作需要在开启防火墙的情况下才能执行成功。如下三条命令只需要执行一组即可
1. 输入命令 firewall-cmd --permanent --zone=public --add-port=3306/tcp -> 永久开放 3306 端口
输入命令 firewall-cmd --permanent --zone=public --add-port=3307/tcp -> 永久开放 3307 端口
输入命令 firewall-cmd --permanent --zone=public --add-port=3308/tcp -> 永久开放 3308 端口
2. 输入命令 firewall-cmd --zone=public --add-port=3306/tcp -> 临时开放 3306 端口
输入命令 firewall-cmd --zone=public --add-port=3307/tcp -> 临时开放 3307 端口
输入命令 firewall-cmd --zone=public --add-port=3308/tcp -> 临时开放 3308 端口
扩展
希望能够帮助到你
over