在生产环境下,如果对数据进行读写操作都是在同一个数据库中进行的。无论是在安全性、高可用性、还是高并发等各个方面都是完全不可能满足实际需求的。因此一般都是通过主从复制(master-slave)的方式来同步数据,保证数据的安全性,再通过读写分离来提升数据库的并发负载能力。
一、什么是mysql replication(mysql主从复制)
1、主从复制指的是当主数据库中进行了update、insert、delete操作导致数据发生改变时,变化会实时同步到一个或者多个从数据库(slave)中。
2、默认情况下时异步复制、无需维持长连接。
3、通过配置可以选择想要同步的库和表。
4、replication时MySQL内建的,自身带有。
二、mysql replication的原理
简单的说就是master将数据的更新操作写入到二进制日志中,slave同步这些二进制日志到中继(relay)日志中,然后读取中继日志中的内容,把二进制的日志解析成SQL语句并执行,从而保持与主数据库中的数据一致。
三、mysql replication的作用
1、读写分离,提供查询服务
2、实时灾备,用于故障切换
3、水平扩展数据库的负载能力
四、mysql replication是如何工作的
1、master将改变记录到二进制日志(binary log)中(这些记录叫做二进制日志事件,binary log events)
2、slave将master的binary log events拷贝到它的中继日志(relay log)
3、slave根据中继日志中的事件,对slave数据库做相应的操作,使其与主数据库一致
一主多从,Master负责写操作,其他slave负责读,这种架构最大问题I/O压力集中,多台slave需要从master上同步数据,影响master的IO性能。
级联复制模式下,部分slave的数据同步不连接主节点,而是连接从节点。因为如果主节点有太多的从节点,就会损耗一部分性能用于replication,那么我们可以让3~5个从节点连接主节点,其它从节点作为二级或者三级与从节点连接,这样不仅可以缓解主节点的压力,并且对数据一致性没有负面影响。
例如,使用一台slave作为中继,分担Master的压力,slave中继需要开启bin-log,并配置log-slave-updates
MySQL中从复制涉及到三个线程,一个运行在主节点(binary dump thread),其余两个(I/O thread ,SQL thread)运行在从节点
一、主节点 binary log dump 线程
当从节点连接到主节点时,主节点会生成一个binlog dump 线程,用于给从节点发送 binary-log中的内容。在从节点读取binary-log中的内容时,此线程会加锁,当读取完成时,在发送给从节点之前,锁会被释放。
二、从节点I/O线程
当从节点上执行了start slave
命令之后,从节点会产生一个I/O线程,用来接受主节点bin log dump线程发送过来的内容,并将内容储存到中继日志中。
三、从节点SQL线程
SQL线程主要时将relay-log中的二进制转化为sql语句并执行,保持从节点与主节点的一致性。
注意:
对于每一个主从连接来说,都需要有三个线程来完成。当主节点又多个从节点进行连接的时候,主节点会分别为从节点创建一个binary log dump 线程,而每个从节点会有属于自己的I/O线程和SQL线程。
主从复制过程
1、主数据库上发生更新事件(update、insert、delete)被写道binlog中
2、从数据库启动后,产生I/O线程,从库发起连接
3、主数据库产生binary log dump 线程将binlog日志发送给从数据库
4、从数据库中 I/O线程接收到binlog内容写入到中继日志(relay log)中
5、从数据空中的SQL线程将relay log中的内容转换为sql语句并执行。
注意
主数据库必须开启binary log(二进制)功能,因为主从同步所有的操作都是基于二进制文件来完成的
MySQL主从复制默认是异步模式进行的。此模式中主数据库的事务提交是不经过slave确认的,master不关心slave是否接收到master发送的binlog。当slave接受到后写入到中继日志中,再转化为sql执行。如果slave并没有接收到主库发送的binlog,主库也并不知情。
如果master宕机,binlog还没有来及被slave接受,而slave备选举为新的主库,这样会导致数据的不一致性。
半同步模式是针对异步模式的缺陷进行的改进。主库必须接受到其中一个从库接受到binlog生成relay log,并给出反应后才完成commit。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XxrDOF4k-1643987258372)(C:\Users\77259\AppData\Roaming\Typora\typora-user-images\1628927111388.png)]
相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,所以,半同步复制最好在低延时的网络中使用。 半同步模式不是mysql内置的,从mysql 5.5开始集成,需要master 和slave 安装插件开启半同步模式。.
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
实验环境:
主机名 | ip | 版本 | 角色 |
---|---|---|---|
mysqlmaster | 192.168.116.20 | centos7 | Master |
mysqlslave1 | 192.168.116.3 | centos7 | slave |
注意!!! 注意!!! : 看清楚是在哪台虚拟机进行的操作
1、安装NTP
[root@mysqlmaster ~]# yum -y install ntp
2、配置NTP
当安装好NTP后,会生成ntp.conf文件 对其进行修改
[root@mysqlmaster ~]# vim /etc/ntp.conf //添加如下两行
server 127.127.1.0
fudge 127.127.1.0 stratum 8
参数说明:
server 127.127.1.0 //local clock,就和本地系统时间同步。127.127.1.0在这里是一个IP地址,不是网段。 fudge 127.127.1.0 stratum 8 设置时区为东八区,在安装系统时,选择的时上海时间
3、重启NTP服务
[root@mysqlmaster ~]# systemctl restart ntpd //重启ntp服务
[root@mysqlmaster ~]# netstat -anpt | grep ntpd //查看ntp服务
[root@mysqlmaster ~]# systemctl enable netpd //设置开机自动启动
4、关闭防火墙
[root@mysqlmaster ~]# systemctl stop firewalld //关闭防火墙
[root@mysqlmaster ~]# systemctl disable firewalld //关闭开机自动启动
5、在从节点上同步时间
[root@mysqlslave1 ~]# yum -y install nptdate //安装npt
[root@mysqlslave1 ~]# /usr/bin/ntpdate 192.168.116.20 //此处的ip为自己的主库ip
1、进去mysql创建测试库以及数据
mysql> create database HA; //创建一个数据库
mysql> use HA; //进入此数据库
mysql> create table T1(id int,name varchar(20)); //创建表
mysql> insert into T1 values(1,'Tom1'); //插入一条数据
2、创建主从复制的授权用户
mysql> grant replication slave on *.* to [email protected] identified by '123'
//当你的从数据库来复制的时候,使用的是slave用户, slave用户的权限是replication slave 作用到所有库下的所有表
注释:192.168.116.3 是自己的从库的ip
3、配置主库的主配置文件my.cnf
[root@mysqlmaster ~]# vim /etc/my.cnf //添加一下内容
[mysqld]
...... //省略部分内容
log-bin=/data/mysql/log/mysql-bin-master #启用二进制日志
server-id=1 #数据库服务器ID标识
binlog-do-db=HA #可以被从服务器复制的库, 即二进制需要同步的数据库名
4、重启mysql
[root@mysqlmaster ~]# /etc/init.d/mysqld restart
5、查看master的状态
mysql> show master status;
File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
---|---|---|---|---|
mysql-bin-master.000019 | 588 | HA |
这里显示的信息每个人是不一样的。
6、查看二进制日志
[root@mysqlmaster ~]# ls /data/mysql/log/
7、导出数据库
[root@mysqlmaster ~]# mysqldump -uroot -p123 HA >HA.sql //到处数据库
[root@mysqlmaster ~]# scp HA.sql [email protected] //将数据发送给从服务器
1、两台数据库的版本要一致
mysql> show variables like '%version%'; //查看mysql版本
2、测试连接到主服务器是否正常
[root@mysqlslave1 ~]# mysql -uslave -p123 -h 192.168.116.20 //使用在主库中授权的用户登录
mysql> show databases; //查看库
这里只会看到一个information_schema的库 因为用户授权的权限只是复制的权限(replication slave)
3、导入数据库,和主库保持一致
[root@mysqlslave1 ~]# mysql -uroot -p123 -e "create database HA;" //创建HA库
[root@mysqlslave1 ~]# mysql -uroot -p123 HA
4、修改从库的my.conf文件
[root@mysqlslave1 ~]# vim /etc/my.cnf
添加如下配置
server-id = 2
relay-log=/data/mysql/log/relay-log-bin //中继日志文件的路径名称
relay-log-index=/data/mysql/log/slave-relay-bin.index //中继日志索引文件的路径名称
注释: server-id :从服务器ID号,不要和主ID相同 ,如果设置多个从服务器,每个从服务器必须有一个唯一的 server-id值,必须与主服务器的以及其它从服务器的不相同。这些ID值能唯一识别复制服务器 群集中的每个服务器实例
5、重启服务
[root@mysqlslave1 ~]# /etc/init.d/mysqld restart
6、在从库中更改其相关配置
[root@mysqlslave1 ~]# mysql -uroot -p123
mysql> stop slave; //停止slave
mysql> change master to master_host='192.168.116.20',
master_user='slave',master_password='123',
master_log_file='mysql-bin-master.000019',master_log_pos=588;
注释:
master_host:主库的ip地址
master_user:在主库中做的具有replication权限的授权用户名
master_password:主库的数据库密码
master_log_file:主库的二进制文件
master_log_pos:主库的二进制文件的其实位置
这里 master_log_file,master_log_pos的值 通过上边的命令show master status; 在主库中查看,一定要与主库的查询结果保持一致。
7、启动slave
mysql> start slave;
1、在slave中查看slave状态
mysql> show slave status;
查看其中的关键信息:
1)Master_Host:主库的ip地址是否正确
2)Master_User:是否使用的是在主库中授权的用户
3)Master_Log_File:是否与在主库中进行show master status显示的信息一致
4)Slave_IO_Running:从库中的I/O线程是否开启
5)Slave_SQL_Running:从库中的SQL线程是否开启
2、在主库中查看是否创建了连接
mysql> show processlist \G;
查看其中关键信息:
1)User:用户是否是授予aplication slave权限的用户
2)Host:是否是从库的ip地址
3)Command:Binlog Dump 是否开启
出现错误一般为一下情况:
1、没有关闭防火墙
解决:
[root@mysqlmaster ~]# systemctl stop firewalld
2、主库在用户授权时,从库的ip写错
解决:
进入主库mysql 进行查看
mysql> select user,host from mysql.user;
查看授权用户对用的ip是否为从库
3、在从库中进行更改配置时出错
解决:
进入从库 重新更改配置
mysql> change master to master_host='192.168.116.20',
master_user='slave',master_password='123',
master_log_file='mysql-bin-master.000019',master_log_pos=588;
master_log_file master_log_pos 这两个值 进入主库进行查看保持与主库一致
mysql> show master status;
注意!!! 这里的master_log_file、master_log_po 的值一定要与主库对应
实验环境
主机 | IP | 系统版本 | 角色 |
---|---|---|---|
mysqlmaster | 192.168.116.20 | CentOS 7 | Master |
mysqlslave1 | 192.168.116.3 | CentOS 7 | Slave 中继 |
mysqlslave2 | 192.168.116.2 | CentOS 7 | Slave |
同以上操作,在三台虚拟机上都进行
1、在主服务器上授权用户
[root@mysqlmaster ~]# mysql -uroot -p123 //进入数据库
mysql> grant replication slave on *.* to slave@'192.168.116.%' identified by '123' //授权用户
mysql> flush privileges; //刷新授权用户
2、创建数据库
mysql> create database HA;
mysql> use HA;
mysql> create table T1(id int,name varchar(20));
mysql> insert into T1 values(1,'tom1');
3、修改主库配置文件
[root@mysqlmaster ~]# vim /etc/my.cnf
添加以下内容
[mysqld]
………省略部分内容
server-id=1
binlog-do-db=HA
log-bin=/data/mysql/log/mysql-bin-master
sync-binlog=1
binlog-format=row
参数说明
server-id:指定主库实例,每台Mysql服务器中的id不能相同
binlog-do-db:指定要实现复制的库
log-bin:二进制文件的文件位置
sync-binlog:每写缓冲多少次就同步到磁盘
sync_binlog=1:表示同步写缓冲和磁盘二进制日志文件,不使用文件系统缓存,在使用innodb事务引擎时,在复
制环境中,为了保证最大的可用性,都设置为“1”,但会对影响io的性能。
binlog-format:格式化二进制文件日志
4、重启服务、查看状态
[root@mysqlmaster ~]# /etc/init.d/mysqld restart
//进入数据库后
mysql> show master status;//显示主服务器的当前binlog文件及事件位置
5、导出主服务器HA库完整备份, 拷贝到 中继服务器 和slave服务器
[root@mysqlmaster ~]# mysqldump -uroot -p123 -B HA>ha.sql
[root@mysqlmaster ~]# scp ha.sql [email protected]:~
[root@mysqlmaster ~]# scp ha.sql [email protected]:~
1、导入数据库
[root@mysqlslave1 ~]# mysql -uroot -p123
2、配置从库的配置文件
[root@mysqlslave1 ~]# vim /etc/my.cnf
添加以下内容
………… //省略部分内容
server-id=2
log-slave-updates=1
log-bin=/data/mysql/log/mysql-bin-slave1
relay-log=/data/mysql/log/relay-log-bin
relay-log-index=/data/mysql/log/slave-relay-bin.index
参数说明
server-id:指定主库实例,每台Mysql服务器中的id不能相同
log-slave-updates:在上面讲到的中从复制过程中,从库会通过I/O线程将读取主库的二进制文件并写到自己的中 继日志中,在这里的Slave不仅需要接收,它还需要往下传递二进制文件。所以添加这个参数 后,中继从库在把接收到的二进制文件写入到从库时,同时也会写到自己的二进制文件中。 在级联复制中,这个参数是必要的。
log-bin:指定二进制文件位置
relay-log:指定中继文件位置
relay-log-index:指定中继文件索引位置
3、重启mysql
[root@mysqlslave1 ~]# /etc/init.d/mysqld restart
4、进行从库的授权
[root@mysqlslave1 ~]# mysql -uroot -p123
mysql> stop slave;
msyql> change master to master_host='192.168.116.20',master_user='slave',
master_password='123',master_log_file='mysql-bin-master.000001',
master_log_pos=154;
mysql> start slave;
上边的实验已经介绍过这些参数的值,这里不再过多讲解。
5、查看中继服务的状态
mysql> show slave status \G
//通过上面的方法进行检查其中的参数 I/O、SQL 两个线程的状态
6、授权用户(给mysqlslave2使用)
mysql> grant replication slave on *.* to 'slave'@'192.168.116.%' identified by '123'
mysql> flush privileges;
mysql> show master status; //查看slave中继服务器的当前的binlog文件即事件位置
1、导入数据库
[root@mysqlslave2 ~]# mysql -uroot -p123
2、修改配置文件
[root@mysqlslave2 ~]# vim /etc/my.cnf
//添加以下内容
[mysqld]
………省略部分内容
server-id = 3
relay-log=/data/mysql/log/relay-log-bin
relay-log-index=/data/mysql/log/slave-relay-bin.index
3、重启mysql
[root@mysqlslave2 ~]# /etc/init.d/mysqld restart
4、授权
[root@mysqlslave2 ~]# mysql -uroot -p123 //进入数据库
mysql> stop slave;
mysql> change master to master_host='192.168.116.3',master_user='slave',
master_password=123,master_log_file='mysql-bin-slave1.000001',
master_log_pos='448';
mysql> start slave;
5、查看状态
mysql> show slave status\G
根据上述的主从实验进行状态判断,判断状态都正常的情况下,即完成了级联复制的部署
………省略部分内容
server-id = 3
relay-log=/data/mysql/log/relay-log-bin
relay-log-index=/data/mysql/log/slave-relay-bin.index
3、重启mysql
```bash
[root@mysqlslave2 ~]# /etc/init.d/mysqld restart
4、授权
[root@mysqlslave2 ~]# mysql -uroot -p123 //进入数据库
mysql> stop slave;
mysql> change master to master_host='192.168.116.3',master_user='slave',
master_password=123,master_log_file='mysql-bin-slave1.000001',
master_log_pos='448';
mysql> start slave;
5、查看状态
mysql> show slave status\G
根据上述的主从实验进行状态判断,判断状态都正常的情况下,即完成了级联复制的部署