【Java劝退师】MySQL 知识脑图 - 数据库原理

960 阅读19分钟

MySQL

MySQL

数据库原理

一、优势

MySQL : 互联网企业使用第一

Oracle : 互联网之外企业使用第一

  1. 体积小、速度快
  2. 开源免费、维护成本低
  3. 易扩展、高可用

二、架构演进

1. 单机单库

瓶颈

  • 数据量 过大
  • 读/写操作量 过大
  • 可用性 差

2. 主从架构

解决 高可用、读压力 问题

瓶颈

  • 数据量 过大
  • 写操作量 过大

3. 分库分表

解决 数据量、写压力 问题

4. 云数据库

服务提供商 负责解决 可配置性、可扩展性、多用户存储结构设计 问题

三、体系架构

1. 服务层

  • 连接池 Connection Pool - 保存、管理 客户端与数据库的连接,一个线程管理一个连接
  • 系统管理和控制工具 Management Services & Utilities - 备份恢复、安全管理、集群管理
  • SQL 接口 SQL Interface - 接收来自客户端的 SQL 命令,返回结果给客户端
  • 解析器 Parser - 将 SQL 生成解析树,并检查是否合法
  • 查找优化器 Optimizer - 将解析树转换成运行计划
  • 缓存 Cache&Buffer - 将 SQL 语句与结果进行缓存,若下次查找有命中缓存则直接返回结果

2. 存储引擎层

  • 负责数据的存储与提取
  • 插件式的存储引擎,屏蔽不同引擎间的差异

3. 系统文档层

负责将 数据、日志 存储在操作系统上

  • 日志文档

    • 错误日志 -【默认】开启 - show variables like '%log_error%';

    • 通用日志 - 记录 SQL 查找语句 - show variables like '%general%';

    • 二进制日志 - 纪录 SQL 增删改语句 - 用于 数据库恢复、主从复制

      • 是否开启 - show variables like '%log_bin%';
      • 查看参数 - show variables like '%binlog%';
      • 查看日志 - show binary logs;
    • 慢查找日志 - 纪录超时 SQL 查找语句 - 【默认】10 秒

      • 是否开启 - show variables like '%slow_query%';

      • 查看时长设置 - show variables like '%long_query_time%';

  • 配置文档

    • my.cnf

    • my.ini

  • 数据文档

    • db.opt - 库默认字符集、校验规则

    • frm - 与表相关的元数据(表结构) - 每张表都有一个

    • ibd - InnoDB 表的索引和数据 - 每张 InnoDB 表都有一个

    • MYI - MyISAM 表的索引 - 每张 MyISAM 表都有一个

    • MYD - MyISAM 表的数据 - 每张 MyISAM 表都有一个

    • ibdata1 - 系统表数据、存储表元数据、Undo日志

    • ib_logfile0、ib_logfile1 - Redo 日志

  • pid 文档

    • 存储自己进程的 ID

四、查找运行机制

  1. 创建连接 - 客户端与 MySQL 创建半双工连接

    • 查看线程状态 - show processlist;

    全双工 : 能同时 发送 和 接收 数据 - 打电话

    半双工 : 同一时刻,要么发送数据,要么接收数据,不能同时 - 无线电对讲机

    单工 : 只能发送【或】只能接收数据 - 单行道

  2. 查找缓存 - 当缓存命中则直接返回结果,否则将调用语法解析器

    • SQL 语句和参数必须完全相同,才能命中缓存
    • 不能缓存情况
      • 查找语句使用 SQL_NO_CACHE
      • 查找结果数量大于 query_cache_limit
      • SQL 语句中有动态参数 - now()
    • 查找 缓存启用、大小、限制 - show variables like '%query_cache%';
    • 查找 详细缓存参数、空间 - show status like 'Qcache%';
  3. 语法解析

    1. 使用 解析器(Parser) 将 SQL 语句生成 解析树
    2. 使用 预处理器 检查 解析树 是否合法 - 数据表、数据字段 是否存在
    3. 生成 新解析树
  4. 查找优化 - 使用 查找优化器(Optimizer) 根据 解析树 生成最优计划

    • 等价变换
      • 5=5 and a>5 → a > 5
      • a < b and a = 5 → b > 5 and a = 5
    • count、min、max 函数优化
      • InnoDB引擎
        • min 函数只需要找索引最左边
        • max 函数只需要找索引最右边
      • MyISAM引擎
        • count(*) 不需要计算,直接返回
    • 提前终止查找
      • limit 获取到所需的数据,就不再往后遍历
    • in 函数排序
      • where id in (2,1,3) → where id in (1,2,3)
  5. 运行查找 - 调用查找引擎,查找引擎 调用 存储引擎 进行 SQL 查找

    • 若返回结果过多,采增量模式返回

