主从复制

原理:将主服务器的binlog日志复制到从服务器上执行一遍,达到主从数据的一致状态。**

过程:从库开启一个I/O线程,向主库请求Binlog日志。主节点开启一个binlog dump线程,检查自己的二进制日志,并发送给从节点;从库将接收到的数据保存到中继日志(Relay log)中,另外开启一个SQL线程,把Relay中的操作在自身机器上执行一遍

优点:作为备用数据库,并且不影响业务可做读写分离,一般是一个写库,一个或多个读库,分布在不同的服务器上,充分发挥服务器和数据库的性能,但要保证数据的一致性

MySQL复制支持多种不同的复制策略,包括同步、半同步、异步和延迟策略等。

同步策略:Master要等待所有Slave应答之后才会提交(MySql对DB操作的提交通常是先对操作事件进行二进制日志文件写入然后再进行提交)。
半同步策略:Master等待至少一个Slave应答就可以提交。
异步策略:Master不需要等待Slave应答就可以提交。
延迟策略:Slave要至少落后Master指定的时间。

异步复制

MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从库上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。

主库将事务 Binlog 事件写入到 Binlog 文件中,此时主库只会通知一下 Dump 线程发送这些新的 Binlog,然后主库就会继续处理提交操作,而此时不会保证这些 Binlog 传到任何一个从库节点上。

异步复制—基于二进制日志文件的主从复制
注:server1和server2上均装有mysql,且均完成了安全初始化
在server1上:(master)
server1(172.25.20.1)为主数据库,
server2(172.25.20.3)为从数据库

vim /etc/my.cnf
/etc/init.d/mysqld restart
##写入server-id=1(服务器ID) log-bin=mysql-bin(开启二进制日志)

##进入mysql
mysql -p

mysql>create user 'repl'@'172.25.20.%' identified by 'westos';##创建复制用户
mysql>grant replication slave on *.* to 'repl'@'172.25.20.%';##授予用户权限
mysql> flush privileges;

server2上:(slave)

mysql -h 172.25.20.1 -u repl -pwestos
##检测复制用户是否创建成功

vim /etc/my.cnf
##写入server-id=2

systemctl restart mariadb

在server1上:

mysql -p
mysql> show master status;##查看master状态

在server2上:

配置slave:

mysql -p
mysql> change master to   
 -> master_host='172.25.20.1',    
 -> master_user='repl',    
 -> master_password='westos',    
 -> master_log_file='mysql-bin.000001',    
 -> master_log_pos=1200;
mysql> start slave;
mysql> show slave status\G;           
#Slave_IO_Running: Yes            
#Slave_SQL_Running: Yes
#显示如上说明主从复制成功

注意:上面的master_log_file和master_log_pos的参数根据master 的状态填写
测试:
在server1中创建一个库或表,在server2中也可以显示看到,则证明主从复制成功。
异步复制—基于全局事务标识(GTID)的主从复制
注:两个服务器已经使用MySQL的基于二进制日志位置的复制协议作为主服务器和从服务器运行
在server1(主节点中)
配置主节点:启用复制主节点,开启gtid服务

vim /etc/my.cnf
log-bin=mysql-bin ##基于二进制日志位置的主从复制
server-id=1
gtid_mode=ON ##打开gtid
enforce-gtid-consistency=OK
/etc/init.d/mysqld restart

在server2(从节点中)
配置从站slave开启GTID的服务

vim /etc/my.cnf

server-id=2   ##基于二进制日志位置的主从复制
gtid_mode=ON  ##打开gtid
enforce-gtid-consistency=ON

systemctl restart mariadb

配置从站slave使用基于GTID的自动定位。

mysql> stop slave; ##停止基于二进制位置的复制

mysql> CHANGE MASTER TO
    -> MASTER_HOST = '172.25.20.1',
    -> MASTER_USER = 'repl',
    -> MASTER_PASSWORD = 'westos',
    -> MASTER_AUTO_POSITION = 1;

mysql> START SLAVE; ##开启gtid的主从复制
mysql> SHOW SLAVE STATUS\G ##查看复制状态

