mysql复制包括异步复制和半同步复制:
异步复制:主库将事件写入二进制日志,但不知道从库是否接收成功,也不知道从库什么时候重放二进制日志,如果主库崩溃,则在主库提交的事务可能还没有传输到从库,这种情况下如果主从故障切换,从库还没有传输到从库的事务将丢失
master发起事务提交,在execute阶段执行完对数据的修改,然后写入事件到二进制日志,在commit阶段完成存储引擎层的事务提交,同时主库通过dump线程把二进制日志发送到两个从库,另个从库接收到后写入relay log日志文件,之后读取relay log日志进行应用,最后进行提交,由于主库发送binlog是异步的,从库是否接收成功不影响主库的提交。
为了避免从库没有接收到binlog导致的数据丢失。mysql对复制进行了改进,引入了半同步复制,半同步复制是以插件的形式进行安装。半同步复制,主库提交事务产生的二进制日志,需要至少被一个从库接收并写入relay log中等待ACK消息被主库成功接收之后主库才确认事务以提交。正常情况下主库发生故障转移时不会产生数据丢失问题
半同步复制在binlog日志阶段后commit阶段前,主库必须等待从库在把日志写入relay日志后回复ACK消息,确保从库把接收的日志写入了relay log中,这样就避免了异步复制主库宕机可能存在的日志丢失问题了。
mysql5.7增强半同步复制:
rpl_semi_sync_master_wait_point的配置(控制半同步复制中在主库返回事务提交状态信息给客户端之前,等待从库ack消息的位点)
after_sync(默认):主库将事务修改写入二进制日志,把日志传输到从库,等待从库写入relay log 并返回ACK消息后,主库将在存储引擎层提交事务,并将结果返回给发起的事务的客户端,然后客户端可以继续做其他事情
存在问题:如果主库在从库接收日志并写入relay中之后返回ACK消息时挂掉(主库没有收到ack),这时客户端接收不到成功的消息,如果这时主从故障切换,从库利用二进制回放可以看到事务提交的数据,但客户端却没有收到成功的消息,这个时候是不是从库的多了一个事务的数据。(幽灵事务)
after_commit:主库将事务修改写入二进制日志,把日志传输到从库,并继续在存储引擎层提交执行的事务,提交事务后,主库继续等待从库的ACK消息,收到ACK消息后,主库将提交结果返回给客户端,然后客户端可以继续做其他事情
存在问题:after_commit在主库等待从库发送ACK时,存储引擎层已经把事务提交,只是当前客户端看不到提交的数据(需要等待从库的ack消息),但其他客户端可以看到提交的数据。如果这时主库崩溃,而从库也没有接收binlog日志,那么会出现,其他客户端在主库看到的提交数据,故障切换后再原来的从库上又看不到数据了。出现所谓的“幻读”(丢数据了)而after_sync避免这个问题
半同步复制需要在主库和备库分别安装插件semisync_master.so和semisync_slave.so
系统变量和状态变量:
系统变量
rpl_semi_sync_master_enabled:控制是否在主库上启用半同步复制
rpl_semi_sync_slave_enabled:控制是否在从库上启用半同步复制
rpl_semi_sync_master_timeout:控制主库在超时切换到异步复制之前,等待从库返回ack消息的时间
状态变量:
rpl_semi_sync_master_clients:显示半同步复制从库的数量
rpl_semi_sync_master_status:显示当前主库半同步插件是否处于启用状态
rpl_semi_sync_master_no_tx:从库未成功确认事务的提交数
rpl_semi_sync_master_yes_tx:从库成功确认事务的提交数
rpl_semi_sync_slave_status:显示当前从库半同步复制插件是否处于启用状态
使用show variables like查看系统变量,通过show status like查看状态变量