五、存储引擎

  1. InnoDB【默认】
    • 支持 事务、外键 且 事务安全
    • 行级锁 - 支持高并发
    • 适合大量 insert、update 操作
    • 使用 聚簇索引 - 将 索引 和 数据 一同存储
    • 两个存储文档 - .frm 表结构、.ibd 索引&数据 - 单表最大支持 64 TB
  2. MyISAM
    • 不支持 事务、外键
    • 访问速度快
    • 表级锁 - 并发能力低
    • 适合大量 select 操作
    • 使用 非聚簇索引 - 索引 和 数据 分开存储
    • 三个存储文档 - .frm 表结构、.MYI 表索引、.MYD 表数据 - 单表默认支持 256 TB
  3. Memory
    • 利用内存创建表 - 访问速度非常快
    • 应用关闭,数据丢失
  4. Csv
    • 以 CSV 文档存储数据
    • 所有 Column 必须 非null
    • 不支持 索引、分区
    • 适合做 数据交换的中间表
  5. BlackHole
    • 数据只进不出,所有插入的数据都不会保存

六、InnoDB 结构

1. 内存

  1. Buffer Pool (BP) 缓冲池

    当有新的数据要写入到 Buffer Pool 时,InnoDB 会判断 Free Page 是否足够

    如果足够,就将 Free Page 从 Free List 中删除,加到 Lru List 中

    如果不足,淘汰 Lru List 末尾的 Page,释放内存空间给新的 Page

    • 使用链表结构管理 Page

    • Page 类型

      • 默认大小 16 K
      • Free Page - 未被使用过
      • Clean Page - 已被使用,但数据还未被修改
      • Dirty Page - 已被使用,数据也被修改,导致 Page数据 与 磁盘数据 产生不一致
    • 链表类型

      • Free List 空闲缓冲区 - 管理 Free Page
      • Flush List 刷盘缓冲区 - 管理 Dirty Page,按 Page 修改时间排序
      • Lru List 使用中缓冲区 - 以 midpoint 为基点,管理 Clean Page 与 Dirty Page
        • 前 63% 为 new 列表,存放常用数据

        • 后 37% 为 old 列表,存放少用数据

      脏页 既存在于 Flush List 也存在于 Lru List,链表间互不影响

    • LRU 算法

      • 普通 LRU - 末位淘汰,新数据从链表头部加入,释放时从末位淘汰
      • 改进 LRU - 新数据从 midpoint 插入,数据被访问时,将向链表头部移动,否则将逐渐向尾部移动,等待淘汰
    • 参数

      • 查看 Page 大小 - show variables like '%innodb_page_size%';

      • 查看 Buffer Pool 参数 - show variables like '%innodb_buffer%';

      【建议】innodb_buffer_pool_size 设为总内存的 60% ~ 80%

      【建议】innodb_buffer_pool_instances 设为多个,避免缓存争夺

  2. Change Buffer (CB) 写缓冲区 - 进行增删改操作时,若 BP 中没有对应的 Page 数据,将会在 CB 中做纪录,待未来数据被读取时,再将数据合并恢复到 BP 中;若 BP 中有对应数据,则直接在 BP 中更改

    • 默认占用 BP 空间 25%,最大允许 50%
    • 仅适用 非唯一普通索引 Page - 因为做唯一性校验,必须查找硬盘
  3. Adaptive Hash Index 自适应哈希索引 - 优化对 BP 查找

    • InnoDB 引擎会自动根据访问频率和模式创建 Hash 索引
  4. Log Buffer 日志缓冲区 - 保存 Redo/Undo 数据

    • Redo Log 刷盘模式 innodb_flush_log_at_trx_commit
      • 0 : 每隔 1 秒 写日志、刷盘 - 最多丢失 1 秒数据
      • 【默认】1 : 事务提交,立刻写日志、刷盘,不丢失数据 - 最安全、性能差
      • 【建议】2 : 事务提交,将 Log 写入 OS Cache,OS Cache 每隔 1 秒 刷盘

