一. mysql的主从复制
主从复制原理:
MySQL之间数据复制的基础是二进制日志文件(binary log file)。一台MySQL数据库一旦启用二进制日志后,其作为master,它的数据库中所有操作都会以“事件”的方式记录在二进制日志中,其他数据库 作为slave通过一个I/O线程与主服务器保持通信,并监控master的二进制日志文件的变化,如果发现master二进制日志文件发生变化,则会把 变化复制到自己的中继日志中,然后slave的一个SQL线程会把相关的“事件”执行到自己的数据库中,以此实现从数据库和主数据库的一致性,也就实现了 主从复制 。
环境需求:
Linux 系统版本:Redhat 6.5 版本
系统防火墙关闭:selinux=disabled
server3:172.25.100.3(Master)
server4:172.25.100.4(Slave)
Server3 配置 master:
[root@server3 mysql5.7]# yum install -y
mysql-community-client-5.7.17-1.el6.x86_64.rpm
mysql-community-common-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-compat-5.7.17-1.el6.x86_64.rpm
mysql-community-server-5.7.17-1.el6.x86_64.rpm
[root@server3 mysql5.7]# /etc/init.d/mysqld start #启动
[root@server3 mysql5.7]# grep password /var/log/mysqld.log #查找初始密码
2018-09-27T12:31:29.501825Z 1 [Note] A temporary password is generated for
root@localhost: a.h%:n=/8Atp
2018-09-27T12:31:52.515047Z 0 [Note] Execution of init_file
'/var/lib/mysql/install-validate-password-plugin.xc3FP3.sql' started.
2018-09-27T12:31:52.595877Z 0 [Note] Execution of init_file
'/var/lib/mysql/install-validate-password-plugin.xc3FP3.sql' ended.
2018-09-27T12:31:54.480393Z 0 [Note] Shutting down plugin 'sha256_password'
2018-09-27T12:31:54.480397Z 0 [Note] Shutting down plugin
'mysql_native_password'
2018-09-27T12:31:56.636592Z 3 [Note] Access denied for user
'UNKNOWN_MYSQL_USER'@'localhost' (using password: NO)
[root@server3 mysql5.7]# mysql_secure_installation #更改root登陆密码为'REDHAT.org123‘
[root@server3 mysql5.7]# vim /etc/my.cnf #更改配置文件
[root@server3 mysql5.7]# /etc/init.d/mysqld restart
[root@server3 mysql5.7]# mysql -p
mysql> grant replication slave on *.* to repl@'172.25.100.%' identified by 'REDHAT.org123';
Query OK, 0 rows affected, 1 warning (0.05 sec) ##授权 slave 以 repl 身份从 172.25.100.0/24 网段登陆,对任何数据库的任何表进行操作,密码‘REDHAT.org123‘
Server4 配置 slave:
[root@server3 mysql5.7]# yum install -y
mysql-community-client-5.7.17-1.el6.x86_64.rpm
mysql-community-common-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-5.7.17-1.el6.x86_64.rpm
mysql-community-libs-compat-5.7.17-1.el6.x86_64.rpm
mysql-community-server-5.7.17-1.el6.x86_64.rpm
[root@server4 mysql5.7]# /etc/init.d/mysqld start
[root@server4 mysql5.7]# grep password /var/log/mysqld.log
2018-09-27T13:14:50.056197Z 1 [Note] A temporary password is generated for
root@localhost: 9wImv8:s>eUb
[root@server3 mysql5.7]# mysql_secure_installation #更改root登陆密码为'REDHAT.org123‘
[root@server4 mysql5.7]# vim /etc/my.cnf
[root@server4 mysql5.7]# /etc/init.d/mysqld restart
[root@server4 mysql5.7]# mysql -p
mysql> change master to master_host='172.25.100.3',master_user='repl',master_password='REDHAT.org
123',master_log_file='mysql-bin.000001',master_log_pos=448;
Query OK, 0 rows affected, 2 warnings (0.40 sec) #令server4作为备用并指向master--server3
mysql> start slave;
Query OK, 0 rows affected (0.12 sec)
mysql> SHOW slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.25.100.3
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000001
Read_Master_Log_Pos: 448Relay_Log_File: server4-relay-bin.000002
Relay_Log_Pos: 320
Relay_Master_Log_File: mysql-bin.000001
Slave_IO_Running: Yes
Slave_SQL_Running:Yes #此两处状态为yes说明指向成功
测试:
master3中创建库
Server3-master:创建新数据库
mysql> create database westos;
Query OK, 1 row affected (0.10 sec)
mysql> use westos;
Database changed
mysql> create table linux(
-> username varchar(5) not null,
-> password varchar(10) not null);
Query OK, 0 rows affected (0.53 sec)
mysql> insert into linux values('user1',123);
Query OK, 1 row affected (0.12 sec)
mysql> insert into linux values('user2',456);
Query OK, 1 row affected (0.09 sec)
在 server4-slave 中登陆 mysql,查看自动同步过来的 linux 表中的数据
[root@server4 mysql5.7]# mysql -p
二. 基于GTID的 主从复制:
GTID ( Global transaction identifiers )
一. 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、在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。
GTID复制是怎么实现自动同步,自动对应位置的?
例如:ServerC <-----ServerA ----> ServerB
主机ServerA
备机:ServerB,ServerC
当主机ServerA 挂了之后 ,此时ServerB执行完了所有从ServerA 传过来的事务,
ServerC 延时一点。这个时候需要把 ServerB 提升为主机 ,Server C 继续为备机。
当ServerC 链接ServerC 之后,首先在自己的二进制文件中找到从ServerA 传过来的最新的GTID,
然后将这个GTID 发送到ServerB ,ServerB 获得这个GTID之后,就开始从这个GTID的下一个GTID
开始发送事务给ServerC。这种自我寻找复制位置的模式减少事务丢失的可能性以及故障恢复的时间。
二. GTID的优点:
1.一个事务对应一个唯一ID,一个GTID在一个服务器上只会执行一次
2.GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置
3.减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机
三. GTID的缺点:
1.不支持非事务引擎
2.不支持create table ... select 语句复制(主库直接报错)
原理:( 会生成两个sql,一个是DDL创建表SQL,一个是insert into 插入数据的sql。
由于DDL会导致自动提交,所以这个sql至少需要两个GTID,但是GTID模式下,只能给这个sql生成一个GTID )
3.不允许一个SQL同时更新一个事务引擎表和非事务引擎表
4.在一个复制组中,必须要求统一开启GTID或者是关闭GTID
5.开启GTID需要重启(5.7除外)
6.开启GTID后,就不再使用原来的传统复制方式
7.对于create temporary table 和 drop temporary table语句不支持
8.不支持sql_slave_skip_counter
部署:
配置 server3-master:
[root@server3 mysql5.7]# vim /etc/my.cnf
##添加内容表示开启 GTID 模块
[root@server3 mysql5.7]# /etc/init.d/mysqld restart
[root@server3 mysql5.7]# mysql -p
配置 server4-slave:
[root@server4 mysql5.7]# vim /etc/my.cnf
[root@server4 mysql5.7]# /etc/init.d/mysqld restart
[root@server4 mysql5.7]# mysql -p
mysql> stop slave;
Query OK, 0 rows affected (0.29 sec)
mysql> change master to
master_host='172.25.100.3',master_user='repl',master_password='REDHAT.org
123',MASTER_AUTO_POSITION=1;
Query OK, 0 rows affected, 2 warnings (0.52 sec)
mysql> start slave;
Query OK, 0 rows affected (0.08 sec)
mysql> show slave status\G;
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 172.25.100.3
Master_User: repl
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 154
Relay_Log_File: server4-relay-bin.000002
Relay_Log_Pos: 367
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
测试:
在 server3-master 中增加数据
[root@server3 mysql5.7]# mysql -p
mysql> insert into linux('user3',789);
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual
that corresponds to your MySQL server version for the right syntax to use near
''user3',789)' at line 1
mysql> insert into linux values('user3',789);
Query OK, 1 row affected (0.34 sec)
在 server4-slave 中登陆 mysql,查看同步情况:
。
三.mysql的半同步复制:
异步复制(Asynchronous replication)
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
全同步复制(Fully synchronous replication)
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
半同步复制(Semisynchronous replication)
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
master-server3部署:
slave-server4部署
测试:master写入
关闭 slave IO 线程;同步失败,设定时间后 master 收不到回复,自动切换为异步
复制(默认10S)
开启 slave IO 线程,再查看,同步成功