MySQL 高可用 - 复制

“可用”就是指系统是否可用;“高”往往是一个百分比,指系统可用占比。毕竟有可能出现故障或者宕机。高可用分为计算和存储高可用。计算高可用有(主备、主从、对称集群、非对称集群)几种模式,存储高可用有(主备、主从、主备/主从切换、主主、集群、分区)几种模式。
MySQL的复制功能是构建高可用应用的基础,复制也是可扩展性、灾难恢复、备份、数据仓库等工作的基础。

复制的应用

数据分布:通过复制将数据分布到不同的地理位置做备份
负载均衡:通过复制将读操作分布备机或者其他服务器上,实现对读密集应用的优化
备份:复制也是备份的技术实现之一
高可用和故障切换:复制为高可用实现技术支持,在出现故障时可以切换到备机上
MySQL 升级测试:使用高版本作为备库时,保证在升级实例前查询能够在备库上按照预期执行

复制的原理

MySQL复制
MySQL复制
  1. 在主库上把数据更改记录到二进制日志(Binary Log)中:在提交事务完成数据更新前,主库将数据更新的事件记录到二进制日志中,MySQL会按照事务提交的顺序而不是每条语句执行的顺序来记录二进制日志,在记录日志后主库通知存储引擎提交事务
  2. 备库将主库上的日志复制到自己的中继日志(relay Log):备库上启动工作线程(I/O线程),与主库建立客户端连接。然后在主库上启动一个二进制转储线程(该线程没有对应的 SQL 命令),二进制转储线程会读取主库上的二进制日志中的事件,不对事件进行轮询处理。如果转储线程进度追赶上主库的更新速度,他将进入睡眠状态,直到主库发送信号量通知转储线程有新的二进制日志产生,转储线程会继续工作。I/O 线程将接收到的二进制日志写入到备库的中继日志中
  3. 备库读取中继日志中的事件,将其重放到备库数据库上:备库 SQL 线程读取中继日志中的事件并在备库上执行,实现备库的数据更新。当 SQL 线程追赶上 I/O 线程,中继日志已经在系统缓存中,此时开销就比较低。SQL 线程也可以通过配置决定是否将操作日志写到自己的二进制日志中

复制实现方式

基于语句的复制

基于语句复制也称为逻辑复制,在这种模式下主库会记录造成数据更改的 SQL,备库会读取并重放这些事件(重新执行主主库记录的 SQL)。

优点
  • 记录和执行都比较简单
  • 二进制事件更加紧凑
  • 基于语句的模式占用带宽较小
缺点
  • 主库数据的更新,除了 SQL 语句,可能还有其他因素。例如:使用了时间戳函数可能导致主备库插入的时间不一样;使用了 CURRENT_USER() 函数等
  • 更新必须是串行的,需要加锁来处理

基于行的复制

将实际数据记录在二进制日志中

优点
  • 记录实际数据可以保证主备的数据是一致的
  • 备库无需重放主库的查询语句,例如下面语句,如果使用基于语句复制则会导致备库也有很大开销
1
INSERT INTO TEST_TABLE(col1, col2, col3) SELECT col1, col2, sum(col3) FROM table2 GROUP BY col1, col2;
缺点
  • 有导致全表记录修改的 SQL,此时主库的日志记录和备库的数据复制开销都很大
  • 基于行复制时,如果需要进行时间点恢复比较困难

这两种模式都不是完美的,MySQL 可以在两种模式下切换,默认是基于语句的复制,当发现语句不能被正确复制时使用基于行的复制。