06__mysql-主从复制
一、MySQL集群概述
1. 集群的主要类型
- 高可用集群(High Available Cluster,HA)
- 高可用集群是指通过特殊的软件把独立的服务器连接起来,组成一个能够提供故障切换(Fail Over)功能的集群
2. 如何衡量高可用
可用性级别(指标) | 年度宕机时间 | 描述 | 叫法 |
---|---|---|---|
99% | 3.65天/年 | 基本可用系统 | 2个9 |
99.9% | 8.76小时/年 | 可用系统 | 3个9 |
99.99% | 52.6分钟/年 | 高可用系统 | 4个9 |
99.999% | 5.3分钟/年 | 抗故障系统 | 5个9 |
99.9999% | 32秒/年 | 容错系统 | 6个9 |
计算方法:
1年 = 365天 = 8760小时
99% = 8760 * 1% = 8760 * 0.01 = 87.6小时=3.65天
99.9 = 8760 * 0.1% = 8760 * 0.001 = 8.76小时
99.99 = 8760 * 0.0001 = 0.876小时 = 0.876 * 60 = 52.6分钟
99.999 = 8760 * 0.00001 = 0.0876小时 = 0.0876 * 60 = 5.26分钟
3. 常用的集群架构
- ==MySQL Replication==
- MySQL Cluster
- MySQL Group Replication (MGR) 5.7.17
- MariaDB Galera Cluster
- ==MHA==|Keepalived|HeartBeat|Lvs,Haproxy等技术构建高可用集群
二、MySQL复制简介
1. 什么是MySQL复制
- Replication可以实现将数据从一台数据库服务器(master)复制到一台到多台数据库服务器(slave)
- 默认情况下,属于异步复制,所以无需维持长连接
2. MySQL复制原理
简单来说,master将数据库的改变写入**==二进制日志==,slave同步这些二进制日志,并根据这些二进制日志进行==数据重演操作==**,实现数据异步同步。
详细描述:
- slave端的IO线程发送请求给master端的binlog dump线程
- master端binlog dump线程==获取二进制日志==信息(==文件名和位置信息==)发送给slave端的IO线程
- salve端IO线程获取到的内容==依次==写到slave端relay log里,并把master端的bin-log文件名和位置记录到master.info里
- salve端的SQL线程,检测到relay log中内容更新,就会解析relay log里更新的内容,并==执行这些操作==,从而达到和master数据一致
3. MySQL复制架构
3.1 双机热备(1主1从)
web_server >读写请求> mysql_master >复制>mysql_slave
默认情况下,master接受读写请求,slave只接受读请求以减轻master的压力。
3.2 级联复制 (1主多从)
web_server >读写请求> mysql_master >复制>mysql_slave >复制>mysql_slave
**优点:**进一步分担读压力
**缺点:**slave1 出现故障,后面的所有级联slave服务器都会同步失败
3.3 并联复制 (1主多从)
web_server >读写请求> mysql_master >复制>mysql_slave
>复制>mysql_slave
**优点:**解决上面的slave1的单点故障,同时也分担读压力
**缺点:**间接增加master的压力(传输二进制日志压力)
3.4 双主复制 (M-M)
web_server >读写请求> mysql_master1 >复制< mysql_master2
特点:
从命名来看,两台master好像都能接受读、写请求,但实际上,往往运作的过程中,同一时刻只有其中一台master会接受写请求,另外一台接受读请求。
三、MySQL复制搭建
1. 传统AB复制架构(M-S)
说明:当前环境中master上已有mysql数据库,版本为5.6.35
① 实现环境
mysql_master 192.168.2.115
mysql_slave 192.168.2.116
③ 搭建主从复制思路
- slave必须安装相同版本的mysql数据库软件
- master端必须开启二进制日志(binlog);slave端必须开启relay log日
- master端和slave端的server-id号必须不能一致
- slave端配置向master来同步数据
- master端必须创建一个复制用户
- 保证master和slave端初始数据一致
- 配置主从复制(slave端)
④ 主从搭建步骤
⑴ Slave安装MySQL软件
#!/bin/bash
#判断创建mysql用户
id mysql
[ $? -eq 1 ] && useradd -rs /sbin/nologin mysql
mkdir -p /root/soft/
cd /root/soft/
#下载安装包
wget https://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.35-linux-glibc2.5-x86_64.tar.gz
#解压
tar xf mysql-5.6.35-linux-glibc2.5-x86_64.tar.gz
mv mysql-5.6.35-linux-glibc2.5-x86_64 /usr/local/mysql
#更改属主属组
chown -R mysql. /usr/local/mysql/
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql
#注意:
#暂时不需要初始化数据库文件,只是安装好了和master相同版本的mysql数据库软件;后面向master来同步所有数据。
⑵ 修改主从配置文件
注意:master和slave都要修改!
- server-id必须不能一致;
- master需要开启二进制日志
- slave需要开启中继日志
[root@master ~]# cat /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port=3307
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/db01_3307.err
character_set_server=utf8mb4
server-id = 10
#开启二进制日志
log-bin=/usr/local/mysql/data/binlog
[root@slave ~]# cat /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/db02_3307.err
character_set_server=utf8mb4
server-id=20
#开启中继日志
relay-log=/usr/local/mysql/data/relaylog
⑶ master上的数据复制到slave
- 停止master上的mysql服务
[root@master ~]# mysqladmin shutdown -p123
- ==删除auto.cnf文件==
[root@master data]# rm -f /usr/local/mysql/data/auto.cnf
说明:auto.cnf文件里保存的是每个数据库实例的UUID信息,代表数据库的唯一标识
- 同步master数据到slave
[root@master data]# rsync -av /usr/local/mysql/data/ 192.168.2.116:/usr/local/mysql/data
- 启动master和slave数据库
[root@master ~]# service mysql start
[root@slave ~]# service mysql start
⑷ slave配置向master同步数据
- master端创建授权用户
mysql>
grant replication slave on *.* to 'slave'@'10.1.1.%' identified by '123';
grant replication slave on *.* to 'slave'@'192.168.2.%'identified by '123';
#用户名:'slave'@'10.1.1.%'
#密码:123
mysql> flush privileges;
- 查看master上正在写的二进制文件名和位置
先加锁,防止两边数据不一致
mysql> flush tables with read lock;
查看当前数据库的二进制日志写到什么位置(只有打开二进制日志,这句命令才有结果)
mysql> show master status;
+-----------------+----------+--------------+------------------+----------
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------+----------+--------------+------------------+----------------
| mybinlog.000002 | 405 | | | |
+-----------------+----------+--------------+------------------+----------
- slave上配置同步信息
mysql> change master to master_host='10.1.1.37',master_user='slave',master_password='123',master_port=3306,master_log_file='mybinlog.000004',master_log_pos=405;
说明:
master_host master的IP
master_user 复制的用户
master_password 复制用户密码
master_port master的端口号
master_log_file master正在写的二进制文件名,锁表后查看的
master_log_pos master正在写的二进制位置
- 启动复制线程,开始同步
mysql> start slave;
mysql> show slave status\G;
.....
Slave_IO_Running: Yes 代表成功连接到master并且下载日志
Slave_SQL_Running: Yes 代表成功执行日志中的SQL语句
启动slave报如下错误:
mysql> start slave;
ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
解决:删除relay-log.info,重启mysql服务或者mysql>reset slave;
- master上解锁
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
- 测试验证
master上插入数据:
mysql> select * from db02.t1;
mysql> insert into t1 values(4,'tom');
Query OK, 1 row affected (0.00 sec)
slave上查看数据:
mysql> select * from db02.t1;
⑤ 数据不一致导致同步失效
通过变量sql_slave_skip_counter
临时跳过事务进行处理
SET GLOBAL sql_slave_skip_counter = N N代表跳过N个事务
举例说明:
mysql> SET GLOBAL sql_slave_skip_counter=1;
mysql> stop slave;
mysql> start slave;
注意:
1. 跳过事务应该在slave上进行
2. 传统的AB复制方式可以使用变量:sql_slave_skip_counter,基于GTIDs的方式不支持
2. 基于GTIDs的AB复制架构(M-S)
2.1 关于GTIDs概述
-
GTIDs(Global transaction identifiers)全局事务标识符,是mysql 5.6新加入的一项技术
-
当使用GTIDs时,每一个事务都可以被识别并且跟踪
-
添加新的slave或者当发生故障需要将master身份或者角色迁移到slave上时,都无需考虑是哪一个二进制日志以及哪个position值,极大简化了相关操
-
GTIDs是完全基于事务的,因此不支持MYISAM存储引擎
-
GTIDs由source_id和transaction_id组成:
1)source_id来自于server_uuid,可以在auto.cnf中看到
2)transation_id是一个序列数字,自动生成.
-
在mysql 5.6.7之前,使用==mysql_upgrade==命令会出现问题
2.2 基于GTIDs的配置
利用已有的传统m-s环境升级至基于GITDs的Replication
- 为了保证数据一致性,master和slave设置为只读模式 (主+从)
- 修改配置文件支持GTIDs (主+从)
- 重启数据库 (主+从)
- ==从服务器上重新配置同步== (从)
① 主从设置只读模式
mysql> set @@global.read_only=ON;
② 修改配置文件支持GTIDs
[root@master ~]# cat /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port=3307
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/db01_3307.err
character_set_server=utf8mb4
log-bin=/usr/local/mysql/data/binlog
server-id = 10
gtid-mode=on
log-slave-updates=1
enforce-gtid-consistency
[root@slave ~]# cat /etc/my.cnf
[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/db02_3307.err
log-bin=/usr/local/mysql/data/mybinlog #=> 这里一定要设置
character_set_server=utf8mb4
server-id = 20
relay-log = /usr/local/mysql/data/relaylog
log-slave-updates=1
gtid-mode=on
enforce-gtid-consistency=1
skip-slave-start
说明:
1)开启GITDs需要在master和slave上都配置gtid-mode,log-bin,log-slave-updates,enforce-gtid-consistency(该参数在5.6.9之前是--disable-gtid-unsafe-statement)
2)其次,slave还需要增加skip-slave-start参数,目的是启动的时候,先不要把slave起来,需要做一些配置
3)基于GTIDs复制从服务器必须开启二进制日志!
③ 重起主从数据库服务
[root@master ~]# service mysql restart
Starting MySQL.. SUCCESS!
[root@slave ~]# service mysql restart
Starting MySQL.. SUCCESS!
④ slave重新配置同步(重要)
mysql> change master to master_host='192.168.2.115',master_user='slave',master_password='123',master_port=3307,master_auto_position=1;
注意:
1.确保有复制用户
2.主要区别于传统复制的参数是:master_auto_position=1
⑤ slave上启动同步线程
mysql> start slave;
⑥ 关闭只读模式
mysql> set @@global.read_only=OFF;
⑦ 测试验证
[root@master ~]# show master status;
Executed_Gtid_Set 有值时GITDs为已开
2.3 基于GTIDs手动跳过事务
指定需要跳过的GTIDs编号
SET GTID_NEXT='aaa-bbb-ccc-ddd:N';
开始一个空事务
BEGIN;
COMMIT;
使用下一个自动生成的全局事务ID。
SET GTID_NEXT='AUTOMATIC';
举例说明:
mysql> stop slave;
mysql> SET @@SESSION.GTID_NEXT= '044e6392-cf9b-11e8-a748-000c294ca304:3';
mysql> BEGIN;
mysql> commit;
mysql> SET @@SESSION.GTID_NEXT= 'AUTOMATIC';
mysql> start slave;
mysql> show slave status\G
说明:需要跳过哪个事务,需要手动查看relaylog文件得到
[root@slave1 data]# ../bin/mysqlbinlog relay.000003|less
。。。。
# at 756
#181015 12:04:45 server id 10 end_log_pos 817 CRC32 0x5374f49e GTID [commit=yes]
SET @@SESSION.GTID_NEXT= '044e6392-cf9b-11e8-a748-000c294ca304:3'/*!*/;