2. 硬盘

  1. Redo Log 重做日志

    • 在崩溃恢复期间,用于修复不完整的事务数据

    • 当事务开始,产生 Redo Log,事务提交时将 Redo Log 写入 Log Buffer

    • 采用顺序循环方式写入文档,写满则回溯到第一个文档,进行覆盖

    • 当事务的 Dirty Page 被写入磁盘,Redo Log 占用的空间即可被重用

    • Redo Log 为顺序写入效率高,直接将纪录写入 ibd 属于非顺序写入,效率低

    • show variables like '%innodb_log%';

  2. Undo Log 撤销日志

    • 在事务开始前,保存数据被修改前的状态,用于回滚事务

    • 逻辑日志,纪录相反的运行过程

      • delete ←→ insert
      • update → 原始数据的 update
    • 实现 MVCC(多版本并发控制) - 为其他并发事务提供旧数据进行快照读

    • show variables like '%innodb_undo%';

  3. Binlog 二进制日志

    • 纪录 表结构变更、表数据修改

    • 用于 主从复制、mysqlbinlog 工具数据恢复

    • 纪录模式

      • ROW
        • 日志记录每一行的修改【结果】
        • 优点 - 完全实现主从同步
        • 缺点 - 日志暴涨
      • STATMENT
        • 日志将 SQL 语句复制
        • 优点 - 日志量小
        • 缺点 - 少数情况导致数据不一致 - last_insert_id()、now()
      • MIXED
        • 根据 SQL 语句将以上两种模式混合使用
    • show variables like 'log_bin';

    Redo Log 与 BinLog 区别

    1. Redo Log 专属于 InnoDB;Binlog 是 MySQL 自带
    2. Redo Log 是用二进制存储的物理日志,纪录更新【结果】;Binlog 是 逻辑日志,纪录更新【过程】
    3. Redo Log 是循环写,大小固定;Binlog 追加写,不会覆盖

3. 线程

IO Thread

使用大量的 AIO 做读写处理,提高数据库性能

  • Read Thread - 负责将数据从磁盘加载到 Page - 4 个

  • Write Thread - 负责将 Dirty Page 刷新到磁盘 - 4 个

  • Log Thread - 负责将 Log Buffer(日志缓冲区) 内容刷新到磁盘 - 1 个

  • Insert Buffer Thread - 负责将 Chage Buffer(写缓冲区) 内容刷新到磁盘 - 1 个

Purge Thread

  • 回收不需要的 Undo Page (事务已提交完成)
  • show variables like '%innodb_purge_threads%';

Page Cleaner Thread

  • 负责调用 Write Thread 将 Dirty Page 进行刷盘
  • show variables like '%innodb_page_cleaners%';

Master Thread

  • InnoDB 主线程,负责调度其他线程,优先级最高
  • 每 1 秒操作
    • 调用 Log Thread,将 Log Buffer 刷新到磁盘
    • 判断 IO 压力,决定是否合并 Chage Buffer(写缓冲区)
    • 判断 Dirty Page 比例(75%),决定是否调用 Write Thread 刷新 Dirty Page 到磁盘
  • 每 10 秒操作
    • 调用 Write Thread 刷新 Dirty Page 到磁盘
    • 合并 Change Buffer(写缓冲区)
    • 调用 Purge Thread,回收 Undo Page

4. ibd 文档

Tablespace(表空间) → ibd文档 → Segment(段) → Extent(区) → Page(页) → Row(行)

Tablespace

  • 保存多个 ibd 文档

ibd 文档

  • 保存 索引 和 表纪录
  • 一个文档包含多个 Segment(段)

Segment

  • 管理多个 Extent(区)
  • 分为 Leaf node segment(数据段)、Non-leaf node segment(索引段)、Rollback segment(回滚段)
  • 一张表至少会有 1 个数据段、1 个索引段
  • 每多创建 1 个索引,就会多 2 个 Segment

Extent

  • 大小为 1M
  • 包含 64 个 Page
  • 当需要分配新资源,最小的分配单元为 Extent,而非 Page

Page

  • 大小为 16 K
  • 保存多个 Row 纪录
  • 多种类型,数据页、Undo页、系统页、事务数据页、BLOB对象页

Row

  • 字段值
  • 事务 ID (Trx id) - 与事务有关,对一条纪录有不同版本的备份
  • 字段指针 (Field pointers) - 方便获取字段值

七、索引

可以加快查找速度,但会降低增、删、改速度

InnoDB 是以 主键聚簇索引 为 叶子节点 来构建出 B+Tree 结构