测试:
在主节点server1中插入数据,在从节点server2中查看。

半同步复制

半同步复制是介于全同步复制与全异步复制之间的一种,主库只需要等待至少一个从库节点收到并且 Flush Binlog 到 Relay Log 文件即可,主库不需要等待所有从库给主库反馈。同时,这里只是一个收到的反馈,而不是已经完全完成并且提交的反馈,如此,节省了很多时间。

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

半同步复制为异步复制协议添加了一个同步步骤。这意味着主库在提交时等待至少一个从库确认它已收到该事务,才会继续提交操作。

对角箭头表示服务器之间交换的消息或服务器与客户端应用程序之间交换的消息。

在server1中:
主库安装服务插件,并且开启半同步复制:

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.01 sec)

mysql> select plugin_name,plugin_status
    -> from information_schema.plugins
    -> where plugin_name like '%semi%';
+----------------------+---------------+
| plugin_name          | plugin_status |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE        |
+----------------------+---------------+
1 row in set (0.00 sec)

mysql> set global rpl_semi_sync_master_enabled=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%semi%';    #环境变量
mysql> show status like '%rpl_semi_sync%';	#状态变量

在server2中:
在从端也安装插件,开启半同步复制:

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.00 sec)

mysql> set global rpl_semi_sync_slave_enabled=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%semi%';

注意: 要重启从上的IO线程,如果没有重启,则默认还是异步复制,重启后,slave会在master上注册为半同步复制的slave角色。

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 status like '%rpl%';
mysql> show variables like '%rpl%';

测试:半同步测试正常同步情况:

从端打开IO:

mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)

主端插入新数据:
mysql> insert into userlist values ('user333','333');
Query OK, 1 row affected (0.01 sec)

mysql> select * from user_tb;

mysql> show status like '%rpl%'; 
#Rpl_semi_sync_master_yes_tx 变为1,成功一次

从端验证同步结果:
mysql> select * from user_tb;

原理:将主服务器的binlog日志复制到从服务器上执行一遍,达到主从数据的一致状态。**

过程:从库开启一个I/O线程,向主库请求Binlog日志。主节点开启一个binlog dump线程,检查自己的二进制日志,并发送给从节点;从库将接收到的数据保存到中继日志(Relay log)中,另外开启一个SQL线程,把Relay中的操作在自身机器上执行一遍

优点:作为备用数据库,并且不影响业务可做读写分离,一般是一个写库,一个或多个读库,分布在不同的服务器上,充分发挥服务器和数据库的性能,但要保证数据的一致性

MySQL复制支持多种不同的复制策略,包括同步、半同步、异步和延迟策略等。

同步策略:Master要等待所有Slave应答之后才会提交(MySql对DB操作的提交通常是先对操作事件进行二进制日志文件写入然后再进行提交)。
半同步策略:Master等待至少一个Slave应答就可以提交。
异步策略:Master不需要等待Slave应答就可以提交。
延迟策略:Slave要至少落后Master指定的时间。

异步复制
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从库上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。

主库将事务 Binlog 事件写入到 Binlog 文件中,此时主库只会通知一下 Dump 线程发送这些新的 Binlog,然后主库就会继续处理提交操作,而此时不会保证这些 Binlog 传到任何一个从库节点上。

异步复制—基于二进制日志文件的主从复制
注:server1和server2上均装有mysql,且均完成了安全初始化
在server1上:(master)
server1(172.25.20.1)为主数据库,
server2(172.25.20.3)为从数据库

vim /etc/my.cnf
/etc/init.d/mysqld restart
##写入server-id=1(服务器ID) log-bin=mysql-bin(开启二进制日志)

##进入mysql
mysql -p

mysql>create user 'repl'@'172.25.20.%' identified by 'westos';##创建复制用户
mysql>grant replication slave on *.* to 'repl'@'172.25.20.%';##授予用户权限
mysql> flush privileges;

server2上:(slave)

mysql -h 172.25.20.1 -u repl -pwestos
##检测复制用户是否创建成功

vim /etc/my.cnf
##写入server-id=2

systemctl restart mariadb

