实现MySQL主从复制

实验准备:

在Pc上安装两个MySQL,分别监听3307和3308端口,在centos7上也安装一个MySQL,这样我们就有三个slave!首先我们要保证4个MySQL上的数据一致,并且配置好各个的日志,这样即使出错了,也容易找出错误。

  • Slave1:MySQL3307
  • Slave2:MySQL3308
  • Slave3:Centos7上的MySQL
  • Master: 运行在3306端口的MySQL

修改Master的配置

1
2
3
4
5
6
7
8
9
10
11
[mysqld]
server-id=1 //[必须]服务器唯一ID,默认是1,可以随便配置,只要不重复即可
binlog-do-db = xxx // 同步的数据库名,如有多个写多行
binlog-ignore-db =mysql // 不需要备份的数据库,如有多个写多行
read-only =0 // 主机,读写都可以
log-bin=mysql-bin //[必须]启用二进制日志
binlog-format =mixed // bin的格式
relay-log=mysql-relay // 中继日志文件名
expire-logs-days=20 // 日志最长保存时间
max_binlog_size = 100M // 日志最大容量
slave-skip-errors=all // 跳过所有错误

修改Slave的配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#MySQL3307
[mysqld]
log-bin=mysql-bin //[不是必须]启用二进制日志
server-id=3307 //[必须]服务器唯一ID,默认是1,可以随便配置,只要不重复即可
replicate-do-db =test // 复制某个库,如有多个写多行
replicate-ignore-db=mysql // 不复制某个库,如有多个写多行

#MySQL3308
[mysqld]
log-bin=mysql-bin //[不是必须]启用二进制日志
server-id=3308 //[必须]服务器唯一ID,默认是1,可以随便配置,只要不重复即可
replicate-do-db =test // 复制某个库,如有多个写多行
replicate-ignore-db=mysql // 不复制某个库,如有多个写多行

#Centos7
[mysqld]
log-bin=mysql-bin //[不是必须]启用二进制日志
server-id=3 //[必须]服务器唯一ID,默认是1,可以随便配置,只要不重复即可
replicate-do-db =test // 复制某个库,如有多个写多行
replicate-ignore-db=mysql // 不复制某个库,如有多个写多行

保存修改后重启4个MySQL服务

在Master创建3个MySQL用户

1
2
3
4
5
6
7
grant replication client,replication slave on *.* to slave3307@'%' identified by 'slave3307';

grant replication client,replication slave on *.* to slave3308@'%' identified by 'slave3308';

grant replication client,replication slave on *.* to centos7@'%' identified by 'centos7';

flush privileges;

登录Master执行命令查看log_pos和log_file

1
2
3
4
5
6
show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000062 | 8233| | |
+------------------+----------+--------------+------------------+

注意 执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化

配置从服务器Slave,下面的命令分别在3个MySQL上执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
change master to master_host='192.168.19.254',master_port=3306,master_user='slave3307',
master_password='slave3307',master_log_file='mysql-bin.000062',master_log_pos=8233;

start slave #启动从服务器复制功能

change master to master_host='192.168.19.254',master_port=3306,master_user='slave3308',
master_password='slave3308',master_log_file='mysql-bin.000062',master_log_pos=8233;

start slave #启动从服务器复制功能

change master to master_host='192.168.19.254',master_port=3306,master_user='centos7',
master_password='centos7',master_log_file='mysql-bin.000087',master_log_pos=8233;

start slave #启动从服务器复制功能

检查Slave复制功能的状态

1
show slave status\G

注意 Slave_IO及Slave_SQL进程必须正常运行,即YES状态,否则都是错误的状态(如:其中一个NO或者出现Connection)。有时候是server-id配置错误、防火墙拦截或账户没有权限,仔细检查各个的错误日志,就能很快找到问题所在。

END 以上操作过程,主从服务器配置完成

1
2
3
4
#在Windows上注册MySQL添加服务

