MySQL 的主从复制依赖于 binlog ,也就是记录 MySQL 上的所有变化并以二进制形式保存在磁盘上。复制的过程就是将 binlog 中的数据从主库传输到从库上。
这个过程一般是异步的,也就是主库上执行事务操作的线程不会等待复制 binlog 的线程同步完成。还有另外两种模式:半同步复制(需要一个从库返回响应才能给客户端返回写入成功)和同步复制(所有从库都返回响应才能给客户端返回写入成功)
以异步过程为例,流程大概是这个样子的,有需要高清图的可以私信我
MySQL 集群的主从复制过程梳理成 3 个阶段:
- 写入 Binlog:主库写 binlog 日志,提交事务,并更新本地存储数据。
- 同步 Binlog:把 binlog 复制到所有从库上,每个从库把 binlog 写到暂存日志中。
- 回放 Binlog:回放 binlog,并更新存储引擎中的数据。
具体详细过程如下:
- MySQL 主库在收到客户端提交事务的请求之后,会先写入 binlog,再提交事务,更新存储引擎中的数据,事务提交完成后,返回给客户端“操作成功”的响应。
- 从库会创建一个专门的 I/O 线程,连接主库的 log dump 线程,来接收主库的 binlog 日志,再把 binlog 信息写入 relay log 的中继日志里(追加写入),再返回给主库“复制成功”的响应。
- 从库会创建一个用于回放 binlog 的线程,去读 relay log 中继日志,然后回放 binlog 更新存储引擎中的数据,最终实现主从的数据一致性。
在完成主从复制之后,你就可以在写数据时只写主库,在读数据时只读从库,这样即使写请求会锁表或者锁记录,也不会影响读请求的执行。
主从复制的模型主要有三种:
- 同步复制:MySQL 主库提交事务的线程要等待所有从库的复制成功响应,才返回客户端结果。这种方式在实际项目中,基本上没法用,原因有两个:一是性能很差,因为要复制到所有节点才返回响应;二是可用性也很差,主库和所有从库任何一个数据库出问题,都会影响业务。
- 异步复制(默认模型):MySQL 主库提交事务的线程并不会等待 binlog 同步到各从库,就返回客户端结果。这种模式一旦主库宕机,数据就会发生丢失。
- 半同步复制:MySQL 5.7 版本之后增加的一种复制方式,介于两者之间,事务线程不用等待所有的从库复制成功响应,只要一部分复制成功响应回来就行,比如一主二从的集群,只要数据成功复制到任意一个从库上,主库的事务线程就可以返回给客户端。这种半同步复制的方式,兼顾了异步复制和同步复制的优点,即使出现主库宕机,至少还有一个从库有最新的数据,不存在数据丢失的风险
主从复制中的关键点:
三个线程:
Log Dump线程(主库)
当从节点与主节点建立连接之后,主节点会为从节点创建一个Log Dump线程,用来监听Binlog的变化,如果有变化会将新增的部分发送给从节点
I/O线程(从库)
从节点和主节点建立连接之后,从节点会开启一个I/O线程,用来接收主节点的Log Dump线程发送的binlog,I/O线程接收到binlog之后会把它追加写入到Relay Log
SQL线程(从库)
SQL线程读取Relay log的文件内容,并进行SQL重放,维护数据一致性
重要的两个日志:
Binlog
Binlog以事件形式记录了对MySQL数据库执行的所有更改操作(写操作)
Relay log
用来保存从节点IO线程接收到的Binlog日志,作为中继日志使用
GTID
MySQL的GTID(Global Transaction Identifier,全局事务标识符)是MySQL复制架构中的一个功能,用于确保数据在主从服务器之间的同步性。
GTID是一个唯一的标识符,用于标识特定的事务。在MySQL复制架构中,每个事务都被分配一个唯一的GTID,这使得在主服务器和从服务器之间的复制中,可以轻松地识别哪些事务已经被复制,哪些尚未被复制。
使用GTID还可以使得在进行主从切换时,从服务器可以自动找到正确的位置来恢复复制。此外,GTID还可以用于在多主复制环境中解决冲突,从而提高系统的可靠性和可用性。
总的来说,GTID是MySQL复制架构中一个非常有用的功能,可以提高系统的可靠性和可维护性。