实验环境:
主库:server1: 172.25.19.1
从库: server2:172.25.19.2
主从复制的要求:
(1)主库开启binlog日志(设置log-bin参数)
(2)主从server-id不同
(3)从库服务器能连同主库
[ ] 主从复制的原理:
mysql的主从配置又叫replication,AB复制,基于binlog二进制日志,主数据库必须开启binlog二进制日志才能进行复制。
(1) master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events);
(2)从库生成两个线程,一个i/o线程,一个SQL线程,i/o线程去请求主库的binlog,
(3) slave将master的binary log events拷贝到它的中继日志(relay log);
(4)slave重做中继日志中的事件,将更改应用到自己的数据上。
一、MYSQL的主从复制
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
[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
29 log-bin=mysql-bin
30 server-id=1
6.开启服务之后生成了一个临时密码,过滤临时密码进行安全初始化
[root@server1 ~]# grep password /var/log/mysqld.log
[root@server1 ~]# mysql_secure_installation
安全初始化登陆的时候使用的是临时密码,接下来要自己设置数据库的密码,这个密码必须有特殊字符,英文字母的大小写还有数字
7.登陆数据库
参数解释:
REPLICATION | 表示复制的权限 |
---|---|
*.* | 表示对所有哭的所有表都授权 |
repl | 用户名 |
‘172.25.19.%’ | 授权172.25.19网段的所有都可以同步 |
[root@server1 ~]# mysql -p
mysql> SHOW DATABASES;
## 创建用户并授权
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'172.25.19.%' IDENTIFIED BY 'Yjy+123+mm';
##查看主库的状态
mysql> SHOW MASTER STATUS;
##退出
mysql> QUIT
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
[root@server2 ~]# mysql -p
##查看所有的表
mysql> SHOW DATABASES;
##配置主库的信息
mysql> CHANGE MASTER TO MASTER_HOST='172.25.19.1', ##主库的ip地址
MASTER_USER='repl', ##主库的用户
MASTER_PASSWORD='Yjy+123+mm', ##主库用户的密码
MASTER_LOG_FILE='mysql-bin.000002', ##主库的日志文件
MASTER_LOG_POS=1247; ##主库的状态码
mysql>
mysql> START SLAVE; ##开启从库
查看从库状态
mysql> SHOW SLAVE STATUS\G
##可以看到的当前两个进程都是yes,表示主库和从库的数据一致
注意:配置完之后所有的写的操作都要在主库上进行,因为在主库上写从库可以通过日志文件来读取并重演,但是在从库上写主库不会同步,导致主从库数据不一致,这好似查看从库的状态信息就会看到有NO
10.server1写
查看那数据目录下的文件,有刚刚显示的日志文件
[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# ls
[root@server1 mysql]# mysql -p
创建数据库westos
mysql> CREATE DATABASE westos;
进入到数据库westos
mysql> USE westos;
查看表
mysql> SHOW TABLES;
创建表usertd
mysql>
mysql> CREATE TABLE usertd (
-> username varchar(10) not null,
-> password varchar(15) not null);
查看表的结构
mysql> DESC usertd;
向表中插入信息
mysql> INSERT INTO usertd VALUES ('user1','123');
查看表的所有信息
mysql> SELECT * FROM usertd;
查看所有数据库,可以看到现在有一个westos数据库
mysql> SHOW DATABASES;
进入到westos数据库的环境
mysql> USE westos;
查看usertd表的所有信息
mysql> SELECT * FROM usertd;
退出
mysql> quit
[root@server2 ~]# cd /var/lib/mysql
[root@server2 mysql]# ls
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在一组复制中,全局唯一。通过GTID保证每个主库上提交的事务在集群中有一个唯一的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
[root@server2 mysql]# mysql -p
查看从库的状态
mysql> SHOW SLAVE STATUS\G
切换到mysql数据库
mysql> USE mysql
查看表,有一个gtid_executed表
mysql> SHOW TABLES;
查看标准表中的所有数据
mysql> SELECT * FROM gtid_executed;
[root@server1 mysql]# mysql -p
切换到westos库
mysql> USE westos
向usertd表中插入数据
mysql> INSERT INTO usertd VALUES ('user2','123');
Query OK, 1 row affected (0.01 sec)
mysql> INSERT INTO usertd VALUES ('user3','123');
Query OK, 1 row affected (0.00 sec)
查看数据
mysql> select * from usertd;
mysql> quit
Bye
SERVER2
查看从库状态
mysql> SHOW SLAVE STATUS\G
查看gtid_executed表中的数据
mysql> SELECT * FROM gtid_executed;
可以看到在主库中做的操作被记录
停止从库
mysql> STOP SLAVE;
改变主库的信息,从1开始记录
mysql> CHANGE MASTER TO MASTER_HOST='172.25.19.1',MASTER_USER='repl',
MASTER_PASSWORD='Yjy+123+mm',MASTER_AUTO_POSITION=1;
开启从库
mysql> START SLAVE
-> ;
查看状态,数据一致,从1开始记录
mysql> SHOW SLAVE STATUS\G
mysql> quit
Bye
[root@server2 mysql]# mysql -p
mysql> select * from westos.usertd;
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
半同步复制就是为了解决数据丢失的问题。
配置过程:
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>
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)
mysql> SHOW SLAVE STATUS\G
查看变量状态
mysql> SHOW STATUS LIKE '%rpl%';
查看变量的值
mysql> SHOW VARIABLES LIKE '%rpl%';
SERVER1
mysql> SHOW VARIABLES LIKE '%rpl%';
mysql> stop slave io_thread;
Query OK, 0 rows affected (0.00 sec)
(1)进入westos数据库
mysql> USE westos
(2)插入数据到usertd表
mysql> INSERT INTO usertd VALUES ('user4','123');
Quy OK, 1 row affected (10.01 sec)
有10秒的延迟,这是因为从库的io进程关闭了,不能及时的写入数据
主库等待10秒之后从库还没有起来,主库不再等待直接写入
(3)再次插入数据,主库直接写入,没有延迟
这是因为:
半同步复制再一次失败后会自动切换成异步复制
从库进程起来之后会将没有做的事情再做一遍
mysql> INSERT INTO usertd VALUES ('user5','123');
Query OK, 1 row affected (0.00 sec)
mysql> SHOW VARIABLES LIKE '%rpl%';
mysql> SELECT * FROM westos.usertd;
mysql> SELECT * FROM westos.usertd;
mysql> start slave io_thread;
(8)再次查看数据,数据已同步
也就是说只要从库的io进程恢复工作就会立即同步没有同步的数据
mysql> SELECT * FROM westos.usertd;
总结:半同步复制再一次失败后会自动切换成异步复制
从库进程起来之后会将没有做的事情再做一遍
再次验证:
主库添加数据
mysql> INSERT INTO usertd 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 westos.usertd;
从库查看
mysql> SELECT * FROM westos.usertd;