默认状况下,MySQL的复制功能是异步的。master把binlog发送给slave时,这个复制动做就已经完成,master不会验证slave是否接收完毕(相似于Oracle DataGuard Maximum Performance)。异步复制同时意味着在把数据从一个mysqld实例拷贝到另外一个mysqld时有一个延时,即master当前提交的事务不会在同一时刻拷贝到slave。这也带来了必定的风险,当master或slave发生故障时,slave有可能会没有接收到master发送过来的binlog,这样就会形成了master/slave的数据不一直,甚至在恢复时也会形成数据的损失。
为了解决这个问题,MySQL 在5.5之后引入了一种半同步模式,slave在接收binlog并写入relay log后会给服务器发送一个反馈,告诉master接收完成,当出现超时状况时,master会暂时切换到异步复制模式,和Oracle DataGuard Maximum Available的处理方式比较类似。半同步复制模式必须在master和slave端同时启用,不然master会使用默认的异步模式。php
个人环境是RHEL 6.5 x86_64, Percona-Server-server-56(RPM),已经配置了异步的同步模式。
检查动态加载选项和插件列表。html
mysql> select @@have_dynamic_loading ; +------------------------+ | @@have_dynamic_loading | +------------------------+ | YES | +------------------------+ 1 row in set (0.00 sec) mysql> show plugins; ......
默认并无加载半同步插件,rpm发行版的插件.so文件的位置
/usr/lib64/mysql/plugin/semisync_master.so
/usr/lib64/mysql/plugin/semisync_slave.so
而后在M/S上都加载插件并启用同步。初次加载插件后,MySQL会将该插件记录到系统表mysql.plugin中,下次mysqld启动时会自动加载,无需INSTALL PLUGINmysql
mysql> INSTALL PLUGIN rpl_semi_sync_master soname 'semisync_master.so' ; Query OK, 0 rows affected (0.01 sec) 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_master_enabled=ON; mysql> SET GLOBAL rpl_semi_sync_slave_enabled=ON;
要将rpl_semi_sync_master_enabled和rpl_semi_sync_slave_enabled参数写入配置文件my.cnfsql
rpl_semi_sync_master_enabled = 1 rpl_semi_sync_slave_enabled =1
日志文件会显示:bash
2014-08-14 14:13:23 5927 [Note] Semi-sync replication initialized for transactions. 2014-08-14 14:13:23 5927 [Note] Semi-sync replication enabled on the master.
在master上有4个相关参数,slave中有2个.服务器
mysql> show global variables like 'rpl_semi%'; +------------------------------------+-------+ | Variable_name | Value | +------------------------------------+-------+ | rpl_semi_sync_master_enabled | ON | --master上是否开启了半同步复制模式 | rpl_semi_sync_master_timeout | 10000 | --该参数默认为10000毫秒,可动态调整。它用来表示若是主库中某个事务等待时间超过10秒,则降级为异步复制模式。 | rpl_semi_sync_master_trace_level | 32 | --开启半同模式的调试级别 | rpl_semi_sync_master_wait_no_slave | ON | --表示是否容许master每一个事物提交后都要等待slave的接收等待确认信号,默认为ON。 | rpl_semi_sync_slave_enabled | ON | --slave是否开启了半同步复制模式 | rpl_semi_sync_slave_trace_level | 32 | +------------------------------------+-------+ 6 rows in set (0.00 sec)
3. 半同步与异步的切换网络
执行完上面的步骤后,咱们在M/S上检查半同步的状态,发现rpl_semi_sync_slave_status都是关闭的。这说明虽然启用了半同步的功能,但slave不会自动从异步模式转换到半同步模式。session
mysql> show status like "%semi%"; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | --有多少slave配置成了semi-sync模式 | Rpl_semi_sync_master_net_avg_wait_time | 677 | --等待slave确认的平均等待时间,单位微秒。 | Rpl_semi_sync_master_net_wait_time | 3385 | --master的总等待时间,单位微秒 | Rpl_semi_sync_master_net_waits | 5 | --等待slave确认的的总的等待次数 | Rpl_semi_sync_master_no_times | 0 | --关闭半同步复制的次数 | Rpl_semi_sync_master_no_tx | 0 | --slave确认的不成功提交次数 | Rpl_semi_sync_master_status | ON | --master如今是不是半同步复制状态 | Rpl_semi_sync_master_timefunc_failures | 0 | --半同步所用的时间函数失败的次数 | Rpl_semi_sync_master_tx_avg_wait_time | 776 | --事务等待slave确认的平均等待时间,单位微秒 | Rpl_semi_sync_master_tx_wait_time | 3881 | --事物等待slave确认的总等待时间,单位微秒 | Rpl_semi_sync_master_tx_waits | 5 | --等待slave确认的的总的等待次数 | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | --改变当前等待最小二进制日志的次数 | Rpl_semi_sync_master_wait_sessions | 0 | --当前有多少个session 由于slave 的回复而形成等待 | Rpl_semi_sync_master_yes_tx | 5 | --slave确认的成功提交次数 | Rpl_semi_sync_slave_status | OFF | --该server的slave是否处于半同步状态 +--------------------------------------------+-------+
过上面的参数也说明了开启半同步会致使一部分额外的开销:
(1). 完成单条事务增长了额外的等待延迟,延迟的大小取决于网络的好坏。
(2). Semi-sync不是分布式事务,主库会在本身完成事务后,等待备库接收事务日志。
接下来从新启动slave。异步
mysql> stop slave; Query OK, 0 rows affected (0.01 sec) mysql> start slave ; Query OK, 0 rows affected (0.03 sec) 这是Master和Slave中的日志中会提示: --- master --- 2014-08-14 14:26:10 5927 [Note] Start semi-sync binlog_dump to slave (server_id: 2), pos(mysql-bin.000009, 1507) --- slave --- 2014-08-14 14:26:09 5969 [Note] Slave I/O thread: Start semi-sync replication to master 'rep@172.19.17.210:3306' in log 'mysql-bin.000009' at position 1507
次检查slave的状态:分布式
mysql> show status like "%semi%"; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_status | ON | ...... | Rpl_semi_sync_slave_status | ON | +--------------------------------------------+-------+ 15 rows in set (0.01 sec)
参考:通常状况下,当slave的io线程将binlog接受完毕后,要给master发送一个确认。若是超过rpl_semi_sync_master_timeout=10000(10秒)内未收到该确认信号,那么就自动转换为异步复制模式。这种状况下要排查错误并重启slave来恢复半同步模式。
http://dev.mysql.com/doc/refman/5.5/en/replication-semisync.html
http://www.orczhou.com/index.php/2011/06/mysql-5-5-semi-sync-replication-setup-config/