MySQL实现主从复制的原理详解
作者:DannyIdea
主从复制是怎么实现的呢?
当MySQL数据库发生写操作的时候会记录下binlog,它是一种逻辑日志。有了这个 binlog,从服务器会获取主服务器的 binlog 文件,然后解析里面的 SQL 语句,在从服务器上面执行一遍,保持主从的数据一致。
这里面涉及到三个线程:
IO线程
连接到 master 获取 binlog,并且解析 binlog 写入中继日志,这个线程叫做 I/O 线程。
log dump线程
master 节点上有一个 log dump 线程,是用来发送 binlog 给 slave 的。
sql线程
从库的 sql 线程,是用来读取 relay log,把数据写入到数据库的。
主从复制的方式
异步复制
在异步复制中,主库执行完操作后,写入binlog日志后,就返回客户端,这一动作就结束了,并不会验证从库有没有收到,完不完整,所以这样可能会造成数据的不一致。
说到底,复制过程中数据是否一致,主要取决于Binlog日志的安全性与完整性
在MySQL中,有sync_binlog=n这一参数,他的值表示每进行n次事务提交,MySQL就将Binlog刷新到磁盘。如果这个值为1,就代表每提交一次事务(SQL),就将Binlog往磁盘刷新一次,这样一来,就算数据库宕机了,那么最多只能损失一次事务的数据。
但是,一旦多个事务并发提交时,由于受sync_binlog的限制,MySQL只能按顺序来处理这些请求,另外,高频率的刷新binlog对IO的影响也很大,进一步影响了数据库的性能,所以,一般这个值都设为0或者其他值,在数据的安全性和高并发下的性能之间取得一个平衡。
为了更加有效的保护Binlog的安全性和完整性,MySQL5 .5之后引入了半同步复制
半同步复制
在异步复制中,我们遇到的一个主要问题就是,在复制过程当中,主库不会去验证Binlog有没有成功复制到从库,那如果主库提交一个事务并写入Binlog中后,当从库还没有从主库得到Binlog时,主库宕机了或因磁盘损坏等故障导致该事务的Binlog丢失了,那从库就不会得到这个事务,也就造成了主从数据的不一致。
而半同步复制,当主库每提交一个事务后,不会立即返回,而是等待其中一个从库接收到Binlog并成功写入Relay-log中才返回客户端,所以这样就保证了一个事务至少有两份日志,一份保存在主库的Binlog,另一份保存在其中一个从库的Relay-log中,从而保证了数据的安全性和一致性。
另外,在半同步复制时,如果主库的一个事务提交成功了,在推送到从库的过程当中,从库宕机了或网络故障,导致从库并没有接收到这个事务的Binlog,此时主库会等待一段时间(这个时间由rpl_semi_sync_master_timeout的毫秒数决定),如果这个时间过后还无法推送到从库,那MySQL会自动从半同步复制切换为异步复制,当从库恢复正常连接到主库后,主库又会自动切换回半同步复制。
半同步复制的“半”体现在,虽然主从库的Binlog是同步的,但主库不会等待从库执行完Relay-log后才返回,而是确认从库接收到Binlog,达到主从Binlog同步的目的后就返回了,所以从库的数据对于主库来说还是有延时的,这个延时就是从库执行Relay-log的时间。所以只能称为半同步。
总之这两种策略,可以浓缩理解为,一个是“不管不问”,一个是“确认到位就跑”。
读写分离
做了主从复制的方案之后,我们只把数据写入 master 节点,而读的请求可以分担到slave 节点, 这种方案我们称之为读写分离。
读写分离可以一定程度低减轻数据库服务器的访问压力,但是需要特别注意主从数据一致性的问题。
我们在做了主从复制之后,如果单个 master 节点或者单张表存储的数据过大的时候,比如一张表有上亿的数据,单表的查询性能还是会下降,我们要进一步对单台数据库节点的数据进行拆分,而这个拆分就是分库分表。
常见的分库分表策略
垂直分库
把一个数据库按照业务拆分成不同的数据库:
水平分库分表
把单张表的数据按照一定的规则分布到多个数据库。
到此这篇关于MySQL实现主从复制的原理详解的文章就介绍到这了,更多相关MySQL 主从复制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!