InnoDB 的表必须要有聚簇索引;表没有主键,则以第一个非空 unique 字段作为聚簇索引;否则创建一个隐藏的 row-id 作为聚簇索引

1. 类型划分

  • 存储结构
    • B Tree 索引
    • Hash 索引
    • 全文索引
    • R Tree 索引
  • 应用层次
    • 普通索引
    • 唯一索引
    • 主键索引
    • 复合索引
  • 键值类型
    • 主键索引 - 索引字段 中有包含 主键 与 所有字段
    • 辅助索引(二级索引) - 索引字段中只包含 主键 与 索引字段
  • 索引与数据关系
    • 聚簇索引 - 索引 和 数据 存放在一起 - InnoDB
    • 非聚簇索引 - 索引 和 数据 未存放在一起 - MyISAM

2. 应用类型

  1. 普通索引

    • 在普通字段创建索引,没有限制

    • CREATE INDEX <索引名> ON tablename (字段名);

    • ALTER TABLE tablename ADD INDEX [索引名] (字段名);

    • CREATE TABLE tablename ( [...], INDEX [索引名] (字段名));

  2. 唯一索引

    • 与普通索引类似,但字段必须唯一,允许空值
    • CREATE UNIQUE INDEX <索引名> ON tablename (字段名);
    • ALTER TABLE tablename ADD UNIQUE INDEX [索引名] (字段名);
    • CREATE TABLE tablename ( [...], UNIQUE [索引名] (字段名)) ;
  3. 主键索引

    • 特殊的唯一索引,不允许空值
    • 每张表只能有一个主键
    • CREATE TABLE tablename ( [...], PRIMARY KEY (字段名));
    • ALTER TABLE tablename ADD PRIMARY KEY (字段名);
  4. 复合索引

    • 使用多个字段创建的索引
    • 遵循最左前缀原则
    • 复合索引相比多个单一索引开销更小
    • CREATE INDEX <索引名> ON tablename (字段名1,字段名2...);
    • ALTER TABLE tablename ADD INDEX [索引名] (字段名1,字段名2...);
    • CREATE TABLE tablename ( [...], INDEX [索引名] (字段名1,字段名2... ));

3. 原理

  1. 二分查找法

    • 有序数组中,透过对半,查找目标值

    • 优点 : 等值、范围查找优秀

    • 缺点 : 更新、添加、删除 成本高

  2. Hash 结构

    • 等值查找快速

    • 范围查找全表扫描

  3. B Tree 结构

    • 索引 和 数据 分布在整棵树
    • 每个节点可以存放多个 索引 和 数据
    • 节点中 索引 从左到右升序排列
    • 搜索 - 节点内采二分查找,未命中则进入子节点重复查找,直到叶子节点结束
  4. B+ Tree 结构【InnoDB采用】

    • 非叶子节点只保存索引
    • 叶子节点包含 索引 和 数据
    • 叶子节点间使用指针连接,提升区间访问性能
    • 进行范围查找只需定位两个节点的索引值,然后利用叶子节点指针遍历即可

八、索引分析与优化

应该关心索引是否减少需扫描的行数,而非是否使用索引

LIKE 查找时,% 在后面索引才生效

不建议在含有 NULL 的字段上使用索引,建议将字段设置默认值

1. Explain

  • select_type 查找类型

    • SIMPLE : 不包含 子查找 或 union

    • PRIMARY : 最外层查找

    • UNION : union 关键字之后的查找

    • DEPENDENT UNION : union 关键字之后的查找 且 使用外层的查找结果

    • UNION RESULT : union 的结果

    • SUBQUERY : select 的 子查找

    • DEPENDENT SUBQUERY : select 的 子查找 且 使用外层的查找结果

  • type 查找采用方式

    效率由上到下增强

    • ALL : 全表扫描

    • index : 先利用索引获取顺序,再做全表扫描

    • range : 利用索引进行范围查找

    • ref : 使用普通索引查找

    • eq_ref : 多表查找时,前表的一条纪录只能匹配后表的一条结果(表关系为一对一)

    • const : 使用 主键 或 唯一索引 做 等值查找

    • NULL : 不需访问表

  • possible_keys - 可能用到的索引

  • key - 真正用到的索引

  • row -【估算】需要扫描多少行,越少效率越高

  • key-len - 使用索引的字节数量,用于判断是否使用了全部的复合索引

  • extra

    • Using where - 回表查找
    • Using index - 查找索引即可满足需求,不用回表(覆盖索引)
    • Using filesort - 查找结果需要额外排序 - 建议优化,使用覆盖索引,直接利用索引进行排序
    • Using temprorary - 使用了临时表(涉及去重、分组)

