背景:
在MySQL5.5版本中,引入了半同步复制模式(Semi-synchronous Replication),在这种模式下:master会等到binlog成功传送并写入至少一个slave的relay log之后才会提交,这样,在允许损失一定的事务吞吐量的前提下来保证同步数据的安全。半同步模式其实是作为MySQL5.5的一个plugin实现的,master和slave使用不同的plugin。
针对MySQL5.5的这个特性,我们做了一些测试,具体情况如下:
一、环境准备
1、操作系统与数据库环境情况:
OS:Ubuntu 12.04 LTS \n \l
mysql:Ver 14.14 Distrib 5.5.32, for debian-linux-gnu (x86_64) using readline 6.2
2、打开semi-sync功能:
Mysql 在编译后会在plugin目录生成两个.so文件,semisync_slave.so semisync_master.so安装
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
主库:
$vi my.cnf
...
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000
...
备库:
$vi my.cnf
...
rpl_semi_sync_slave_enabled=1
这些参数是可以动态修改的
主库执行:
set global rpl_semi_sync_master_enabled=1;
set global rpl_semi_sync_master_timeout=1000;
从库执行;
set global rpl_semi_sync_slave_enabled=1;
重启动slave:
查看状态:
show status like "%rpl_semi%";
mysql> show status like "%rpl_semi%";
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 2 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 0 |
| 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 | 0 |
| Rpl_semi_sync_master_tx_wait_time | 0 |
| Rpl_semi_sync_master_tx_waits | 0 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 0 |
| Rpl_semi_sync_slave_status | OFF |
+--------------------------------------------+-------+
说明半同步已经打开,主库连接有2个客户端。
二、测试情况:
1. 关闭semi_sync功能,使用异步复制,对主节点持续插入三百万条数据,在插入过程中reboot主节点主机。
测试结果:
主库上记录数:
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 1030000 |
+----------+
备库1:
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 870000 |
+----------+
备库2:
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 690000 |
+----------+
2. 做为测试1的对照,打开semi_sync功能,使用半同步复制,对主节点持续插入三百万条数据,在插入过程中reboot主节点主机。
测试结果:
主库
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 1050000 |
+----------+
1 row in set (0.00 sec)
备库1
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 1050000 |
+----------+
1 row in set (0.00 sec)
mysql>
备库2
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 1040000 |
+----------+
1 row in set (0.00 sec)
结论:在经过反复测试,发现在使用reboot(与使用servcie mysql stop命令结果相同),关闭主机的情况下,半同步复制会保证至少一台从节点数据与主节点一致。而异步复制很少能够做到从节点数据不丢失。
3. 关闭semi_sync功能,使用异步复制,对主节点持续插入三百万条数据,在插入过程中直接关闭主节点电源。
测试结果:
主库53:
Database changed
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 2118997 |
+----------+
1 row in set (0.00 sec)
mysql>
从库74
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 2390000 |
+----------+
1 row in set (0.00 sec
从库141
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 2390000 |
奇怪的是两个从库数据均比主库多,
第二次测试:
主库:
Database changed
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 177536 |
+----------+
1 row in set (0.00 sec)
mysql>
从库1
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 450000 |
+----------+
1 row in set (0.00 sec
从库2
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 430000 |
+----------+
1 row in set (0.00 sec)
第二次测试尽管两个从库数据不一致,但都不主库数据多。
此时查看从节点状态,报错信息:
Last_IO_Errno: 1236
Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Client requested master to start replication from impossible position; the first event 'mysql-bin.000017' at 27462756, the last event read from '/var/log/mysql/mysql-bin.000017' at 4, the last byte read from '/var/log/mysql/mysql-bin.000017' at 4.'
Last_SQL_Errno: 0
结果分析:反复关电测试,发现每次都会出现从节点比主节点数据多的情况。经过分析,我们认为,mysql中从节点应该是直接读取的主节点中的缓存中的数据,而这些数据如果在没有写入磁盘中就出现断电的话,这部分数据主节点中将会丢失,而此时从节点因为得到了这部分缓存了的数据,所以会出现比主节点数据多的情况。
4、做为测试3的对照,打开semi_sync功能,使用半同步复制,对主节点持续插入三百万条数据,在插入过程中关闭主节点主机电源。
测试结果:
主库53:
Database changed
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 2118997 |
+----------+
1 row in set (0.00 sec)
mysql>
从库74
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 2390000 |
+----------+
1 row in set (0.00 sec
从库141
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 2390000 |
第二次测试:
主库:
Database changed
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 177536 |
+----------+
1 row in set (0.00 sec)
mysql>
从库1
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 450000 |
+----------+
1 row in set (0.00 sec
从库2
mysql> select count(*) from sbtest;
+----------+
| count(*) |
+----------+
| 430000 |
+----------+
1 row in set (0.00 sec)
结论:在直接关电的情况下,是否打开半同步复制区别不大,都会出现从库比主库多的情况。