MySQL之复制(十)

复制

改变主库

确定期望的日志位置

在这里插入图片描述

如果有备库和新主库的位置不相同,则需要找到该备库最后一条执行的时间在新主库的二进制日志中相应的位置,然后再执行CHANGE MASTER TO.可以通过mysqlbinlog工具来找到备库执行的最后一条查询,然后在主库上找到同样的查询,进行简单的计算即可得到。
为了便于描述,假设每个日志时间有一个自增的数字ID,最新的备库,也就是新主库,在旧主库崩溃时获得了编号为100的事件,假设有另外两台备库:replica2和replica3。replica2已经获取了99号事件,replica3获取了98号事件。如果把两台备库都指向新主库的同一个二进制日志位置,它们将从101号事件开始复制,从而导致数据不同步。但只要新主库的二进制日志已经通过log_slave_updates打开,就可以在新主库的二进制日志中找到99号和100号日志,从而将备库恢复到一致的状态。由于服务器重启,不同的配置,日志轮转或者FLUSH LOGS命令,同一个事件在不同的服务器上可能有不同的偏移量。找到这些事件可能会耗时很长并且枯燥,但是通常没有难度。通过mysqlbinlog从二进制日志或中继日志中解析出每台备库上执行的最后一个事件,并同样使用该命令解析新主库上的二进制日志,找到相同的查询,mysqlbinlog会打印出该事件的偏移量,在CHANGE MASTER TO命令中使用这个值。(pt-heartbeat的心跳记录能够很好地帮助你好到正在查找的事件的大约位置)
更快的方法是把新主库和停止的备库上的字节偏移量相减,它显示了字节位置的差异。然后把这个值和新主库当前二进制日志的位置相减,就可以得到期望的查询的位置。只需要验证一下就可以据此启动备库。
假设server1是server2和server3的主库,其中服务器server1已经崩溃。根据SHOW SLAVE STATUS获得Master_Log_File/Read_Master_Log_Pos的值,server2已经执行完了server1上所有的二进制日志,但server3还不是最新的数据,如图显示了这个场景(日志事件和偏移量仅仅是为了举例).正如图所示。我们可以肯定server2已经执行完主库上的所有二进制日志,因为Master_Log_File和Read_Master_Log_Pos值和server1上最后的日志位置是相吻合的,因此我们可以将server2提升为新主库,并将server3设置为server2的备库。应该在server3上为需要执行的CHANGE MASTER TO语句赋予什么样样的参数呢?这里需要做一点点计算和调整。server3在偏移量1493停止,比server2执行的最后一条语句的偏移量1582小89字节。server2正在向偏移量为8167的二进制日志写入,8167-89=8078,因此理论上我们应该将server3指向server2的日志的偏移量为8078的位置。最好去确认下这个位置附近的日志事件,以确定在该位置上是否是正确的日志事件,因为可能有别的例外,例如有些更新可能只发生在server2上。假设我们光查到的事件是一样的,下面这条命令会将server3切换为server2的备库。

server2>CHANGE MASTER TO MASTER_HOST="server2",MASTER_LOG_FILE="mysql-bin.000009", MASTER_LOG_POS=8078;

如果服务器在它崩溃时已经执行完成并记录了超过一个事件,会怎样呢?因为server2仅仅读取并执行到了偏移量1582,你可能永远地失去了一个事件。但是如果老主库的磁盘没有损坏,仍然可以通过mysqlbinlog或者从日志服务器的二进制日志中找到丢失的事件。
如果需要从老朱库上恢复丢失的事件,建议在提升新主库之后且在允许客户端连接之前做这件事情,这样就无须再每台备库上都执行丢失的事件,只需要使用复制来完成。但如果崩溃的老主库完全不可用,就不得不等待,稍后再做这项工作。
上述流程中一个可调整的地方是使用可靠的方式来存储二进制日志,如SAN或分布式复制数据库设备(DRBD).即使主库完全失效,依然能够获得它的二进制日志。也可以设置一个日志服务器,把备库指向它,然后让所有备库赶上主库失效的点。这使得提升一个备库为新的主库没那么中国要。本质上这和计划中的提升是相同的。(当提升一台备库为主库时,千万不要将它鞥多服务器ID修改成源主库的服务器ID,否则将不能使用日志服务器从一个旧主库来重放日志事件。这也是确保服务器ID最好保持不变的原因之一)

在一个主-主配置中交换角色

