在MySQL主从复制中,大体上有三个线程,master端有一个dump 线程,slave端有两个线程,i/o 线程和sql线程。
当有数据写入后,master 端的dump线程将bin log发送到slave端的io线程,i/o线程接收后,将其存放在本地的relay log中。
sql线程读取relay log,接着重放 event,更新数据。
主从复制有三种方式:
异步复制同步复制半同步复制其中,同步复制中,master执行一个事务后,要求所有的slave都执行完成后,才会返回给客户端。这样,在性能上,是有影响的。同步复制的优势,就是不丢失数据。缺点,就是复制效率低。 MySQL自身不支持同步复制,需要用第三方工具如DRBD(sync模式)等实现同步复制。
异步复制中,master 更新操作写入binlog后,就会返回给客户端。不关心,slave 是否接收到binlog,以及是否应用了更新。异步复制的优势,是复制效率高。缺点是,可能会丢失数据。
半同步复制(semi-sync repication),是介于同步复制和异步复制之间的一种复制方式。主库在执行完客户端提交的事务之后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端(极端情况下,如果等待超时,会退化为异步复制)。相对于异步复制,半同步复制提高了数据的安全性。
下文使用的是单机多实例环境,具体搭建过程可参考单机安装MySQL多实例。
MySQL版本是 5.7.27。
MySQL主从集群信息如下:
角色ipport主库127.0.0.13306从库127.0.0.13307MySQL安装包中,已经自带MySQL半同步插件。
$ ll /application/mysql/lib/plugin/semi* -rwxr-xr-x. 1 lanyang lanyang 708586 Jun 10 2019 /application/mysql/lib/plugin/semisync_master.so -rwxr-xr-x. 1 lanyang lanyang 152341 Jun 10 2019 /application/mysql/lib/plugin/semisync_slave.so安装插件
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so'; Query OK, 0 rows affected (0.01 sec) mysql>主库开启半同步
mysql> set global rpl_semi_sync_master_enabled = 1; Query OK, 0 rows affected (0.01 sec) mysql>配置半同步超时参数(单位ms)
mysql> set global rpl_semi_sync_master_timeout = 1000; Query OK, 0 rows affected (0.00 sec) mysql>该参数表示主库等待从库ack的时间,如果超时,半同步复制就退化为异步复制。
此处配置的超时时间是1s。
在配置文件添加,使其永久生效:
[mysqld] rpl_semi_sync_master_enabled = 1 rpl_semi_sync_master_timeout = 1000查看半同步插件安装和配置状态
mysql> select * from mysql.plugin; +----------------------+--------------------+ | name | dl | +----------------------+--------------------+ | rpl_semi_sync_master | semisync_master.so | +----------------------+--------------------+ 1 row in set (0.00 sec)主库半同步复制的状态参数
mysql> show global status like '%semi%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 0 | | 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 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec)其中,Rpl_semi_sync_master_clients 有多少个开启了半同步复制的从库。
Rpl_semi_sync_master_net_avg_wait_time master等待slave回复的平均网络等待时间。
Rpl_semi_sync_master_net_wait_time 总网络等待时间。
Rpl_semi_sync_master_net_waits master等待slave回复总的网络等待次数。
Rpl_semi_sync_master_tx_avg_wait_time 平均事务等待时间。
Rpl_semi_sync_master_tx_wait_time 总事务等待时间。
Rpl_semi_sync_master_tx_waits 总事务等待次数。
Rpl_semi_sync_master_yes_tx 接收确认次数。
Rpl_semi_sync_master_no_times 关闭半同步复制的次数。
Rpl_semi_sync_master_no_tx 查看有多少事务没有使用半同步复制的机制进行复制,也就是master等待超时的次数。
主库半同步复制的相关参数配置
mysql> show global variables like '%semi%'; +-------------------------------------------+------------+ | Variable_name | Value | +-------------------------------------------+------------+ | rpl_semi_sync_master_enabled | ON | | rpl_semi_sync_master_timeout | 1000 | | 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 | +-------------------------------------------+------------+ 6 rows in set (0.00 sec)其中, rpl_semi_sync_master_wait_for_slave_count 表示主库事务提交前,在指定的时间rpl_semi_sync_master_timeout超时之前,必须有这个指定数量的从库确认已接收到。
如果超时之前,仍然没有得到rpl_semi_sync_master_wait_for_slave_count这个数量的从库确认,则退化为异步复制。
默认值1,即超时之前,需要有一个从库确认已接收到bin log,事务才可以提交。
对于 rpl_semi_sync_master_wait_no_slave,表示是否每个事务提交后都需要等待从库的接收确认信号。
如果为ON(默认是ON),只要指定数量的从库在超时之前确认已接收,则半同步复制会继续。
如果为OFF,表示在超时之前,没有达到指定数量从库已确认接收。则退化为异步复制。
从库开启半同步
mysql> set global rpl_semi_sync_slave_enabled = 1; Query OK, 0 rows affected (0.00 sec) mysql>添加到配置文件使其永久生效:
[mysqld] rpl_semi_sync_slave_enabled = 1配置后,记得重启下i/o线程。
查看从库上半同步复制状态和参数:
mysql> show global status like '%semi%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.00 sec) mysql> show global variables like '%semi%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ 2 rows in set (0.00 sec)接着,查看主库上的半同步复制状态:
mysql> show global status like '%semi%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 1 | +--------------------------------------------+-------+ ... ... 14 rows in set (0.00 sec)显示已有一个从库通过半同步复制连接到主库。
在主库上写入两条数据:
mysql> insert into app.test(service_group_name) values('abc001'); Query OK, 1 row affected (0.01 sec) mysql> insert into app.test(service_group_name) values('abc002'); Query OK, 1 row affected (0.00 sec)查看主库上的半同步复制状态:
mysql> show global status like '%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 | 2 | | 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 | 472 | | Rpl_semi_sync_master_tx_wait_time | 472 | | 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 | 2 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec) mysql>(1)停止从库的i/o线程
停止从库的i/o线程,可以使半同步复制超时。
mysql> stop slave io_thread; Query OK, 0 rows affected (0.01 sec)(2)在主库上写入数据
mysql> insert into app.test(service_group_name) values('abc003'); Query OK, 1 row affected (1.01 sec) mysql>可以看到执行时间1.01s。
查看此时的半同步复制状态:
mysql> show global status like '%semi%'; +--------------------------------------------+-------+ | Variable_name | Value | +--------------------------------------------+-------+ | Rpl_semi_sync_master_clients | 0 | | Rpl_semi_sync_master_net_avg_wait_time | 0 | | Rpl_semi_sync_master_net_wait_time | 0 | | Rpl_semi_sync_master_net_waits | 2 | | Rpl_semi_sync_master_no_times | 1 | | Rpl_semi_sync_master_no_tx | 1 | | Rpl_semi_sync_master_status | OFF | | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 472 | | Rpl_semi_sync_master_tx_wait_time | 472 | | 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 | 2 | +--------------------------------------------+-------+ 14 rows in set (0.01 sec)Rpl_semi_sync_master_no_times 关闭半同步的次数为1。
Rpl_semi_sync_master_no_tx 等待超时的次数,为1.
Rpl_semi_sync_master_status 半同步状态处于关闭状态。
(3)从库开启i/o 线程
mysql> start slave io_thread; Query OK, 0 rows affected (0.00 sec)(4)再次查看主库上半同步复制状态
mysql> show global status like '%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 | 3 | | Rpl_semi_sync_master_no_times | 1 | | Rpl_semi_sync_master_no_tx | 1 | | Rpl_semi_sync_master_status | ON | | Rpl_semi_sync_master_timefunc_failures | 0 | | Rpl_semi_sync_master_tx_avg_wait_time | 472 | | Rpl_semi_sync_master_tx_wait_time | 472 | | 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 | 2 | +--------------------------------------------+-------+ 14 rows in set (0.00 sec)从库复制后,主库半同步复制状态又变为ON。
16.1.6.2 Replication Source Options and Variables