一、概念讲解
1.数据库是按照数据结构来组织、存储和管理数据的仓库。每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据。我们也可以将数据存储在文件中,但是在文件中读写数据速度相对较慢。
2.mysql主从复制的原理:mysql要做到主从复制,其实依靠的是二进制日志,即:假设主服务器叫A,从服务器叫B;主从复制就是B跟着A学,A做什么,B就做什么。那么B怎么同步A的动作呢?现在A有一个日志功能,把自己所做的增删改查的动作。全都记录在日志中,B只需要拿到这份日志,照着日志上面的动作施加到自己身上就可以了。这样就实现了主从复制。
3.GDIT介绍:MySQL-5.6.2开始支持,MySQL-5.6.10后完善,GTID 分成两部分,一部分是服务的UUid,UUID保存在mysql数据目录的auto.cnf文件中,这是一个非常重要的文件,不能删除,这一部分是不会变的。另外一部分就是事务ID了,随着事务的增加,值一次递增,如下图
4.GTID的工作原理:
1、master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。
2、slave端的i/o 线程将变更的binlog,写入到本地的relay log中。
3、sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。
4、如果有记录,说明该GTID的事务已经执行,slave会忽略。
5、如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。
6、在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。
5. GTID的优点:
1.一个事务对应一个唯一ID,一个GTID在一个服务器上只会执行一次
2.GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置
3.减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机
6.主从同步复制有以下几种方式:
(1)同步复制,master的变化,必须等待slave-1,slave-2,…,slave-n完成后才能返回。
(2)异步复制,master只需要完成自己的数据库操作即可,至于slaves是否收到二进制日志,是否完成操作,不用关心。MYSQL的默认设置。
(3)半同步复制,master只保证slaves中的一个操作成功,就返回,其他slave不管。这个功能,是由google为MYSQL引入的。
二、mysql的主从复制
(一)配置主数据库:
1.在主库中将mysql的安装包进行解压
[root@server1 ~]# ls
[root@server1 ~]# tar xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
[root@server1 ~]# ls
2.将没有用的包删除
[root@server1 ~]# rm -rf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar mysql-community-devel-5.7.24-1.el7.x86_64.rpm mysql-community-embedded-5.7.24-1.el7.x86_64.rpm mysql-community-embedded-compat-5.7.24-1.el7.x86_64.rpm mysql-community-embedded-devel-5.7.24-1.el7.x86_64.rpm mysql-community-minimal-debuginfo-5.7.24-1.el7.x86_64.rpm mysql-community-server-minimal-5.7.24-1.el7.x86_64.rpm mysql-community-test-5.7.24-1.el7.x86_64.rpm
[root@server1 ~]# ls
3.安装剩下的包
[root@server1 ~]# yum install -y 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
4.将mysql包发送给server2
[root@server1 ~]# scp install -y 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@172.25.66.2:/root
5.打开数据库(此过程有点慢)并查看密码:
[root@server1 ~]# systemctl start mysqld
#查看密码的两种方式
[root@server1 ~]# cat /var/log/mysqld.log | grep password
[root@server1 ~]# grep password /var/log/mysqld.log
6.对数据库进行安全初始化,修改密码(密码必须要由数字,大小写字母,特殊字母组成,四者缺一不可,且必须大于8位)
[root@server1 ~]# mysql_secure_installation
7.编写mysql的配置文件并重启服务
[root@server1 ~]# vim /etc/my.cnf
[root@server1 ~]# systemctl restart mysqld
配置文件中增加的内容如下:
28 log-bin=mysql-bin #打开二进制日志
29 server-id=1 #设置ID不能与别的主机重复
8.创建用户并授权
[root@server1 ~]# mysql -p
mysql> grant replication slave on *.* to bai@'172.25.66.%' identified by 'Bgg+2019';
分析:
replication 表示授权复制的权限
*.*表示所有数据库可以进行同步
bai表示授权名,可以随意填写
'172.25.66.%'表示授权
172.25.66.0/24的网段所有服务器可以同步,%表示任意
9.查看状态:
-
查看二进制日至是否打开(log_bin中是ON表示二进制日至打开)
mysql> show variables like ‘log_%’;
-
查看主库的状态(复制时根据Position号进行复制,从部通过读取主部的二进制日志)
mysql> show master status;
(二)配置从数据库:
1.在server2中安装数据库的包
[root@server2 ~]# ls
[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 -y
2.查看其是否能够登陆成功,如果能登陆成功,说明授权成功
[root@server2 ~]# mysql -u bai -p -h 172.25.66.1
3.开启mysql的服务(可能会比较慢)并查看超级用户的密码
[root@server2 ~]# systemctl start mysqld
[root@server2 ~]# cat /var/log/mysqld.log | grep password
4.和主库一样进行安全初始化(密码最好设成一样的,以免记错)
[root@server2 ~]# mysql_secure_installation
5.编辑配置文件并重新开启mysqld服务
[root@server2 ~]# vim /etc/my.cnf
[root@server2 ~]# systemctl restart mysqld
文件中增加的内容如下:
28 server-id=2 #此server-id要和主库中的不一样
6.在server2设定从设备并开启从设备(可以通过在server1中查看主设备中的状态的值设定,输入以下命令即可查看show master status;)
[root@server2 ~]# mysql -p
mysql> change master to master_host='172.25.66.1',master_user='bai',master_password='Bgg+2019',master_log_file='mysql-bin.000002',master_log_pos=446;
mysql> START SLAVE;
mysql> SHOW slave status\G;
注意:master_log_file和master_log_pos的值要依照主设备状态的值来设定,因为会变化
(三)测试
1.在主数据库中创建库,创建表,并插入数据
[root@server1 ~]# mysql -p
mysql> CREATE DATABASE westos;
mysql> SHOW DATABASES;
mysql> USE westos;
mysql> SHOW TABLES;
mysql> CREATE table userlist(
-> username varchar(10) not null,
-> password varchar(15) not null);
mysql> insert into userlist values ('user1','123');
mysql> select * from userlist;
注意:
可以查看到主库的状态信息中的positioin一直在变化
mysql> show master status;
2.在从数据库中查看是否将主库中的信息成功同步复制
[root@server2 ~]# mysql -p
mysql> SHOW DATABASES;
mysql> USE westos;
mysql> select * from userlist;
三.基于GDIT主从复制
(一)配置GDIT主从复制
1.在server1中更改mysql的配置文件并重新启动mysqld服务
[root@server1 ~]# vim /etc/my.cnf
[root@server1 ~]# systemctl restart mysqld
配置文件的内容如下:
30 gtid_mode=ON #开启gtid模式
31 enforce-gtid-consistency=true #强制gtid一直性,用于保证启动gtid后事务的安全
2.在server1中更改mysql的配置文件并重新启动mysqld服务
[root@server2 ~]# vim /etc/my.cnf
[root@server2 ~]# systemctl restart mysqld
配置文件的内容如下:
29 gtid_mode=ON #开启gtid模式
30 enforce-gtid-consistency=true #强制gtid一直性,用于保证启动gtid后事务的安全
3.在从库中先停掉slave,然后重新创建连接(slave连接master时将使用基于GTID的复制协议,所以将MASTER_AUTO_POSITION=1)
[root@server2 ~]# mysql -p
mysql> STOP slave;
mysql> change master to master_host='172.25.66.1',master_user='bai',master_password='Bgg+2019',MASTER_AUTO_POSITION=1;
mysql> start slave;
#开启后查看Slave_IO_Running和Slave_SQL_Running是否开启
mysql> show slave status\G;
(二)测试
1.在主库的userlist表中添加新的信息
[root@server1 ~]# mysql -p
mysql> USE westos;
mysql> INSERT INTO userlist values ('user2','222');
mysql> select * from userlist;
2.在从库中查看是否将主库中的信息复制成功,会发现已经成功复制
[root@server2 ~]# mysql -p
mysql> USE westos;
mysql> select * from userlist;
四.基于GDIT的半同步复制
Mysql默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返回给客户端,并不关心从库是否已经接受并处理,这样就会有一个问题,如果主库crash掉了,此时主库已经提交的事务可能并没有传到从库上,此时,强行将从库升为主库,可能会导致新主库上的数据不完整。半同步复制就是为了解决数据丢失的问题
(一)配置半同步
1.在主数据库中安装服务插件并开启半同步复制
[root@server1 ~]# mysql -p
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> set global rpl_semi_sync_master_enabled=ON;
mysql> select plugin_name,plugin_status
-> from information_schema.plugins
-> where plugin_name like '%semi%';
2.在主库中查看是否开启半同步复制
mysql> show variables like '%rpl%'; #环境变量
mysql> show variables like '%semi%';
mysql> show status like '%rpl_semi_sync%'; #状态变量
分析:
(1)表示默认是10000毫秒(10s),生产环境中建议无穷大
(2)查看时主要查看其Rpl_semi_sync_master_status是否开启
3.在从库中也安装插件,开启半同步复制,并查看其是否开启
[root@server2 ~]# mysql -p
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
mysql> set global rpl_semi_sync_master_enabled=ON;
mysql> show variables like '%semi%';
注意:
一定要重启从库上的IO线程,如果不重启,则默认还是异步复制,重启后,slave会在master上注册为半同步复制的slave角色
mysql> stop slave io_thread;
mysql> start slave io_thread;
4.在从库中查看是否开启半同步复制
mysql> show status like '%rpl%';
mysql> show variables like '%rpl%';
(二)测试一(半同步失败情况)
没有通过半同步复制
1.从库关掉IO线程
mysql> stop slave io_thread;
2.在主库表中插入数据,会等待10s,10s后会变为异步复制
mysql> use westos;
mysql> insert into userlist values('user5','888');
3.此时在主库中发现半同步失败次数+1
mysql> show status like '%rpl%';
分析:
(1)Rpl_semi_sync_master_no_tx表示没有成功接收slave提交的次数,也就是使用半同步失败的次数,10s后没有得到反馈信息,会转为异步复制
(2)Rpl_semi_sync_master_no_tx表示使用半同步成功的个数,数据的一致性能提高
4.查看从库中的内容是否更新,发现没有更新
mysql> use westos;
mysql> select * from userlist;
5.打开IO线程,此时数据才会同步过来,此时复制过来的是异步复制的结果mysql> start slave io_thread;
6.查看从库中的内容是否更新,发现成功更新(如果先开始没有更新,稍等一下,便可以成功更新)
mysql> select * from userlist;
(三)测试二(半同步正常情况)
1.将从库的IO打开
mysql> start slave io_thread;
2.在主库中插入新数据
mysql> INSERT INTO userlist values ('user3','333');
3.在从库中查看信息是否同步,发现成功同步,说明半同步正常
mysql> select * from userlist;
4.可以使用以下命令查看到进程信息
mysql> show processlist;
注意:
1.我这里Rpl_semi_sync_master_yes_tx并没有增1,你们增加了吗?
2.rpl_semi_sync_master_timeout=10000表示延迟10000毫秒该参数为10000毫秒,即10秒,不过,这个参数是动态动态可调,表示如果主库在某次十五中的等待时间超过10秒,则降级为异步复制模式,不在等待slave从库,如果主库再次探测slave从库恢复,则会自动回到半同步复制模式