天天看点

关闭删库跑路的后门,打造高可用的MySQL(下)2 最佳实践3 打造高可用的MySQL

1.2.1.3 查看状态

  • show master status
  • 关闭删库跑路的后门,打造高可用的MySQL(下)2 最佳实践3 打造高可用的MySQL
  • 显示正在写入的Binlog文件,及当前的位置。

    假设我们每天凌晨用mysqldump做一个全量备份,然后开启了Binlog,有了这些,就可以把数据恢复到全量备份之后的任一时刻。

用Binlog把数据恢复到删库跑路之前的那个时刻:

$mysqlbinlog --start-datetime "2020-05-16 00:00:00" 
--stop-datetime "2020-05-16 18:00:00" 
/usr/local/var/mysql/binlog.000001 | mysql -uroot      

这时候,数据已经恢复到当天的18点了。

定期的全量备份 + Binlog,就可以把数据恢复到任一历史时间点。

2 最佳实践

无论全量备份还是Binlog,都不要和数据库存放在同一服务器

在回放Binlog时,指定的起始时间可以比全量备份的时间稍微提前,确保全量备份之后的所有操作都在恢复的Binlog范围内,保证恢复的数据的完整性。

因为回放Binlog操作是幂等的(需要设置Binlog为ROW格式),所以重复回放的那部分Binlog并不会影响数据的准确性。

3 打造高可用的MySQL

恢复数据时间很长,这期间系统一直不可用,怎么搞?

不要等着数据库宕机,才开始做恢复,平时就要恢复。

3.1 异步复制

一主一从,性能佳。

实时地在主备数据库之间来同步Binlog,主库做了一次数据变更,生成一条Binlog,我们就把这一条Binlog复制到备用库并立即回放,这样就可以让备用库里面的数据和主库中的数据一直保持是一样的。一旦主库宕机,就可以立即切换到备用库上继续提供服务。

MySQL本身提供了主从复制

https://dev.mysql.com/doc/refman/8.0/en/replication.html

方案的问题。当我们对主库执行一次更新操作的时候,主从两个数据库更新数据实际的时序是这样的:

在主库的磁盘上写入Binlog

主库更新存储引擎中的数据

给客户端返回成功响应

主库把Binlog复制到从库

从库回放Binlog,更新存储引擎中的数据。

主从延迟

从库的数据有可能比主库上的数据旧。

正常情况下,主从延迟基本都是毫秒级别,可认为就是实时保持同步。

不正常的,一旦主库或者从库繁忙的时候,会出现明显的主从延迟。

很多情况下,数据库都不是突然宕机的,而是先繁忙,性能下降,最终宕机。这种情况下,很有可能主从延迟很大,如果我们把业务直接切到从库上继续读写,主从延迟这部分数据就丢了,并且这个数据丢失是不可逆的。即使事后你找回了当时主库的Binlog也是没法做到自动恢复的,因为它和从库的数据是冲突的。

简单地说,如果主库宕机并且主从存在延迟的情况下,切换到从库继续读写,可以保证业务的可用性,但是主从延迟这部分数据就丢失了。

这个时候你就需要做一个选择题了

保证不丢数据,牺牲可用性,暂时停止服务,想办法把主库的Binlog恢复到从库上之后再提供服务

冒着丢一些数据的风险,保证可用性,第一时间切换到从库继续提供服务

能不能既保证数据不丢,还高可用?

3.2 同步复制

自动切换,性能最差。

MySQL支持

同步复制

,开启同步复制时,MySQL主库会等待数据成功复制到从库之后,再给客户端返回响应。

一主一从的隐患

从库宕机了怎么办?本来从库宕机对主库是完全没影响的,因为现在主库要等待从库写入成功再返回,从库宕机,主库就会一直等待从库,主库也卡死了。

一主双从

得加一个从库,主库配置成:成功复制到任意一个从库就返回,只要有一个从库还活着,就不会影响主库写入数据,这样就解决了从库宕机阻塞主库的问题。

如果主库发生宕机,在两个从库中,至少有一个从库中的数据是和主库完全一样的,可以把这个库作为新的主库,继续提供服务。

代价

至少用三台数据库服务器,但这三台的服务性能,还不如一台。