目录结构# 1
2
3
4
5
6
.
├── master
│ └── my . cnf
├── slave
│ └── my . cnf
└── docker - compose . yml
master
:主配置
slave
:从配置
docker-compose
:通过docker-compose
进行容器配置和启动
master/my.cnf# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/8.3/en/server-configuration-defaults.html
[mysqld]
host-cache-size = 0
skip-name-resolve
datadir = /var/lib/mysql
socket = /var/run/mysqld/mysqld.sock
secure-file-priv = /var/lib/mysql-files
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
# 自定义部分
log-bin = master-bin
binlog-format = row # row 按行重放,statement 重放 sql 语句,mixed 默认基于 statement,一旦发现基于 sql 无法精准重放时,会使用 row,MySQL 默认是基于 statement 的复制
binlog-do-db = test # 开启 binlog 的数据库名,如果有多个数据库,那么可以重复设置
server-id = 1 # server-id 不能和任何 主或从 重复
# 自定义部分
[client]
socket = /var/run/mysqld/mysqld.sock
!includedir /etc/mysql/conf.d/
slave/my.cnf 和master/my.cnf
内容基本一致,但是server-id
不能重复
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/8.3/en/server-configuration-defaults.html
[mysqld]
host-cache-size = 0
skip-name-resolve
datadir = /var/lib/mysql
socket = /var/run/mysqld/mysqld.sock
secure-file-priv = /var/lib/mysql-files
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
# 自定义部分
log-bin = master-bin
binlog-format = row
binlog-do-db = test
server-id = 2 # 注意不要重复
# 自定义部分
[client]
socket = /var/run/mysqld/mysqld.sock
!includedir /etc/mysql/conf.d/
docker-compose.yml# 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
version : "3"
# 定义一个 network,方便主从容器之间通信。名字可以随便起。
networks :
mysql-master-slave-network :
driver : bridge
# 定义服务
services :
mysql-master :
image : mysql
container_name : mysql-master
ports :
- 3306 : 3306
volumes :
- "./master/:/etc/mysql/conf.d" # 将 master 中的配置映射到容器内
environment :
MYSQL_ROOT_PASSWORD : root # 设置 MySQL root 密码
restart : unless-stopped # 启动方式
networks :
- mysql-master-slave-network # 必须指定容器的网络,不然在 bridge 模式下容器无法正确通信
mysql-slave :
image : mysql
container_name : mysql_slave
ports :
- 3307 : 3306
volumes :
- "./slave/:/etc/mysql/conf.d"
environment :
MYSQL_ROOT_PASSWORD : root
restart : unless-stopped
networks :
- mysql-master-slave-network
主从设置# 获取master
的状态# 连接进master
,然后执行查看命令
1
2
3
4
5
6
7
$ mycli mysql://root:root@localhost:3306
> show master status;
+-------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-------------------+----------+--------------+------------------+-------------------+
| master-bin.000003 | 352 | | | |
+-------------------+----------+--------------+------------------+-------------------+
File
就是当前binlog
文件,Position
是偏移量,说明下一条命令从这里开始。File
和Position
后面在slave
中会使用到。
如果没有数据库,则需要先创建一个数据库,否则slave
不会正常同步。(slave
也需要先创建一个相同的数据库,才能开始同步)
1
2
3
create database test ;
Query OK , 1 row affected
Time : 0 . 006 s
配置从库# 连接进slave
1
$ mycli mysql : //root:root@localhost:3307
查看slave
的状态,默认应该是空的 1
2
3
4
5
6
7
8
9
10
11
12
13
14
> show slave status \ G ;
*************************** [ 1 . row ] ***************************
Slave_IO_State |
Master_Host |
Master_User |
Master_Port |
Connect_Retry |
Master_Log_File |
Read_Master_Log_Pos |
Relay_Log_File |
Relay_Log_Pos |
Relay_Master_Log_File |
Slave_IO_Running |
Slave_SQL_Running |
创建数据库 1
2
3
> create database test ;
Query OK , 1 row affected
Time : 0 . 006 s
连接到主库 1
2
3
> change master to master_host = 'mysql-master' , master_user = 'root' , master_password = 'root' , master_port = 3306 , master_log_file = 'master-bin.000003' , master_log_pos = 352 ;
Query OK , 0 rows affected
Time : 0 . 017 s
master_host
:可以填写mysql-master
,因为我们已经指定了主和从都在这个网络里面,只是他们的ip
不同,docker
会帮我们进行转发
master_port
:是主机容器内部的端口,而不是我们映射出来的端口,因为我们是直接连接的容器内部。
master_log_file
:就是我们看到的master
的File
信息,指定我们的slave
从这个binlog
开始同步
master_log_pos
:就是我们看到的master
的Position
信息,指定我们的slave
从这个偏移量开始同步
其他的配置都是mysql
的账户信息。
启动主从复制 1
2
3
> start slave ;
Query OK , 0 rows affected
Time : 0 . 018 s
查看slave
状态,如果Slave_IO_Running
和Slave_SQL_Running
都为Yes
,则说明启动成功,如果有一个显示为No
,则可以查看Last_IO_Error
或Last_SQL_Error
的错误信息。
失败示例,可以看到Last_IO_Error
字段显示主从的server-id
重复了,所以启动失败 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
> show slave status \ G
*************************** [ 1 . row ] ***************************
Slave_IO_State |
Master_Host | mysql - master
Master_User | root
Master_Port | 3306
Connect_Retry | 60
Master_Log_File | master - bin . 000004
Read_Master_Log_Pos | 158
Relay_Log_File | bce0051a5191 - relay - bin . 000001
Relay_Log_Pos | 4
Relay_Master_Log_File | master - bin . 000004
Slave_IO_Running | No
Slave_SQL_Running | Yes
...
Master_SSL_Verify_Server_Cert | No
Last_IO_Errno | 13117
Last_IO_Error | Fatal error : The replica I / O thread stops because source and replica have equal MySQL server ids ; these ids must be different for replication to work ( or the --replicate-same-server-id option must be used on replica but this does not always make sense; please check the manual before using it).
Last_SQL_Errno | 0
Last_SQL_Error |
Replicate_Ignore_Server_Ids |
...
成功示例,Slave_IO_Running
和Slave_SQL_Running
均为Yes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
> show slave status \ G
*************************** [ 1 . row ] ***************************
Slave_IO_State | Waiting for source to send event
Master_Host | mysql - master
Master_User | root
Master_Port | 3306
Connect_Retry | 60
Master_Log_File | master - bin . 000003
Read_Master_Log_Pos | 352
Relay_Log_File | 89 c93f9a6591 - relay - bin . 000002
Relay_Log_Pos | 329
Relay_Master_Log_File | master - bin . 000003
Slave_IO_Running | Yes
Slave_SQL_Running | Yes
...
Last_IO_Errno | 0
Last_IO_Error |
Last_SQL_Errno | 0
Last_SQL_Error |
Replicate_Ignore_Server_Ids |
...
测试同步# 连接到master
,在test
库中新建一个表 1
2
3
4
5
6
7
8
9
10
$ mycli mysql : // root : root @ localhost : 3306
> use test ;
> create table T (
-> id int primary key ,
-> a int ,
-> b int ,
-> c int
-> )
Query OK , 0 rows affected
Time : 0 . 027 s
连接到slave
,进入test
库查看所有的表,会发现自动创建了一个 T 表 1
2
3
4
5
6
7
8
9
10
11
$ mycli mysql : // root : root @ localhost : 3307
> use test ;
> show tables ;
+ -------------------+
| Tables_in_test |
+ -------------------+
| T |
+ -------------------+
1 rows in set
Time : 0 . 010 s