MySql 笔记三主从复制、持久化及集群数据一致性

MySql 笔记(三)主从复制、持久化及集群数据一致性

主从复制

  • 小数据量的时候我们一般使用Mysql都是单机的,而当数据并发量过大时单机就会承受不住这么大的压力,从而使的Mysql宕机,并且单机也并不能支撑系统的高可用性,这个时候,就需要对Mysql使用集群,那么对于Mysql而言,使用集群一般使用一主多从的方式进行的,一个master负责写,多个slaves负责读,这样既能将压力分担到各个机器上,即使有某台机器宕机了,依然可以使用其他的机器提供服务。并且需要更高的性能的话,只要再增加机器进行横向扩展就行了。那么,它又是怎么样进行主从服务器之间的数据同步的呢?
  • 服务器上的从mysql会开启一个IO线程去向master请求当前数据变化的binlog,每一个slave都会将master上的binlog完整的复制过来,写到自己的relay log中去,并且还会有一个SQL线程去定时的检查relay log,如果有新增的内容,就会把该SQL语句在自己的机器上也执行一遍,来实现主从同步。

持久化

简介:

  • 在Mysql中,我们调用接口写入数据成功时,并不是直接将原始数据持久化到磁盘,而是把数据放到一个数据页内存中,后面会异步的将数据刷入磁盘,并会将产生的日志先持久化到磁盘,这样的做的效率会更高,那么,为什么这么做会更加高效呢?
  • 我们之前有了解过,在使用innodb引擎进行存储的时候,聚集索引是数据直接存储在叶子结点下的,当插入数据的时候,新插入数据可能还会要调整原来的数据的位置,并不是直接插在原数据后面,这样的话会比较消耗性能。但是如果是使用日志记录的话,它日志是直接在后面追加的,顺序存储,效率会更高。

那么下面看看mysql中的这两种日志:

1.binlog

  • binlog是Mysql server层的日志,无论使用什么引擎都都binlog日志,除非关闭binlog日志记录。它是一个逻辑日志,相当于存储的就是一条sql语句的原始逻辑。
  • 并且它是使用追加的方式在后面进行顺序存储的,效率较高。当日志文件达到一定的大小以后就会开启另外一个日志文件来写日志。
  • mysql的主从复制就是通过binlog来进行的。
  • 它是没有保证crash-safe能力的。

2.redo log:

  • redo log也叫重做日志,是用来实现事务的持久性的。
  • 它和binlog不同的是,它是专属于innodb引擎的,它是一个物理日志,记录的是在某一个数据也上做了什么修改,所以说,它并不具有单独恢复数据的能力,它需要通过和数据页搭配才能恢复数据。
  • 并且它也是以顺序的方式进行存储的,但是和binlog 的区别就是,当redo log并不会新开一个文件,它会一直在原有的文件上进行覆盖写入。

Mysql双一操作,它是保证数据安全性的必须要设定的参数:

为了保证数据的安全性,防止出现数据丢失的情况,这两个参数是一定要设置成1的,因为数据页的写磁盘是异步的,在提交事务之后数据页不一定被持久化了,但是记录它的log是要被持久化的,不然如果在提交事务后出现了Mysql宕机,而日志和数据页都没有写入磁盘,那么这个数据就没有办法进行恢复,就出现数据丢失的情况了。

  1. sync_binlog=1,这个binlog在每一次写的时候都会直接刷到磁盘中去。
  2. innodb_flush_log_at_trx_commit=1,这个表示每个事务在完成提交的时候,log_buffer都会放到log_file文件中去,并主动去进行一次刷盘。

WAL(Write Ahead Log):

  1. 数据在持久化之前先写日志
  2. 在innodb中,redo log就是典型的WAL,先写数据到内存数据页,再写redo log,再持久化数据

Mysql集群数据一致性

要说集群Mysql集群数据一致性的原理,首先要先了解一下数据同步在提交时走过的流程。

  1. 主节点进行增删改等操作时,会顺序写入binlog中。
  2. 每一个从库,在主库中都有一个binlog dump线程对应它,在主节点binlog发生变化的时候,所有的dump线程都会去吧数据推送给从库。
  3. 从库的IO线程接收到binlog后,就会写入本地的relaylog中。
  4. 从库的SQL线程读取relaylog中新写入的log,根据log也执行一遍数据库操作。

对于单机的Mysql而言,我们可以设置双一操作,是的binlog redolog在每次事务提交完成前将其持久化到磁盘中,这样就能保证即使crash也不会异常丢失数据了。

而在Mysql的集群中,想要保证主备数据的一致性并不是一件容易的事,下面是Mysql的复制的三种方式:

  1. 异步复制
    异步复制是默认的同步方式,性能也是最好的,而异步复制的意思就是,主库在执行事务的提交过程中会给从库发送binlog数据,然后直接返回,并不会等待从库的收到binlog的确认回应。因此这就存在一种问题,主库在提交事务完成以后并不知道从库是否已经同步数据,那么如果事务已经提交,而数据还没有同步到从库的时候主库就crash了,然后发生了主备切换,新主库上的数据就是不完整的。

  2. 半同步复制
    半同步复制的意思,就是主库在应答客户端的事务请求前,首先要确保至少有一个从库接收到binlog并且写入到relaylog中去,其实就是在事务提交的过程中,在binlog写入后和事务提交返回前,会先将binog发送给从库并且需要等待从库的ACK回应。
    这里的等待ack回应有两种时机可以进行选择:

    (1)rpl_semi_sync_master_wait_point 设置为WAIT_AFTER_COMMIT,那么便是binlog写入、engine层commit之后,事务返回之前进行等待从库的ACK回应。

    这样依然是有问题的,因为engine层commit之后,事务便对外可见了,这时就可以读到数据,可是如果在等待从库回应前主库就已经crash了,而从库又没有收到binlog,并提升为新主库,那么老主库上已经提交的数据在新的主库上就找不到了。

    如果说老主库没有办法进行恢复的话,这条数据就会被永久丢失了。

    (2)rpl_semi_sync_master_wait_point 设置为WAIT_AFTER_SYNC,这样的话等待的时机是在binlog写入之后,engine层commit之前。

    相对于上面的那种做法,至少就不会出现之前还能读出数据,主库crash重新切换后就读不到数据的情况了。但是这样依旧没有办法保证主从的一致性,老主库在重启后会恢复其数据,可是新主库并不知道这条数据。

    所以如果发生了主备切换,只能回滚engine层未commit的事务。

  3. 全同步模式
    主库在执行事务提交的过程中,要等待所有从库都同步该binlog,并提交完成事务,才能给客户端返回成功。这样做的效率肯定是最低的,但是数据的可靠性也是最高的,即使是写完后在从节点上立马读也能读到数据。

相关文章

学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习...
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面...
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生...
Can’t connect to local MySQL server through socket \'/v...
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 ...
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服...