2. 慢查找日志

开启

  • SHOW VARIABLES LIKE 'slow_query_log%'
  • SET global slow_query_log = ON;
  • SET global slow_query_log_file = 'OAK-slow.log';
  • SET global log_queries_not_using_indexes = ON; - 纪录未使用索引的 SQL,但是 slow_query_log 必须为 ON
  • SET long_query_time = 10; - 单位 秒,查找超过该时间就纪录

3. 优化

  • 提高索引过滤性 - 避免使用索引后,需扫描的行数仍然过多

  • 尽量使用覆盖索引 - 避免回表查找

  • 分页查找利用 子查找覆盖索引 优化

    • 从全表扫描变成全索引扫描

    • 遍历时不用回表

    select * from user where id>= (select id from user limit 10000,1) limit 100;

九、事务

存储引擎事务已提交,但 Dirty Page 未刷盘,靠 Redo 日志恢复事务

事务回滚,但 Dirty Page 已刷盘,靠 Undo 日志回滚事务

WAL (Write-Ahead Logging) : 先写日志,再写磁盘

1. ACID

  • 原子性 Atomicity : 操作要么都发生,要么都不发生
  • 一致性 Consistency : 数据库从一个一致状态变换到另一个一致状态
  • 隔离性 Isolation : 事务不能被其它的事务所干扰
  • 持久性 Durability : 数据的改变是永久性的

2. 隔离级别

  • 脏读 : 读取到另一个事务未提交的数据 - Read Committed 读已提交 - Oracle、SQLServer 默认

  • 不可重复读 : 读到另一个事务 update 的数据,两次读取到的数据【内容】不一样 - Repeatable Read 可重复读 - MySQL 默认

  • 幻读 : 读取到另一个事务 insert 或 update 的数据,两次读取到的数据【数量】不一样 - Serializable 串行化

3. 读、写锁的演进

  1. 全局排队

    • 完全顺序运行所有事务操作,不用加锁

    • 强一致性

    • 性能低

  2. 排他锁

    • 不同操作涉及相同的数据项时,先进入的操作使用排他锁独占数据项,阻塞其他操作

  3. 读写锁

    • 排他锁的延伸,区分读操作与写操作,读和读之间不加锁,降低阻塞范围

    • 读和写、写和读、写和写,仍会加排他锁

  4. MVCC 多版本控制

    • 允许 读和读、读和写、写和读 并行
    • 写和写 阻塞
    • 在事务运行前,使用 Undo 日志记录当前数据状态与事务号,供其他读操作读取,也能进行回滚
    • 读操作分类
      • 快照读 : 读取纪录的【快照】(历史)版本 - 不加锁
      • 当前读 : 读取纪录的【最新】版本 - 读返回的纪录会加锁,保证其他事务不会并发修改该纪录
    • 只能在 Read Commited、Repeatable Read 隔离级别下工作

4. 锁分类

粒度

  • 表级锁

    • 操作锁住整张表
    • 粒度大、冲突概率高、并发度最低
    • MyISAM、InnoDB、BDB 引擎
  • 页级锁

    • 操作锁定相邻的一组纪录
    • BDB 引擎
  • 行级锁

    • 操作锁住一行数据

    • 粒度最小、冲突概率低、并发度最高

    • InnoDB 引擎

操作

共享锁 和 排他锁 都是【悲观锁】

  • 读锁(S锁)
    • 又称 共享锁,多个读操作可以同时进行,不会互相影响
    • 读操作期间,可以追加 S锁,但不能追加 X锁,如需追加 X锁,需等所有 S锁 释放,才能追加
  • 写锁(X锁)
    • 又称 排他锁,同时只能存在一个锁,写操作完成前,阻断其他写锁和读锁(其他事务都不能操作)

性能

  • 乐观锁
    • 在数据【提交更新时】,才进行版本检测
    • 谁都可以来,但我成功了,你就成功不了
  • 悲观锁
    • 在数据【修改前】,就先锁定
    • 我认为会出问题,所以先上锁

十、行锁原理

InnoDB 的行锁是通过对【索引】的数据加锁实现的,无索引则全表锁定,可能导致死锁

