server1:172.25.15.1 master(主库)
server2:172.25.15.2 slave (从库)
1. 主从同步的定义
主从同步使得数据可以从一个数据库服务器复制到其他服务器上,在复制数据时,一个服务器充当主服务器(master),其余的服务器充当从服务器 (slave)。因为复制是异步进行的,所以从服务器不需要一直连接着主服务器,从服务器甚至可以通过拨号断断续续地连接主服务器。通过配置文件,可以指 定复制所有的数据库,某个数据库,甚至是某个数据库上的某个表。
使用主从同步的好处:
图解主从复制
1.数据库有个bin-log二进制文件,记录了所有sql语句。
2.我们的目标就是把主数据库的bin-log文件的sql语句复制过来。
3.让其在从数据库的relay-log重做日志文件中再执行一次这些sql语句即可。
4.具体需要三个线程来操作:
(1).主库dump线程:每当有从库连接到主库的时候,主库都会创建一个dump线程然后发送binlog(二进制日志)内容到从库。在从库里,当复制开始的时候,从库就会创建两个线程进行处理:
(2).从库IO线程:当START SLAVE语句在从库开始执行之后,从库创建一个IO线程,该线程连接到主库并请求主库发送binlog里面的更新记录到从库上。从库IO线程读取主库的binlog输出线程发送的更新并拷贝这些更新到 relay log 文件。
(3).从库的SQL线程:从库创建一个SQL线程,这个线程读取从库IO线程写到 relay log 的更新事件并执行。从而实现主从的操作一致,最终数据一致;
Mysql服务器之间的主从同步是基于二进制日志机制,主服务器使用二进制日志来记录数据库的变动情况,从服务器通过读取和执行该日志文件来保持和主服务器的数据一致。
在使用二进制日志时,主服务器的所有操作都会被记录下来,然后从服务器会接收到该日志的一个副本。从服务器可以指定执行该日志中的哪一类事件(譬如只插入数据或者只更新数据),默认会执行日志中的所有语句。
每一个从服务器会记录关于二进制日志的信息:文件名和已经处理过的语句,这样意味着不同的从服务器可以分别执行同一个二进制日志的不同部分,并且从服务器可以随时连接或者中断和服务器的连接。
主服务器和每一个从服务器都必须配置一个唯一的ID号(在my.cnf文件的[mysqld]模块下有一个server-id配置项),另外,每一 个从服务器还需要通过CHANGE MASTER TO语句来配置它要连接的主服务器的ip地址,日志文件名称和该日志里面的位置(这些信息存储在主服务器的数据库里)
主从复制用途
1、做数据的热备;作为后备数据库,主数据库服务器故障后,可切换到从数据库继续工作,避免数据丢失。(实时灾备,用于故障切换)
2、架构的扩;业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。
3、读写分离,使数据库能支撑更大的并发;在报表中尤其重要。由于部分报表sql语句非常的慢,导致锁表,影响前台服务。如果前台使用master,报表使用slave,那么报表sql将不会造成前台锁,保证了前台速度
主从复制存在的问题
1.主库宕机后,数据可能丢失
2.从库只有一个sql Thread线程,主库写压力大,复制很可能延时
主从复制存在的问题
1.主库宕机后,数据可能丢失
2.从库只有一个sql Thread线程,主库写压力大,复制很可能延时
解决方法
半同步复制---解决数据丢失的问题
并行复制-----解决从库复制延迟的问题
3. 配置主从同步的基本步骤
1.配置主结点
(1)下载并安装数据库
#1.在官网上下载mysql
[root@sever1 ~]# ls
mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
#2.解压
[root@sever1 ~]# tar xf mysql-5.7.24-1.el7.x86_64.rpm-bundle.tar
[root@sever1 ~]# ls
安装
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
(2).开启二进制日志并指定id
vim /etc/my.cnf
log-bin=mysql-bin #开启二进制日志
server-id=1 #指定id
(3).开启数据库
#1.开启数据库
systemctl start mysqld
#2.查看端口
netstat -anltp
(4)查看数据库初始密码
[root@sever1 ~]# cat /var/log/mysqld.log | grep password
(5)登陆数据库
发现虽然可以登陆,但实际上无法使用数据库,根据提示需要先更改数据库密码,才能使用数据库
#登陆数据库
[root@sever1 ~]# mysql -uroot -p'+初始密码'
(6)安全初始化
[root@sever1 ~]# mysql_secure_installation
(7)登陆数据库并创建用户授权
[root@sever1 ~]# mysql -uroot -phym19970818HYM#
mysql> show databases; #查看年数据库
mysql> grant replication slave on *.* to repl@'172.25.66.%' identified by 'hym19970818HYM#'; #创建用户并授权
注释:
replication #表示授权复制的权限
*.* #表示所有数据库可以进行同步
repl #表示授权用户,可以随意填写
'172.25.66.%' #表示授权172.25.66/24的网段所有服务器可以同步, %表示任意
hym19970818HYM# #表示用户密码(我这里设定成root用户的密码是为了方便记忆)
#mysql-bin.000002表示当前正在使用的二进制日志文件,1003表示执行当前二进制日志位置,即从那里开始复制
mysql> show master status; #查看master的状态
mysql> exit #退出
Bye
查看日志:
[root@sever1 ~]# cd /var/lib/mysql
[root@sever1 mysql]# ls
auto.cnf ibdata1 mysql-bin.000002 public_key.pem
ca-key.pem ib_logfile0 mysql-bin.index server-cert.pem
ca.pem ib_logfile1 mysql.sock server-key.pem
client-cert.pem ibtmp1 mysql.sock.lock sys
client-key.pem mysql performance_schema
ib_buffer_pool mysql-bin.000001 private_key.pem
[root@sever1 mysql]# cat mysql-bin.index
./mysql-bin.000001
./mysql-bin.000002
[root@sever1 mysql]# file mysql-bin.index
mysql-bin.index: ASCII text
#查看日志
[root@sever1 mysql]# mysqlbinlog ./mysql-bin.000002
2.配置从结点
(1).下载并安装数据库
[root@sever1 ~]# 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 [email protected]:
[root@sever2 ~]# ls
[root@sever2 ~]# yum install -y *
(2).指定id
server-id=2 #指定id
(3)开启数据库
[root@sever2 ~]# systemctl start mysqld
[root@sever2 ~]# netstat -antlp
注意:如果开启数据库时,特别缓慢怎么办呢?
[root@server2 ~]# systemctl start mysqld
^C
[root@server2 ~]# ps aux | grep mysql
mysql 2717 1.1 23.2 1119484 176448 ? Sl 09:21 0:00 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid
root 2747 0.0 0.1 112648 960 pts/0 R+ 09:22 0:00 grep --color=auto mysql
#1.杀死进程
[root@server2 ~]# kill -9 2717
[root@server2 ~]# ps aux | grep mysql
mysql 2769 10.0 22.7 988412 172548 ? Sl 09:22 0:00 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid
root 2799 0.0 0.1 112648 960 pts/0 R+ 09:22 0:00 grep --color=auto mysql
#2.重新启动
[root@server2 ~]# systemctl start mysqld
(4)查看数据库初始密码
[root@sever2 ~]# cat /var/log/mysqld.log | grep password
(5)初始化
#将密码设定成与主库root用户密码一样是为了方便记忆,并不是必须
[root@sever2 ~]# mysql_secure_installation
(6)登陆数据库
[root@sever2 ~]# mysql -uroot -p密码
测试远程登陆:
#发现可以远程登陆,说明主节点用户授权成功;-h表示主机的ip地址
[root@sever2 ~]# mysql -h 172.25.66.1 -u repl -p
(7).复制
[root@sever2 ~]# mysql -uroot -phym19970818HYM#
mysql> change master to master_host='172.25.66.1',master_user='repl',master_password='hym19970818HYM#',master_log_file='mysql-bin.000002',master_log_pos=1003; #复制主库
注意:如果次参数设定错误,想要重新复制,必须先执行:stop slave 再重新执行即可
注释:
master_host: 复制主机
master_user: 复制用户
master_password: 用户密码
master_log_file: 二进制日志名称
master_log_pos: 日志号
mysql> start slave; #开启slave
mysql> show slave status\G; #查看slave的状态
测试:
注意:主从复制只是实现了数据的单向同步,即只能从库同步主库的数据
在server1上:创建数据库test
[root@sever1 mysql]# mysql -uroot -phym19970818HYM#
mysql> create database test; #创建数据库
mysql> show databases; #查看数据库
在server2上:发现刚在server1上的创建的test数据库同步到了从结点上,即实现了主从复制
mysql> show databases; #查看数据库
在server1上:创建表并插入数据
mysql> use test; #使用数据库
mysql> create table userlist ( #创建表
-> username varchar(20) not null,
-> password varchar(15) not null);
mysql> insert into userlist values ('user1','111'); #插入数据
mysql> insert into userlist values ('user2','222');
mysql> show tables; #查看表
mysql> select * from userlist; #查看表数据
在server2上:查看到刚在server1上的插入的表数据,进一步验证实现了主从复制
mysql> use test; #使用数据库
mysql> show tables; #查看表
mysql> select * from userlist; #查看表数据
排错:
问题1:IO_Running NO
1.用户授权错误
2.防火墙未关闭
3.二进制日志未开启
问题2:SQL_Running NO
一般是回放数据不一致造成的
概述:
1.简述GTID
GTID分成两部分,一部分是服务的UUID, UUID保存在mysql数据目录的auto.cnf文件中,这是一个非常重要的文件,不能删除,这一部分是不会变的。
另外一部分就是事务ID了,随着事务的增加,值一次递增。在整个复制架构中GTID 是不变化的,即使在多个连环主从中也不会变。
2.工作原理
图解:
原理:
1.master更新数据时,会在事务前产生GTID,一同记录到binlog(二进制日志)中。
2.每当有slave连接到master的时候,master都会创建一个dump线程然后发送binlog(二进制日志)内容到slave。
3.slave端的IO线程将变更的binlog,写入到本地的 relay log 中。
4.slave端的SQL线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。
5.如果有记录,说明该GTID的事务已经执行,slave会忽略。
6.如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。
7.在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。
3.特点
1.一个事务对应一个唯一ID,一个GTID在一个服务器上只会执行一次
2.GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置
3.减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机
4.总结
基于GTID的主从复制与传统的主从复制最大的区别在于:传统的是根据pos号来确定从哪开始复制,而GTID的会自动读取gtid_next变量,即告诉Slave,下一个要执行的GTID值
1.配置主库
(1)开启gtid
vim /etc/my.cnf
gtid_mode=ON
enforce-gtid-consistency=true
(2)重启数据库
[root@sever1 ~]# systemctl restart mysqld
(3)登陆数据库
当重启数据库的时候,发现日志名称和日志号会发生变更
[root@sever1 ~]# mysql -uroot -p密码
mysql> show master status;
mysql> exit
[root@sever1 ~]# systemctl restart mysqld
[root@sever1 ~]# mysql -uroot -phym19970818HYM#
mysql> show master status;
mysql> exit
查看GTID:
[root@server1 ~]# mysql -uroot -phym19970818HYM#
mysql> show databases;
mysql> use mysql;
mysql> show tables; #查看到记录GTID的表
mysql> select * from gtid_executed; #查看GTID信息,当前表中没有信息
mysql> exit
查看二进制日志文件:发现mysql-bin文件中记录了所有的sql操作语句
[root@server1 ~]# cd /var/lib/mysql
[root@server1 mysql]# ls
[root@server1 mysql]# mysqlbinlog mysql-bin.000002
查看UUID:
[root@server1 mysql]# cat auto.cnf
2.配置从库
查看master的状态信息:
[root@server2 ~]# cd /var/lib/mysql
[root@server2 mysql]# ls
#信息会发生变更
[root@server2 mysql]# cat master.info
(1).开启gtid
vim /etc/my.cnf
gtid_mode=ON
enforce-gtid-consistency=true
(2)重启数据库
[root@sever2 ~]# systemctl restart mysqld
(3)重新复制主库
[root@sever2 ~]# mysql -uroot -p密码
mysql> show slave status\G;
mysql> stop slave; #关闭slave
Query OK, 0 rows affected (0.08 sec)
mysql> change master to master_host='172.25.66.1',master_user='repl',master_password='hym19970818HYM#',MASTER_AUTO_POSITION = 1; #复制主库
mysql> start slave; #开启slave
注释:
master_host #复制主机
master_user #复制用户
master_password #复制用户密码
MASTER_AUTO_POSITION = 1 : #使用基于GTID协议的复制
mysql> show slave status\G; #查看slave的状态
测试:
在server1上:创建数据库linux
[root@sever1 ~]# mysql -uroot -p密码
mysql> show databases;
mysql> create database linux;
mysql> show databases;
在server2上:发现刚在server1上的创建的linux数据库同步到了从结点上,即实现了基于GDIT的主从复制
mysql> show databases;
在server1上:创建表并插入数据
mysql> use linux;
mysql> create table student(
-> name varchar(20) not null,
-> id varchar(15) not null);
mysql> desc student;
mysql> insert into student values ('tom','07161032');
mysql> insert into student values ('lily','07161025');
mysql> select * from student;
在server2上:查看到刚在server1上的插入的表数据,进一步验证实现了基于GDIT的主从复制
mysql> use linux;
mysql> show tables;
mysql> select * from student;