C:\phpStudy\MySQL3307\bin\mysqld install mysql3307 --defaults-file="C:\phpStudy\MySQL3307\my.ini"
C:\phpStudy\MySQL3308\bin\mysqld install mysql3308 --defaults-file="C:\phpStudy\MySQL3308\my.ini"

MySQL主从复制跳过错误两种方式:

1
2
3
4
5
6
7
8
9
10
11
1.跳过指定数量的事务:

mysql>stop slave ;
mysql>SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1; #跳过一个事务
mysql>start slave;

2.修改mysql的配置文件,通过slave_skip_errors参数来跳所有错误或指定类型的错误
vi /etc/my.cnf
[mysqld]
slave-skip-errors=1062,1053,1146 #跳过指定error no类型的错误
slave-skip-errors=all #跳过所有错误

2018年10月3号更新:
注意:
如果你是直接复制MySQL的安装目录,而你的MySQL的版本又是5.6及以后的版本,那你有可能出现下面的问题:

1
Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work.

mysql 5.6的复制引入了uuid的概念,各个复制结构中的server_uuid得保证不一样,但是查看到直接复制data文件夹后server_uuid是相同的

1
show variables like '%server_uuid%';

解决方法:
找到data文件夹下的auto.cnf文件,修改里面的uuid值,保证各个db的uuid不一样,重启db即可

附一个正确slave status的信息

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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58

mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 127.0.0.1
Master_User: slave3307
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000007
Read_Master_Log_Pos: 602
Relay_Log_File: mysql-relay.000005
Relay_Log_Pos: 765
Relay_Master_Log_File: mysql-bin.000007
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 602
Relay_Log_Space: 1384
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: fe1b230d-6ee9-11e8-b0c6-9c5c8e103115
Master_Info_File: C:\phpStudy\MySQL3307\data\master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
1 row in set (0.00 sec)

2020年03月15号更新:

binlog_do_db是指定binlog日志记录那些库的二进制日志。replicate_do_db则在slave库中指定同步那些库的binlog日志。
在主从互备环境中,有没有必要每个服务器都同时配置binlog_do_db和replicate_do_db?理由是什么?

binlog-do-db:指定mysql的binlog日志记录哪个db
replicate_do_db:参数是在slave上配置,指定slave要复制哪个库

在master上设置binlog_do_弊端:
1、过滤操作带来的负载都在master上
2、无法做基于时间点的复制(利用binlog)

如何删除日志?
利用 RESET MASTER 或者 purge

reset master :删除所有的binglog日志文件,并将日志索引文件清空,重新开始所有新的日志文件。用于第一次进行搭建主从库时,进行主库binlog初始化工作

注意reset master 不同于 purge binary log的两处地方

  1. reset master 将删除日志索引文件中记录的所有binlog文件,创建一个新的日志文件起始值从000001 开始,然而purge binary log 命令并不会修改记录binlog的顺序的数值
  2. reset master 不能用于有任何slave 正在运行的主从关系的主库。因为在slave 运行时刻 reset master 命令不被支持,reset master 将master 的binlog从000001 开始记录,slave 记录的master log 则是reset master 时主库的最新的binlog,从库会报错无法找的指定的binlog文件

purge使用事例

1
2
3
4
5
6
# 清除mysql-bin.010日志
purge master logs to 'mysql-bin.010’;
# 清除2016-02-28 13:00:00前的日志
purge master logs before '2016-02-28 13:00:00';
# 清除3天前的bin日志
purge master logs before date_sub(now(), interval 3 day);
  • 作者: Sam
  • 发布时间: 2017-11-17 22:28:06
  • 最后更新: 2020-03-15 14:10:35
  • 文章链接: https://ydstudios.gitee.io/post/34c3deb2.html
  • 版权声明: 本网所有文章除特别声明外, 禁止未经授权转载,违者依法追究相关法律责任!