主-主复制拓扑结构的一个好处就是可以很容易地切换主动和被动的角色,因为其配置是对称的。当在主-主配置下切换角色时,必须确保任何时候只有一个服务器可以写入。如果两台服务器交叉写入,可能会导致写入冲突。换句话说,在切换角色后,原被动服务器不应该接收到主动服务器的任何二进制日志。可以通过确保原被动服务器的复制SQL线程在该服务器可写之前已经赶上主动服务器来避免。通过以下步骤切换服务器角色,可以避免更新冲突的危险:

  • 1.停止主动服务器上的所有写入
  • 2.在主动服务器上执行SET GLOBAL read_only=1,同时在配置文件里也设置以下read_only,防止重启后失效。但记住这不会阻止拥有超级权限的用户更改数据。如果想阻止所有人更改数据,可以执行FLUSH TABLES WITH READ LOCK。如果没有这么做,你必须kill所有的客户端连接以保证没有长时间运行的语句或者未提交的事务
  • 3.在主动服务器上执行SHOW MASTER STATUS并记录二进制日志坐标
  • 4.使用主动服务器上的二进制日志坐标在被动服务器上执行SELECT MASTER _POS_WAIT().该语句将阻塞住,直到复制跟上主动服务器
  • 5.在被动服务器上执行SET GLOBAL read_only=0,这样就变换成主动服务器。
  • 6.修改应用的配置,使其写入到新的主动服务器中

可能还需要做一些额外的工作,包括更改两台服务器的IP地址,这取决于应用的配置

复制的问题和解决方案

中断MySQL的复制并不是件难事,因为实现简单,配置相当容易,但也意味着有很多的方式导致复制停止,现如混乱并中断。

数据损坏或丢失的错误

由于各种各样的原因,MySQL的复制并不能很好地从服务器崩溃、掉电、磁盘损坏、内存或网络错误中恢复。遇到这些问题时几乎可以肯定都需要从某个点开始重启复制。大部分由于非正常关机后导致的复制问题都是由于没有把数据及时地刷到磁盘。下面是意外关闭服务器时可能会碰到的情况.

  • 1.主库意外关闭
    如果没有设置主库的sync_binlog选项,就可能在崩溃前没有将最后的几个二进制日志事件刷新到磁盘中。备库IO线程因此也可能一直处于读不到尚未写入磁盘的事件的状态中。当主库重新启动时,备库将重连到主库并在此尝试去读该事件,但主库会告诉备库没有这个二进制日志偏移量。二进制日志转储线程通常很快,因此这种情况步经常发生。解决这个问题的方法是指定备库从下一个二进制日志的开头读日志。但是一些日志事件将永久地丢失,建议使用Percona Toolkit中的pt-table-checksum工具来检查主备一致性,以便于修复。可以通过在主库开启sync_binlog来避免事件丢失。即使开启了sync_binlog.MyISAM表的数据仍然可能在崩溃的时候损坏,对于InnoDB事务,如果innodb_flush_log_at_trx_commit没有设为1,也可能丢失数据(但数据不会损坏)
  • 2.备库意外关闭
    当备库在一次非计划中的关闭后重启时,会去读master.info文件以找到上次停止复制的位置。不幸的是,该文件并没有同步写到磁盘,文件中存储的信息可能是错误的。备库可能会尝试重新执行一些二进制日志事件,这可能会导致唯一索引错误。除非能确定备库在哪里停止(通常不太可能),否则唯一的办法就是忽略那些错误。Percona Toolkit中的pt-slave-restart工具可以帮助完成这一点。如果使用的都是InnoDB表,可以在重启观察MySQl错误日志。InnoDB在恢复过程中会打印出它的恢复点的二进制日志坐标。可以使用这个只来决定备库指向主库的偏移量。Percona Server提供了一个新的特性,可以在恢复的过程中自动将这些信息提取出来,并更新master.info文件,从根本上使得复制能够协调好备库上的事务。MySQL5.5也提供了一些选项来控制i如何将master.info和其他文件刷新到磁盘,这有助于减少这些问题。

除了由于MySQL非正常关闭导致的数据丢失外,磁盘上的二进制日志或终极日志文件损坏并不罕见,下面是一些更普遍的场景:

  • 1.主库上的二进制日志损坏。
    如果主库上的二进制日志损坏,除了忽略损坏的位置外你别无选择。可以在主库上执行FLUSH LOGS命令,这样主库会开始一个新的日志文件,然后将备库指向该文件的开始位置。也可以试着去发现损坏区域的结束位置。某些情况下可以通过SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1来忽略一个损坏的事件。如果有多个损坏的事件,就需要重复该步骤,直到跳过所有损坏的事件。但如果有太多的损坏事件,这么做可能就没有意义了。损坏的事件会阻止服务器找到下一个事件。这种情况下,可能不得不手动地去找到下一个完好地事件。
  • 2.备库上的中继日志损坏
    如果主库上的日志是完好的,就可以通过CHNAGE MASTER TO命令丢弃并重新获取损坏的事件。只需要将备库指向它当前正在复制的位置(Relay_Master_Log_File/Exec_Master_Log_Pos)这会导致备库丢弃所有在磁盘上的中继日志。就这一点而言,MySQL5.5做了一些改进,它能够在崩溃后自动重新获取中继日志。
  • 3.二进制日志与InnoDB事务日志不同步
    当主库崩溃时,InnoDB可能将一个事务标记为已提交,此时盖世五可能还没有记录到二进制日志中,除非是某个备库的中继日志已经保存,否则没有任何办法恢复丢弃的事务。在MySQL5.0版本可以设置sync_binlog选项来防止该问题,对于更早的MySQL4.1可以设置sync_binlog和safe_binlog选项
  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coffee_babe

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值