0%

MySQL主从复制

MySQL主从复制

由于数据的大量增加,访问量越来越复杂,有时候需要来部署多个数据库,通过数据库的复制策略,可以将一台mysql数据库服务器中的数据复制到其他的mysql数据库服务器之上,当各台数据库服务器上都包含相同数据的时候,前端应用通过访问mysql集群中任意一台服务器,都能够读取到相同的数据,这样,每台mysql服务器所需要承担的负载就会大大降低,从而提高整个系统的承载能力,达到系统扩展的目的

MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,另外一个或多个其它服务器充当从服务器。

Mysql的主从复制中主要有三个线程:master(binlog dump thread)、slave(I/O thread 、SQL thread),Master一条线程和Slave中的两条线程

master(binlog dump thread)主要负责Master库中有数据更新时,将更新时间写入到binlog中,并且Master会创建log dump线程通知slave库

slave(I/O thread)线程用于请求Master库,Master会返回binlog的名称以及当前数据更新的位置、binlog文件位置,并将Master库中的binlog保存在relay log中

slave(SQL thread)线程检测relay log更新,将更新的内容同步到数据库中,保证主从数据的同步

复制方式

主从复制的几种方式:

同步复制:
所谓的同步复制,意思是master的变化,必须等待slave-1,slave-2,…,slave-n完成后才能返回。这样,显然不可取,也不是MySQL复制的默认设置。比如,在WEB前端页面上,用户增加了条记录,需要等待很长时间。

异步复制:
如同AJAX请求一样。master只需要完成自己的数据库操作即可。至于slaves是否收到二进制日志,是否完成操作,不用关心,MySQL的默认设置。

半同步复制:
master只保证slaves中的一个操作成功,就返回,其他slave不管。这个功能,是由google为MySQL引入的

基本原理

MySQL复制是基于主服务器在二进制日志中跟踪所有对数据库的更改。因此,要进行复制,必须在主服务器上启用二进制日志。每个从服务器从主服务器接收主服务器已经记录到日志中的数据。

当一个从服务器连接主服务器时,它通知主服务器最后一次成功更新的位置。从服务器接收那时起发生的任何更新,保存在中继日志(relay log)中,重做中继日志的的更新时间。然后封锁并等待主服务器通知新的更新。从服务器执行备份并不干扰主服务器,灾备份过程中主服务器可以继续处理更新。

主从复制的数据完整性依赖于主库的binlog,只要主库的binlog不丢失,数据就不会丢失

mysqlbinlog可以访问到主库的binlog

过程

1
2
3
4
5
-- 查看binlog刷新到磁盘的频率,默认是1
-- sync_binlog为1,表示事务提交之前,将binlog刷新到磁盘,这样即使主机突然宕机,也只会损失prepared状态的事务,尽可能的保证了数据安全
-- sync_binlog为0,表示MySQL不控制binlog的刷新,由文件系统自己控制文件缓存的刷新
-- sync_binlog不为0和1时,表示n次binlog提交组之后才会刷新到磁盘
show variables like 'sync_binlog';
  • master将改变记录到bin log中,这些记录过程叫做二进制日志事件,binary log events
  • slave的io线程将master的bin log拷贝到它的中继日志(relay log)
  • slave的sql执行线程执行中继日志中的sql,将改变应用到自己的数据库中,MySQL的复制是异步且串行化的

由于复制过程是异步的,因此,master和slave之间的数据有可能存在延迟的现象,此时只能够保证数据最终的一致性

主从配置

主MySQL

修改my.cnf,在 [mysqld]模块下面添加以下几行

1
2
3
4
5
server-id = 11      //主服务器编号,id要唯一
log-bin=master_bin //指定二进制日志
log_slave_updates=true //允许从服务器更新
binlog-do-db=exam_admin //需要同步的二进制库名
binlog-ignore-db=mysql //不同步的二进制库名,与binlog-do-db互斥
1
2
3
4
5
6
7
-- 为所有从服务器授权所有数据库
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.80.%' IDENTIFIED BY '123456';
-- 刷新权限
FLUSH PRIVILEGES;
-- 要记下 Position 列的值
show master status;

从MySQL

修改my.cnf,在 [mysqld]模块下面添加以下几行

1
2
3
4
5
6
7
server-id = 22      //从服务器编号
read_only=1 //只读
relay_log=relay-log-bin //指定从服务器的中继日志
relay_log_index=slave-relay-bin.index //定义中继日志的位置和名称
// 防止更新不及时,SLAVE 重启后导致的主从复制出错
master_info_repository=TABLE
relay_log_info_repository=TABLE
1
2
3
4
5
6
7
-- 指定主服务器  master_log_pos是在show master status;时的position
change master to master_host='192.168.80.100',master_user='mysyslave',master_password='123456',master_log_file='master_bin.000001',master_log_pos=100;

-- 开启从服务器
start slave;
-- 要保证slave_IO_Running和slave_SQL_Running都是yes,主从配置成功
show slave status \G

如果要停止主从复制

1
stop slave;

如果要重新配置主从

1
2
stop slave;
reset master;

主从一致性检验工具

checksum、mysqldiff、pt-table-checksum等

主从架构

一主一从、一主多从、双主、级联同步、环形多主

主从架构

双主配置

master1

1
2
3
4
5
6
7
8
9
10
11
12
server-id = 11      //主服务器编号,id要唯一
log-bin=master_bin //指定二进制日志
log_slave_updates=true //允许从服务器更新
binlog-do-db=exam_admin //需要同步的二进制库名
binlog-ignore-db=mysql //不同步的二进制库名,与binlog-do-db互斥

# 作为从数据库时,有写入操作也需要进行二进制文件的修改
log-slave-updates
# 表示自增长字段每次递增的量
auto-increment-increment=2
# 自增长字段的起始值,两个主机的起始值配置不同
auto-increment-offset=1

master2

1
2
3
4
5
6
7
8
9
10
11
12
server-id = 12      //主服务器编号,id要唯一
log-bin=master_bin //指定二进制日志
log_slave_updates=true //允许从服务器更新
binlog-do-db=exam_admin //需要同步的二进制库名
binlog-ignore-db=mysql //不同步的二进制库名,与binlog-do-db互斥

# 作为从数据库时,有写入操作也需要进行二进制文件的修改
log-slave-updates
# 表示自增长字段每次递增的量
auto-increment-increment=2
# 自增长字段的起始值,两个主机的起始值配置不同
auto-increment-offset=2

两个主机之间需要相互复制

1
2
3
4
5
6
7
8
-- 两个mysql服务器都需要执行
-- 指定主服务器 master_log_pos是在show master status;时的position
change master to master_host='192.168.80.100',master_user='mysyslave',master_password='123456',master_log_file='master_bin.000001',master_log_pos=100;

-- 开启从服务器
start slave;
-- 要保证slave_IO_Running和slave_SQL_Running都是yes,主从配置成功
show slave status \G

为了防止两台MySQL之间循环复制,会在MySQL的binlog中记录当前MySQL的server-id,且两台机器的server-id参数不同,MySQL就可以判断出哪个变更是哪一个MySQL Server产生的,从而避免了循环复制的情况

级联复制

有时候在一些应用场景中,会存在读写压力差别比较大,读压力特别大,一个Master可能需要多台Slave才能支撑读的压力,但是一台Master给多台slave复制会消耗较多的资源,很容易造成复制的延时。

此时可以先有几台MySQL从master来进行复制,这几台MySQL称为第一级slave集群,然后其他slave再从第一级slave集群中进行复制,这些slave称为第二级slave集群