在server1上:

mysql -p
mysql> show master status;##查看master状态

在server2上:

配置slave:

mysql -p
mysql> change master to   
 -> master_host='172.25.20.1',    
 -> master_user='repl',    
 -> master_password='westos',    
 -> master_log_file='mysql-bin.000001',    
 -> master_log_pos=1200;
mysql> start slave;
mysql> show slave status\G;           
#Slave_IO_Running: Yes            
#Slave_SQL_Running: Yes
#显示如上说明主从复制成功

注意:上面的master_log_file和master_log_pos的参数根据master 的状态填写
测试:
在server1中创建一个库或表,在server2中也可以显示看到,则证明主从复制成功。
异步复制—基于全局事务标识(GTID)的主从复制
注:两个服务器已经使用MySQL的基于二进制日志位置的复制协议作为主服务器和从服务器运行
在server1(主节点中)
配置主节点:启用复制主节点,开启gtid服务

vim /etc/my.cnf
log-bin=mysql-bin ##基于二进制日志位置的主从复制
server-id=1
gtid_mode=ON ##打开gtid
enforce-gtid-consistency=OK
/etc/init.d/mysqld restart

在server2(从节点中)
配置从站slave开启GTID的服务

vim /etc/my.cnf

server-id=2   ##基于二进制日志位置的主从复制
gtid_mode=ON  ##打开gtid
enforce-gtid-consistency=ON

systemctl restart mariadb

配置从站slave使用基于GTID的自动定位。

mysql> stop slave; ##停止基于二进制位置的复制

mysql> CHANGE MASTER TO
    -> MASTER_HOST = '172.25.20.1',
    -> MASTER_USER = 'repl',
    -> MASTER_PASSWORD = 'westos',
    -> MASTER_AUTO_POSITION = 1;

mysql> START SLAVE; ##开启gtid的主从复制
mysql> SHOW SLAVE STATUS\G ##查看复制状态

测试:
在主节点server1中插入数据,在从节点server2中查看。

半同步复制

半同步复制是介于全同步复制与全异步复制之间的一种,主库只需要等待至少一个从库节点收到并且 Flush Binlog 到 Relay Log 文件即可,主库不需要等待所有从库给主库反馈。同时,这里只是一个收到的反馈,而不是已经完全完成并且提交的反馈,如此,节省了很多时间。

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

半同步复制为异步复制协议添加了一个同步步骤。这意味着主库在提交时等待至少一个从库确认它已收到该事务,才会继续提交操作。

对角箭头表示服务器之间交换的消息或服务器与客户端应用程序之间交换的消息。

在server1中:
主库安装服务插件,并且开启半同步复制:

mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
Query OK, 0 rows affected (0.01 sec)

mysql> select plugin_name,plugin_status
    -> from information_schema.plugins
    -> where plugin_name like '%semi%';
+----------------------+---------------+
| plugin_name          | plugin_status |
+----------------------+---------------+
| rpl_semi_sync_master | ACTIVE        |
+----------------------+---------------+
1 row in set (0.00 sec)

mysql> set global rpl_semi_sync_master_enabled=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%semi%';    #环境变量
mysql> show status like '%rpl_semi_sync%';	#状态变量

在server2中:
在从端也安装插件,开启半同步复制:

mysql> install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
Query OK, 0 rows affected (0.00 sec)

mysql> set global rpl_semi_sync_slave_enabled=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like '%semi%';

注意: 要重启从上的IO线程,如果没有重启,则默认还是异步复制,重启后,slave会在master上注册为半同步复制的slave角色。

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 status like '%rpl%';
mysql> show variables like '%rpl%';

测试:半同步测试正常同步情况:

从端打开IO:

mysql> start slave io_thread;
Query OK, 0 rows affected (0.00 sec)

主端插入新数据:
mysql> insert into userlist values ('user333','333');
Query OK, 1 row affected (0.01 sec)

mysql> select * from user_tb;

mysql> show status like '%rpl%'; 
#Rpl_semi_sync_master_yes_tx 变为1,成功一次

从端验证同步结果:
mysql> select * from user_tb;