复制模式
MySQL主从复制包括异步模式、半同步模式、GTID模式以及多源复制模式,默认是异步模式.
- 异步复制(
Asynchronous replication
)
所谓异步模式指的是MySQL 主服务器上I/O thread 线程将二进制日志写入binlog文件之后就返回客户端结果,不会考虑二进制日志是否完整传输到从服务器以及是否完整存放到从服务器上的relay log(中继日志)中,这种模式一旦主服务(器)宕机,数据就可能会发生丢失。
- 全同步复制(
Fully synchronous replication
)
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
- 半同步复制(
Semisynchronous replication
)
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
半同步潜藏问题
mysql5.7
版本前,客户端事务在存储引擎层提交后,在得到从库确认的过程中,主库宕机了,客户端会收到事务提交失败的信息,此时,可能的情况有两种:
此时客户端由于提交失败,再次提交事务,出现问题.
mysql5.7
版本引入新的半同步方式,事务提交需要从库同步完成.通过rpl_semi_sync_master_wait_point
参数控制:
AFTER_SYNC
, 这个是新的半同步方案
AFTER_COMMIT
, 这个是老的半同步方案
开启半同步复制
半同步复制的安装部署条件:
MySQL 5.5
及以上版本
- 变量
have_dynamic_loading
为YES
(查看命令:show variables like "have_dynamic_loading";
)
- 主从复制已经配置完成
半同步复制是以插件的形式安装的,默认安装包在/usr/local/mysql/lib/plugin/
目录下.可以通过命令查看
show plugins;
SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME LIKE '%semi%';
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
SET GLOBAL rpl_semi_sync_master_enabled = 1;
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
SET GLOBAL rpl_semi_sync_master_enabled = 1;
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
UNINSTALL PLUGIN rpl_semi_sync_master;
UNINSTALL PLUGIN rpl_semi_sync_slave;
plugin-load=rpl_semi_sync_master=semisync_master.so
rpl_semi_sync_master_enabled=1
plugin-load=rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_slave_enabled=1
plugin-load="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
rpl-semi-sync-master-enabled=1
rpl-semi-sync-slave-enabled=1
需要注意,Mysql半同步复制
并不是严格意义上的半同步复制。当半同步复制发生超时时(由rpl_semi_sync_master_timeout
参数控制,单位是毫秒,默认为10000
,即10s
),会暂时关闭半同步复制,转而使用异步复制。当master dump线程发送完一个事务的所有事件之后,如果在rpl_semi_sync_master_timeout
内,收到了从库的响应,则主从又重新恢复为半同步复制。一旦有一次超时自动降级为异步
.
查看半同步复制状态
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> show status like 'Rpl_semi_sync_master_status';
+
| Variable_name | Value |
+
| Rpl_semi_sync_master_status | ON |
+
1 row in set (0.01 sec)
mysql> show status like 'Rpl_semi_sync_slave_status';
+
| Variable_name | Value |
+
| Rpl_semi_sync_slave_status | ON |
+
1 row in set (0.00 sec)
mysql> show variables like '%Rpl%';
+
| Variable_name | Value |
+
| rpl_semi_sync_master_enabled | ON |
| rpl_semi_sync_master_timeout | 10000 |
| rpl_semi_sync_master_trace_level | 32 |
| rpl_semi_sync_master_wait_for_slave_count | 1 |
| rpl_semi_sync_master_wait_no_slave | ON |
| rpl_semi_sync_master_wait_point | AFTER_SYNC |
| rpl_stop_slave_timeout | 31536000 |
+
mysql> show variables like '%Rpl%';
+
| Variable_name | Value |
+
| rpl_semi_sync_slave_enabled | ON |
| rpl_semi_sync_slave_trace_level | 32 |
| rpl_stop_slave_timeout | 31536000 |
+
3 rows in set (0.00 sec)
mysql> show status like '%Rpl_semi%';
+
| Variable_name | Value |
+
| Rpl_semi_sync_master_clients | 1 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 1 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 |
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 461 |
| Rpl_semi_sync_master_tx_wait_time | 461 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 |
+
14 rows in set (0.00 sec)
简单测试
mysql> insert into test.testttt values(1,'22');
Query OK, 1 row affected (0.00 sec)
mysql> stop slave;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test.testttt values(1,'222');
Query OK, 1 row affected (10.01 sec)
mysql> show status like 'Rpl_semi_sync_master_status';
+
| Variable_name | Value |
+
| Rpl_semi_sync_master_status | OFF |
+
1 row in set (0.00 sec)
mysql> show status like 'Rpl_semi_sync_slave_status';
+
| Variable_name | Value |
+
| Rpl_semi_sync_slave_status | OFF |
+
1 row in set (0.00 sec)
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test.testttt values(1,'222');
Query OK, 1 row affected (0.00 sec)
其它注意参数
默认,sync_binlog=0
,表示MySQL不控制binlog的刷新,由文件系统自己控制它的缓存的刷新。这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。
如果sync_binlog>0
,表示每sync_binlog次事务提交,MySQL调用文件系统的刷新操作将缓存刷下去。最安全的就是sync_binlog=1
了,表示每次事务提交,MySQL都会把binlog刷下去,是最安全但是性能损耗最大的设置。
默认为10000
,即每10000
次sync_relay_log
事件会刷新到磁盘。为0
则表示不刷新,交由系统的cache
控制
sync_binlog=1
sync_master_info=1
sync_relay_log=1
sync_relay_log_info=1
参考链接