安装、配置Semi-sync Replication
在两台主机上安装好MySQL5.5,编译好的插件在目录CMAKE_INSTALL_PREFIX/lib/plugin下(默认是/usr/local/mysql/lib/plugin)。例如这里编译是指定CMAKE_INSTALL_PREFIX为/home/mysql/mysql,则有:semisync_master.so semisync_slave.so
mysql主从备份之间存在同步,半同步与异步的方式,对于同步与异步相对而言比较好理解,但是同步存在延迟比较大,效率不高,异步又不能百分百保证数据的一致性。而半同步方式正好是两者的兼容。
mysql半同步模式是在mysql5.5版本以后增加的,所谓半同步指当master事物提交后,等待slave接收日志后才返回给应用层表示成功,事物足够小,延迟较小的话,通过半同步的模式,牺牲较小的性能就能保证数据不丢失。
但是半同步的方式也存在着缺陷,完成单条事物增加了额外的开销,同时延迟的大小也取决于网络的好坏。
采用半同步的方式,当slave down机时,master在一次等待超时时,会关闭半同步的特性,切换到异步的方式。master down机后,可能存在一些事务已经在主库Commit,但是还没有传给任何slave,这类事务被称为"墙头事务",“墙头事务”都是没有返回给slave的,所以发起事务的应用层并不知道这个事务是否已经完成。这时,如果应用层不做切换,只是等down机的master恢复后,继续在master进行操作,客户端会发现前面的"墙头事务"都已经完成,可以继续进行后续的业务处理;另一种情况,如果应用层Failover到slave上,应用层会发现前面的“墙头事务”都没有成功,则需要重新做这些事务,然后继续进行后续的业务处理。
对于slave可以有多个,任何一个slave接收完成日志后,master就可以返回给应用层了,网络传输在并发线程较多时,一次可能传输很多日志,事务的平均延迟会降低。"墙头事务"在墙头上的时候,是可以被读取的,但是这些事务在上面Failover的场景下,是被认为没有完成的。
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so'; Query OK, 0 rows affected (0.01 sec) mysql> show global variables like 'rpl_semi_sync%'; +------------------------------------+-------+ | Variable_name | Value | +------------------------------------+-------+ | rpl_semi_sync_master_enabled | OFF | | rpl_semi_sync_master_timeout | 10000 | | rpl_semi_sync_master_trace_level | 32 | | rpl_semi_sync_master_wait_no_slave | ON | +------------------------------------+-------+ 4 rows in set (0.00 sec)
从库需要安装rpl_semi_sync_slave
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; Query OK, 0 rows affected (0.01 sec) mysql> show global variables like 'rpl_semi_sync%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | OFF | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ 2 rows in set (0.01 sec) mysql>
这些参数是可以动态修改的
rpl_semi_sync_master_enabled :
启动master 支持半同步复制。
rpl_semi_sync_master_timeout :
主库等待半同步复制信息返回的超时间隔,默认10秒
rpl_semi_sync_master_trace_level :
监控等级:
1 = general level (for example, time function failures)
16 = detail level (more verbose information)
32 = net wait level (more information about network waits)
64 = function level (information about function entry and exit)
rpl_semi_sync_master_wait_no_slave :
是否允许master 每个事物提交后都要等待slave 的receipt信号。
默认为on ,每一个事务都会等待,如果slave当掉后,当slave追赶上master的日志时
,可以自动的切换为半同步方式,如果为off,则slave追赶上后,也不会采用半同步的
相应的系统的状态变量:master
mysql> show global status like 'rpl_semi_sync%'; ; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | #记录支持半同步的slave的个数 | Rpl_semi_sync_master_net_avg_wait_time | 411 | #master 等待slave 回复的平均等待时间。 单位毫秒. | Rpl_semi_sync_master_net_wait_time | 27959 | #master 总的等待时间 | Rpl_semi_sync_master_net_waits | 68 | #master 等待slave 回复的的总的等待次数 | Rpl_semi_sync_master_no_times | 0 | #master 关闭半同步复制的次数 | Rpl_semi_sync_master_no_tx | 0 | #aster 没有收到slave的回复而提交的次数 | Rpl_semi_sync_master_status | ON | #标记master现在是否是半同步复制状态 | Rpl_semi_sync_master_timefunc_failures | 0 | #时间函数未正常工作的次数 | Rpl_semi_sync_master_tx_avg_wait_time | 512 | #开启Semi-sync,事务返回需要等待的平均时间 | Rpl_semi_sync_master_tx_wait_time | 34881 | #事务等待备库响应的总时间 | Rpl_semi_sync_master_tx_waits | 68 | #事务等待备库响应的总次数 | Rpl_semi_sync_master_wait_pos_backtraverse | 0 | #改变当前等待最小二进制日志的次数 | Rpl_semi_sync_master_wait_sessions | 0 | # 当前有几个线程在等备库响应 | Rpl_semi_sync_master_yes_tx | 68 | # Semi-sync模式下,成功的事务数 +--------------------------------------------+-------+
slave 的系统状态变量
mysql> show global status like 'rpl_semi_sync%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | OFF | +----------------------------+-------+ 1 row in set (0.01 sec) #标记slave 是否在半同步状态。
关于Rpl_semi_sync_master_wait_pos_backtraverse
花了一些时间弄明白这个变量,继续证实了这个变量确实不重要。
在semisync_master中,维护了这样的两个变量wait_file_name_和wait_file_pos_,当主库上多个事务都在等待备库的响应时,这两个变量记录了所有等待中,最小的那一个Binlog位置。如果这时,一个新的事务加入等待,并且该事务需要等待的Binlog比wait_file_name_和wait_file_pos_还小的话,则更新这两个值,并将Rpl_semi_sync_master_wait_pos_backtraverse值自增一次。
配置mysql原生主从,master配置:
# master my.cnf log-bin = /data/mysqllog/binlog/mysql-bin expire_logs_days = 2 server-id = 20 ID,主从不可重复 binlog-do-db = dingmh #需要同步的库 binlog-ignore-db = mysql #忽略同步的库 增加主从同步的帐户 GRANT REPLICATION SLAVE ON *.* TO 'slave001'@'172.168.10.12' IDENTIFIED BY '123456'; #slave my.cnf server-id = 21 replicate-do-db = dingmh #需要复制的数据库名 replicate-ignore-db= xxx #不需要复制的数据库名 change master to master_host='172.168.10.11',master_user='slave001',master_password='123456'; slave start;
配置semi-sync:
#master my.cnf rpl_semi_sync_master_enabled=1 rpl_semi_sync_master_timeout=1000 #slave my.cnf rpl_semi_sync_slave_enabled=1