InnoDB 优先采用 Next-key Lock 锁住数据+范围,但当 SQL 操作含有唯一索引(一个索引只能定位到一条纪录),将降级成 RecordLock,仅锁住数据

1. 实现算法

  • RecordLock
    • 锁定单行纪录
    • 纪录锁,RC、RR 隔离级别支持
  • GapLock
    • 锁定索引间的【间隙】,确保间隙间距离不变
    • 范围锁,RR 隔离级别支持
  • Next-key Lock
    • 锁住单行纪录,并锁住数据的前后范围
    • 纪录锁 + 范围锁,RR 隔离级别支持

2. 情况

加锁都是 先使用 Next-key Lock 处理,如发现唯一索引,则降级为 RecordLock

当事务使用了写锁(排他锁,同时只能存一个锁),只有当前事务可以修改,但允许普通查找,因为普通查找不加锁

  • select ... from 语句 : InnoDB 采用 MVCC 实现非阻塞读,所以普通 select【不加锁】
  • select ... from lock in share mode 语句 : 追加【读锁】(S锁) (多个读操作可同时进行)
  • select ... from for update 语句 : 追加【写锁】(X锁) (同时只能有一个读操作)
  • update ... where 语句 : 追加【写锁】(X锁)
  • delete ... where 语句 : 追加【写锁】(X锁)
  • insert 语句 : 追加【写锁】(X锁) 的 RecordLock 锁

十一、高可用

1. 主从复制

用途

  • 实时灾备,用于故障切换 - 高可用
  • 读写分离,分担读压力 - 读扩展

前置条件

  • 从库服务器 能连接 主库服务器
  • 主库开启 Binlog 日志
  • 主从的 server-id 不同

实现原理

  1. 主库将变更操作纪录到 Binlog 中
  2. 主库的 BinlogDump Thread 收到从库的请求后,读取 Binlog 信息并推送到从库的 I/O Thread
  3. 从库的 I/O Thread 读取主库的 Binlog 日志,写入到从库的 Relay Log(中继日志) 中
  4. 从库的 SQL Thread 检测到 Relay Log 的变更请求,读取 Relay Log 对操作进行回放,更新数据库信息

问题

  • 主库当机,数据可能丢失 - 解决 - 半同步复制

    主库写入 Binlog 后,等待从库写入 Relay Log 并返回 ACK 后,才进行事务提交

  • 主库压力大,复制可能延时

    • 解决

      • 并行复制

        将 SQL Thread 改为多线程对操作进行回放,且基于 组提交(MySQL 5.7 一组事务的提交) 来保证与主库结果一致

      • 刚写入的时间段内读主库,之后读从库

      • 先去从库读,找不到就读主库 - 注意恶意攻击

      • 实时性要求高的读写操作放主库,次要业务进行读写分离

优化

  • 在从库加索引,主库不加,提升写效率

2. 双主模式

  • 两台服务器互为主从,任何一台数据变更,都会透过复制,将数据备分到另一台数据库中
  • 【建议】使用 双主单写 避免
    • ID 冲突
      • 当使用主键自动递增时,A、B 主库同步不及时,容易产生问题
      • 可以使用自动增长步长解决,A 主库 1,3,5;B 主库 2,4,6 - 对 运维、扩展 不友好
    • 更新丢失
      • 同一条数据在 A、B 主库都进行更新,会发生纪录覆盖问题
  • 使用 Keepalived 或 MMM 实施主库故障自动切换

3. MHA 架构

  • 30 秒内自动完成故障切换

  • 最大程度保证数据一致性

  • 支持在线主库切换

  • 最少需要 3 台服务器

  • 角色

    • MHA Manager
      • 负责检测 Master 是否当机、控制故障转移、检查 MySQL 复制情况
      • 可以 单独布署 或 布署在 Slave 节点
    • MHA Node
      • 所有的 Master、Slave 节点
      • 负责保存、复制 Master 的 Binlog
  • 优点

    • 自动故障转移快
    • 主库崩溃不存在数据一致性问题
    • 支持 半同步复制、异步复制
    • 一个 Manager 可以监控多个集群
  • Master 当机处理

    1. 将 Master 的 Binlog 保存

    2. 根据 Binlog 位置找到最新的 Slave

    3. 用最新 Slave 的 Relay Log 修复其他 Slave

    4. 将保存下来的 Master 的 Binlog 在最新的 Slave 上修复

    5. 将最新的 Slave 提升为 Master

    6. 将其他 Slave 重新指向新 Master,并开启主从复制