实现MySQL主从复制

First Post:

Last Update:

Word Count:
1.5k

Read Time:
6 min

一、开启MySQL的binlog

判断MySQL是否已经开启binlog

1
SHOW VARIABLES LIKE 'log_bin';

查看MySQL的binlog模式

1
show global variables like "binlog%"; #查看binlog_format字段

binlog常用的命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#查看日志开启状态 
show variables like 'log_%';
#查看所有binlog日志列表
show master logs;
#查看最新一个binlog日志的编号名称,及其最后一个操作事件结束点
show master status;
#刷新log日志,立刻产生一个新编号的binlog日志文件,跟重启一个效果
flush logs;
#清空所有binlog日志
reset master;
#可以将二进制文件转为可阅读的sql语句。
mysqlbinlog mysql-bin.000005
恢复命令的语法格式:
mysqlbinlog mysql-bin.0000xx | mysql -u用户名 -p密码 数据库名
常用参数选项解释:
–start-position=875 起始pos点
–stop-position=954 结束pos点
–start-datetime=“2016-9-25 22:01:08” 起始时间点
–stop-datetime=“2019-9-25 22:09:46” 结束时间点
–database=xxx指定只恢复xxx数据库(一台主机上往往有多个数据库,只限本地log日志)
实际是将读出的binlog日志内容,通过管道符传递给mysql命令。这些命令、文件尽量写成绝对路径;

修改mysqlmy.cnf配置文件
一般默认是在/etc/my.cnf路径下

mysqld下添加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#第一种方式:
#开启binlog日志
log_bin=ON
#binlog日志的基本文件名
log_bin_basename=/var/lib/mysql/mysql-bin
#binlog文件的索引文件,管理所有binlog文件
log_bin_index=/var/lib/mysql/mysql-bin.index
#配置serverid
server-id=1

#第二种方式:
#此一行等同于上面log_bin三行,这里可以写绝对路径,也可以直接写mysql-bin(后者默认就是在/var/lib/mysql目录下)
log-bin=/var/lib/mysql/mysql-bin
#配置serverid
server-id=1

修改完配置后,重启mysql。执行SHOW VARIABLES LIKE 'log_bin'; Value 值为 ON即可。

详细binlog的配置简介

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[mysqld]
#设置日志三种格式:STATEMENT、ROW、MIXED 。
binlog_format = mixed
#设置日志路径,注意路经需要mysql用户有权限写,这里可以写绝对路径,也可以直接写mysql-bin(后者默认就是在/var/lib/mysql目录下)
log-bin = /data/mysql/logs/mysql-bin.log
#设置binlog清理时间
expire_logs_days = 7
#binlog每个日志文件大小
max_binlog_size = 100m
#binlog缓存大小
binlog_cache_size = 4m
#最大binlog缓存大小
max_binlog_cache_size = 512m
#配置serverid
server-id=1
  • STATMENT模式(默认):基于SQL语句的复制(statement-based replication, SBR),每一条会修改数据的sql语句会记录到binlog中。
    优点:不需要记录每一条SQL语句与每行的数据变化,这样子binlog的日志也会比较少,减少了磁盘IO,提高性能。

  • 缺点:在某些情况下会导致master-slave中的数据不一致(比如:delete from t where a>=4 and t_modified<=’2018-11-10’ limit 1;在主库执行这个语句的时候,如果使用的是a索引,会删除(4,4,’2018-11-10’)这条记录,如果使用的是t_modified的索引则会删除(5,5,’2018-11-09’);所以在执行这条sql语句的时候提示: Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
    由于 statement 格式下,记录到 binlog 里的是语句原文,因此可能会出现这样一种情况:在主库执行这条 SQL 语句的时候,用的是索引 a;而在备库执行这条 SQL 语句的时候,却使用了索引 t_modified。因此,MySQL
    认为这样写是有风险的。 sleep()函数, last_insert_id(),以及user-defined
    functions(udf)等也会出现问题);

  • ROW:``基于行的复制(row-based replication, RBR)格式:不记录每一条SQL语句的上下文信息,仅需记录哪条数据被修改了,修改成了什么样子了。
    优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。
    缺点:会产生大量的日志,尤其是alter table的时候会让日志暴涨。

  • MIXED:``混合模式复制(mixed-based replication, MBR):以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。

二、配置主库

更改/etc/my.cnf,在[mysqld]下加入

1
2
3
4
#mysql服务id,取值在1到2的32次方减一,默认为1
server-id=1
#表示是否只读,1为只读,0为读写
read-only=0

创建拥有主从复制权限的账户

1
2
3
4
# '%'表示允许任意主机连接,mysql_native_password为mysql的一个身份认证插件
create user '用户名'@'%' identified with mysql_native_password by '密码'
#分配主从复制权限,ON *.*子句表示MySQL中的所有数据库和所有对象。
grant replication slave on *.* to '用户名'@'%'

然后重启mysql

查看binlog文件坐标

1
show master status
File Position Binlog_Do_DB Binlog_Ignore_DB Executed_Gtid_Set
mysql-bin.000001 1361 mysql

三、配置从库

更改从库/etc/my.cnf,在[mysqld]下加入

1
2
3
4
5
#mysql服务id,取值在1到2的32次方减一,默认为1
server-id=2
#表示是否只读,1为只读,0为读写
read-only=1
#super-read-only=1表示超级管理员是否读写

重启mysql

登入从库mysql,执行命令

mysql8.0.23语法

1
change replication source to SOURCE_HOST='主库IP地址',SOURCE_PORT=主库端口号,SOURCE_USER='主库开启主从复制权限的用户',SOURCE_PASSWORD='密码',SOURCE_LOG_FILE='binlog文件名',SOURCE_LOG_POS=1361

mysql8.0.23之前的版本

1
change master to master_host='主库IP地址',master_port=主库端口号,master_user ='主库开启主从复制权限的用户',master_password ='密码',master_log_file ='binlog文件名',master_log_pos = 1361

_log_file和_log_pos通过show master status命令查看

四、开启同步

1
2
start replica; #8.0.22之后
start slave; #8.0.22之前

五、查看主从同步状态

1
2
show replica status; #8.0.22之后
show slave status; #8.0.22之前