ITPub博客

【MySQL】MySQL5.6新特性之crash-safe

原创 作者:杨奇龙 时间:2015-07-26 23:46:54 0 删除 编辑
<span style="font-family:SimSun;font-size:14px;"><strong>一 介绍</strong></span><br /> <span style="font-family:SimSun;">&nbsp; </span><span style="font-family:SimSun;">MySQL 5.6 针对复制功能提供了新特性: slave支持crash-safe. 该功能可以解决之前版本中系统异常断电可能导致的SQL thread 信息不准确的问题。本文从原理方面对该特性进行介绍。</span><br /> <span style="font-family:SimSun;font-size:16px;"><strong>二 原理</strong></span><br /> <span style="font-family:SimSun;">&nbsp; 在了解crash-safe slave 之前,我们先分析一下MySQL 5.6 之前的版本出现 crash-unsafe 的原因。在slave上,复制包含两个线程:即replication中的IO thread和SQL thread。</span><br /> <span style="font-family:SimSun;">IO thread负责从master拷贝binlog文件并保存到本地,拷贝过来的binlog称为relay-log.&nbsp;</span><br /> <span style="font-family:SimSun;">SQL thread负责执行relay-log.</span><br /> <span style="font-family:SimSun;">两个线程的执行进度(偏移量)都保存在文件中.IO thread的执行状态信息保存在master.info文件,SQL thread的执行状态信息保存在relay-log.info文件。系统运行正常的情况下,这种模式到目前为止还没有问题。</span><span style="font-family:SimSun;">需要注意的是这些文件被修改后不是同步写入磁盘的,每当系统发生crash,存储的偏移量可能都不准确.MySQL 5.5通过两个参数修复了该问题,使用sync_master_info=1和sync_replay_log_info=1 来保证Slave 的两个线程每次写一个事务就分别向两个文件同步一次 IO thread和SQL thread当前执行的信息。当然同步操作不是免费的,频繁更新磁盘文件需要消耗性能,如果你的RAID设备的IO策略设置为WRITEBACK 模式,那么这种方法便可以接受的。</span><br /> <span style="font-family:SimSun;">&nbsp;但是,即使设置了sync_master_info=1和sync_relay_info=1, 问题还是会出现,因为复制信息是在transactions提交后写入的,如果crash发生在事务提交和OS写文件之间,那么relay-log.info就可能是错误的。当slave从新启动的时候,最后那个事务可能会被执行两次.具体的影响取决于事务的具体操作.复制可能会继续运行比如update/delete,或者报错 比如insert操作,此时主从数据的一致性可能会被破坏。</span><br /> <span style="font-family:SimSun;">&nbsp;MySQL 5.6版本通过将复制信息存放到表中来解决此问题.通过配置两个参数 relay_log_info_repository=TABLE,master_info_repository=TABLE,relay log info 会存放到 mysql.slave_relay_log_info表中,master info 会存放mysql.slave_master_info表中。就是把SQL线程执行事务和更新mysql.slave_replay_log_info的语句看成一个事务处理,这样就会一直同步的.</span><br /> <span style="font-family:SimSun;">我们可以通过伪代码来了解crash-safe 的原理</span><br /> <span style="font-family:SimSun;">crash-unsafe情况下 SQL_thread 的 的工作模式</span><br /> <div id="codeText" class="codeText"> <ol style="margin:0 1px 0 0;padding:5px 0pt;" start="1" class="dp-css none_number"> <li> <span style="color:#000000;">START TRANSACTION<span style="color:#0000CC;">;</span><br /> </span> </li> <li> &nbsp;Statement 1<br /> </li> <li> &nbsp;&nbsp;<span style="color:#0000CC;">.</span><span style="color:#0000CC;">.</span><span style="color:#0000CC;">.</span><br /> </li> <li> &nbsp;Statement N<br /> </li> <li> &nbsp;COMMIT<span style="color:#0000CC;">;</span><br /> </li> <li> Update replication info files </li> </ol> </div> <span style="font-family:SimSun;">crash-safe情况下 SQL_thread 的 的工作模式</span><br /> <div id="codeText" class="codeText"> <ol style="margin:0 1px 0 0;padding:5px 0pt;" start="1" class="dp-css none_number"> <li> <span style="color:#000000;">START TRANSACTION<span style="color:#0000CC;">;</span><br /> </span> </li> <li> &nbsp;&nbsp;Statement 1<br /> </li> <li> &nbsp;&nbsp;<span style="color:#0000CC;">.</span><span style="color:#0000CC;">.</span><span style="color:#0000CC;">.</span><br /> </li> <li> &nbsp;&nbsp;Statement N<br /> </li> <li> &nbsp;&nbsp;Update replication info<br /> </li> <li> COMMIT </li> </ol> </div> <span style="font-family:SimSun;">crash-safe就是将relay-info.log的信息保存在InnoDB的事务表中,这时执行relay log中的事务和写relay info在一个事务中,就能得到原子性保证。从而避免已执行的binlog位点和写入relay log info 的位点信息不一致的情况发生。看到这里也请各位读者思考一下 ,现在的这种方案是否完美,有哪些问题?</span><br /> <span style="font-family:SimSun;">&nbsp;从上面的改变解决了SQL thread记录执行状态可能导致不一致的风险,但是对于IO thread 依然存在问题 。IO thread 从master上拷贝binlog写入 relay log中,每个二进制日志由多个log event组成,所以每接收到一个log event就需要更新master-info.log而且该是写入操作系统缓存。从IO thread的工作原理来看,它没有办法 将写入master info和拉取binlog放到同一个事务中而保持原子操作,因此IO thread 的行为是会对数据一致性会产生影响,设想一个log event传送到了relay log中两次的情形。</span><span style="font-family:SimSun;">如何解决呢? <br /> &nbsp;方案一 通过参数sync_master_info可以控制fdatasync的时间。默认值是10000,表示IO线程的偏移量每10000个事务更新一次 ,通过设置其为1,每写一次事务便同步到master.info 。<br /> &nbsp;方案二 通过MySQL 5.5版本开始提供的参数relay_log_recovery ,当slave发生crash后重启之后重连master时,slave不根据master-info.log的信息进行重连,而是根据relay-info中执行到master的位置信息重新开始拉master上的日志数据。</span><br /> <br /> <strong><span style="font-size:16px;">三 如何使用&nbsp;</span></strong><br /> &nbsp; 1 停止slave的mysql实例<br /> &nbsp; 2 my.cnf文件中添加<br /> &nbsp; &nbsp; &nbsp;master-info-repository=TABLE<br /> &nbsp; &nbsp; &nbsp;relay-log-info-repository=TABLE<br /> &nbsp; &nbsp; &nbsp;relay-log-recovery<br /> &nbsp; 3 重启slave的mysql实例<br /> 注意:<br /> 如果是MySQL 5.6.5 或者更早期。slave_master_info 和 slave_relay_log_info 表默认使用MyISAM 引擎。所以还得修改成innodb,如下: &nbsp; &nbsp; &nbsp; &nbsp;<br /> <div id="codeText" class="codeText"> <ol style="margin:0 1px 0 0;padding:5px 0pt;" start="1" class="dp-css none_number"> <li> <span style="color:#000000;">ALTER TABLE mysql<span style="color:#0000CC;">.</span>slave_master_info ENGINE<span style="color:#0000CC;">=</span>InnoDB<span style="color:#0000CC;">;</span> <br /> </span> </li> <li> ALTER TABLE mysql<span style="color:#0000CC;">.</span>slave_relay_log_info ENGINE<span style="color:#0000CC;">=</span>InnoDB </li> </ol> </div> <strong><span style="font-size:16px;">四 小结&nbsp;</span></strong><br /> &nbsp; &nbsp;MySQL 5.6 版本为MySQL的稳定性做出了很多改进,这点值得MySQL DBA 去关注,也值得大家去思考,这些改善点还有那些不足之处?有如何解决?<br /> <br /> <strong><span style="font-size:16px;">五 参考文章</span></strong><br /> &nbsp;1&nbsp;<a href="http://dev.mysql.com/doc/refman/5.6/en/slave-logs.html" target="_blank">MySQL 5.6 Manual --slave logs</a>&nbsp;&nbsp;<br /> &nbsp;2&nbsp;<a href="http://insidemysql.sinaapp.com/article/34.html" target="_blank">MySQL crash-safe replication</a>&nbsp;&nbsp;<br /> &nbsp;3&nbsp;<a href="https://www.percona.com/blog/2013/09/13/enabling-crash-safe-slaves-with-mysql-5-6/" target="_blank">Enabling crash-safe slaves with MySQL 5.6</a>&nbsp;<br /> &nbsp;4&nbsp;<a href="http://hcymysql.blog.51cto.com/5223301/1615751" target="_blank">MySQL5.6 crash-safe replication一个坑</a><br /> &nbsp;5&nbsp;<a href="http://mysqlmusings.blogspot.com/2011/04/crash-safe-replication.html" target="_blank">Crash-safe Replication</a>&nbsp;--推荐<br /> &nbsp;6&nbsp;<a href="http://blog.booking.com/better_crash_safe_replication_for_mysql.html" target="_blank">Better Crash-safe replication for MySQL<br /> <br /> </a><span style="color:#666666;font-family:宋体, Arial;line-height:26px;white-space:normal;background-color:#FFFFFF;">如果您觉得从这篇文章受益,可以赞助&nbsp;</span><strong style="color:#666666;font-family:宋体, Arial;line-height:26px;white-space:normal;background-color:#FFFFFF;"><u><span style="font-size:14px;">北在南方</span></u></strong><span style="color:#666666;font-family:宋体, Arial;line-height:26px;white-space:normal;background-color:#FFFFFF;">&nbsp;一瓶饮料 ^_^</span><a href="http://blog.booking.com/better_crash_safe_replication_for_mysql.html" target="_blank"><br style="color:#666666;font-family:宋体, Arial;line-height:26px;white-space:normal;background-color:#FFFFFF;" /> </a><img src="http://blog.itpub.net/attachment/201509/15/22664653_1442320801pGpV.jpg" width="571" height="518" alt="" style="color:#666666;font-family:宋体, Arial;line-height:26px;white-space:normal;background-color:#FFFFFF;" /><br />
请登录后发表评论 登录
全部评论
MySQL DBA NoSQL DEVOPS

注册时间:2009-10-07

  • 博文量
    1016
  • 访问量
    7392320