原理总结
异步复制:在主节点写入日志即返回成功,默认情况下MySQL5.5/5.6/5.7和mariaDB10.0/10.1的复制功能是异步的。异步复制可以实现最佳的性能,主库把binlog日志发送给从库,这一动作就结束了,并不验证从库,会造成主从库数据不一致。
GTID复制不像传统的复制方式(异步复制、半同步复制)需要找到binlog(MASTER_LOG_FILE)和POS点(MASTER_LOG_POS),只需要知道master的IP、端口、账号、密码即可。因为复制是自动的,MySQL会通过内部机制GTID自动找点同步。
GTID复制名词释义:
GTID工作流程:
半同步复制:一主多从模式下,有一个从节点返回成功,即成功,不必等待多个节点全部返回。
MySQL半同步,MySQL5.5由Google贡献的补丁才开始支持半同步复制(semi Replication)模式,该模式可以确保从服务器接收完主服务器发送的binlog日志文件并写入自己的中继日志(relay log)里,然后会给主服务器一个反馈,告诉对方已经接收到完毕,这时主库线程才返回当前session告知操作完成,当出现超时情况时,源主服务器会暂时切换到异步复制模式,直到至少有一台设置为半同步复制模式的从服务器及时收到信息为止。
主从同步可以同步多个数据库,也可以设置为一个数据库同步,如果设置一个数据库,在从服务器上其他数据可以写操作。
半同步复制模式在主服务器和从服务器同时启用,否则主服务器默认使用异步复制模式。
实验环境:
特别提醒:在数据库中进行操作时,事实上大小写都是通用的,但是作为一个专业人士 ?? ,我们还是使用大写
主从复制的要求:
主从复制的原理:
mysql的主从配置又叫replication,AB复制,基于binlog二进制日志,主数据库必须开启binlog二进制日志才能进行复制。
配置主库
1.下载mysql的安装包,解压
[root@server1 ~]# tar xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
2.选择下面五个包安装
[root@server1 ~]# yum install mysql-community-client-5.7.24-1.el7.x86_64.rpm
mysql-community-common-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-server-5.7.24-1.el7.x86_64.rpm
[root@server1 ~]# scp mysql-community-client-5.7.24-1.el7.x86_64.rpm
mysql-community-common-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-server-5.7.24-1.el7.x86_64.rpm server2:/root ##如果你写server2的话,需要提前在本机上对server2进行地址解析
4.server2也安装mysql
[root@server2 ~]# yum install mysql-community-client-5.7.24-1.el7.x86_64.rpm
mysql-community-common-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-5.7.24-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.24-1.el7.x86_64.rpm
mysql-community-server-5.7.24-1.el7.x86_64.rpm
[root@server1 ~]# vim /etc/my.cnf
[root@server1 ~]#
[root@server1 ~]# systemctl start mysqld
6.开启服务之后生成了一个临时密码,使用临时密码进行数据库安全初始化
[root@server1 ~]# grep password /var/log/mysqld.log
[root@server1 ~]# mysql_secure_installation
安全初始化登陆的时候使用的是临时密码,接下来要自己设置数据库的密码,这个密码必须有特殊字符,英文字母的大小写还有数字
7.登陆数据库并授权
[root@server1 ~]# mysql -p
mysql> SHOW DATABASES;
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'172.25.6.%' IDENTIFIED BY 'ZHOUpeng123.';
mysql> SHOW MASTER STATUS;
参数 | 解释 |
---|---|
REPLICATION | 表示复制的权限 |
* .* | 表示对所有哭的所有表都授权 |
repl | 用户名 |
‘172.25.6.%’ | 授权172.25.6网段的所有都可以同步 |
配置从库
8.server2同样编辑配置文件,然后进行安全初始化
[root@server2 ~]# vim /etc/my.cnf
server-id = 2 ##文件末写入
[root@server2 ~]# ll /var/lib/mysql ##第一次启动前要保证这个目录里没有数据
total 0
[root@server2 ~]# systemctl start mysqld
[root@server2 ~]# grep password /var/log/mysqld.log
[root@server2 ~]# mysql_secure_installation
设置完新密码,第一个选项回车跳过,其他的输入Y就好了
9.安全初始化完成之后登陆数据库进行授权
[root@server2 ~]# mysql -p
##查看所有的表
mysql> SHOW DATABASES;
##配置主库的信息
mysql> CHANGE MASTER TO MASTER_HOST='172.25.6.1', ##主库的ip地址
MASTER_USER='repl', ##主库的用户
MASTER_PASSWORD='ZHOUpeng123.', ##主库用户的密码
MASTER_LOG_FILE='mysql-bin.000002', ##主库的日志文件
MASTER_LOG_POS=690; ##主库的状态码
mysql>
mysql> START SLAVE; ##开启从库
查看从库状态
mysql> SHOW SLAVE STATUS\G ##可以看到的当前两个进程都是yes,表示主库和从库的数据一致
10.回到server1上
查看mysql数据目录下的文件,有刚刚显示的日志文件
[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# ls
再次登陆数据库,创建数据
[root@server1 mysql]# mysql -p
mysql> CREATE DATABASE test; ##创建数据库test
mysql> USE test; ##进入到数据库test
mysql> SHOW TABLES; ##查看表
mysql> CREATE TABLE redhat ( ##创建表redhat
-> username varchar(10) not null,
-> password varchar(15) not null);
mysql> DESC redhat; ##查看表的结构
mysql> INSERT INTO usertd VALUES ('user1','123'); ##向表中插入信息
mysql> SELECT * FROM usertd; ##查看表的所有信息
11.server2查看,数据是否同步
mysql> SHOW DATABASES; ##查看所有数据库,可以看到现在有一个test数据库
mysql> USE test; ##进入到test数据库的环境
mysql> SELECT * FROM redhat; ##查看redhat表的所有信息
mysql> quit ##退出
GTID即全局事务ID (global transaction identifier), 其保证为每一个在主上提交的事务在复制集群中可以生成一个唯一的ID。GTID最初由google实现,官方MySQL在5.6才加入该功能。mysql主从结构在一主一从情况下对于GTID来说就没有优势了,而对于2台主以上的结构优势异常明显,可以在数据不丢失的情况下切换新主。
GTID实际上是由UUID+TID (即transactionId)组成的。其中UUID(即server_uuid) 产生于auto.conf文件(cat /data/mysql/data/auto.cnf),是一个MySQL实例的唯一标识。TID代表了该实例上已经提交的事务数量,并且随着事务提交单调递增,所以GTID能够保证每个MySQL实例事务的执行(不会重复执行同一个事务,并且会补全没有执行的事务)。
GTID在一组复制中,全局唯一。通过GDIT保证每个主库上提交的事务在集群中有一个唯一的ID.这种方式强化了数据库的主备一致性,故障恢复以及容错能力。
主从复制,默认是通过pos复制(postion),就是说在日志文档里,将用户进行的每一项操作都进行编号(pos),每一个event都有一个起始编号,一个终止编号,我们在配置主从复制时从节点时,要输入master的log_pos值就是这个原因,要求它从哪个pos开始同步数据库里的数据,这也是传统复制技术。
pos和GTID都是日志文件里事件的一个标志,如果将整个mysql集群看作一个整体,pos就是局部的,GTID就是全局的.
配置过程:
1.主从库都编辑配置文件,重启mysqld服务
server1
[root@server1 mysql]# vim /etc/my.cnf
[root@server1 mysql]# systemctl restart mysqld
32 gtid_mode=ON
33 enforce-gtid-consistency=true
[root@server2 mysql]# vim /etc/my.cnf
[root@server2 mysql]# systemctl restart mysqld
2.server2登陆数据库
[root@server2 mysql]# mysql -p ##查看从库的状态
mysql> SHOW SLAVE STATUS\G ##切换到mysql数据库
mysql> USE mysql; ##查看表,有一个gtid_executed表
mysql> SHOW TABLES; ##查看标准表中的所有数据
mysql> SELECT * FROM gtid_executed;
3.回到server1上,登陆数据库
[root@server1 mysql]# mysql -p
mysql> USE test ##切换到test库
mysql> INSERT INTO redhat VALUES ('user2','123'); ##向redhat表中插入数据
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO redhat VALUES ('user3','123');
Query OK, 1 row affected (0.00 sec)
mysql> select * from redhat; ##查看数据
mysql> quit
Bye
4.在server2从库上查看新写入的数据是否同步
mysql> SHOW SLAVE STATUS\G ##查看从库状态
mysql> SELECT * FROM gtid_executed; ##查看gtid_executed表中的数据,可以看到在主库中做的操作被记录
mysql> STOP SLAVE; ##停止从库
mysql> CHANGE MASTER TO MASTER_HOST='172.25.19.1',MASTER_USER='repl',
MASTER_PASSWORD='Yjy+123+mm',MASTER_AUTO_POSITION=1;
##改变主库的信息,从1开始记录
mysql> START SLAVE; ##开启从库
mysql> SHOW SLAVE STATUS\G ##查看状态,数据一致,从1开始记录
mysql> quit
Bye
[root@server2 mysql]# mysql -p
mysql> select * from westos.usertd;
1.主从库都安装插件
(1)master(主库)
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
##可以查看到插件已经安装
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
mysql> SET GLOBAL rpl_semi_sync_master_enabled=1; ##激活插件
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; ##安装插件
Query OK, 0 rows affected (0.01 sec)
mysql> SET GLOBAL rpl_semi_sync_slave_enabled=1; ##激活插件
Query OK, 0 rows affected (0.00 sec)
2.从库重启io进程,激活插件之后必须要重启io进程,否则不会生效,如果重启不了的话就说明两端的数据不同步
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.00 sec)
mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)
3.查看从库的状态
mysql> SHOW SLAVE STATUS\G
mysql> SHOW STATUS LIKE '%rpl%'; ##查看变量状态
mysql> SHOW VARIABLES LIKE '%rpl%'; ##查看变量的值
4.查看主库的变量的值,可以查看到延迟时间(10000指10000毫秒,也就是10秒)
mysql> SHOW VARIABLES LIKE '%rpl%';
测试:
1.serve2先关闭io进程
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.00 sec)
2.server1写入数据
(1)进入test库
mysql> USE test;
(2)插入数据到redhat表
mysql> INSERT INTO redhat VALUES ('user4','123');
Quy OK, 1 row affected (10.01 sec)
有10秒的延迟,这是因为从库的io进程关闭了,不能及时的写入数据;主库等待10秒之后从库还没有起来,主库不再等待直接写入
(3)再次插入数据,主库直接写入,没有延迟
mysql> INSERT INTO redhat VALUES ('user5','123');
Query OK, 1 row affected (0.00 sec)
这是因为:
半同步复制再一次失败后会自动切换成异步复制
从库进程起来之后会将没有做的事情再做一遍
(4)查看主库的变量,半同步复制关闭
mysql> SHOW STATUS LIKE '%rpl%';
(5)主库查看当前数据
mysql> SELECT * FROM test.redhat;
(6)从库查看当前数据,没有刚刚主库写入的数据——数据未同步
mysql> SELECT * FROM test.redhat;
(7)从库开启io进程
mysql> start slave io_thread;
(8)再次查看数据,数据已同步
也就是说只要从库的io进程恢复工作就会立即同步没有同步的数据
mysql> SELECT * FROM test.redhat;
总结:半同步复制失败后会自动切换成异步复制,从库进程起来之后会检测主从库数据是否同步;若不同步,将会采用异步复制的方式同步数据
主库添加数据
mysql> INSERT INTO redhat VALUES ('user6','123');
Query OK, 1 row affected (0.00 sec)
mysql> SHOW STATUS LIKE '%rpl%';
##Rpl_semi_sync_master_yes_tx变成1,成功了1次
主库查看
mysql> SELECT * FROM test.redhat;
从库查看
mysql> SELECT * FROM test.redhat;