技术博客 技术博客
  • JAVA
  • 仓颉
  • 设计模式
  • 人工智能
  • Spring
  • Mybatis
  • Maven
  • Git
  • Kafka
  • RabbitMQ
  • RocketMQ
  • Redis
  • Zookeeper
  • Nginx
  • 数据库套件
  • MySQL
  • Elasticsearch
  • MongoDB
  • Hadoop
  • ClickHouse
  • Hbase
  • Hive
  • Flink
  • Flume
  • SQLite
  • linux
  • Docker
  • Jenkins
  • Kubernetes
  • 工具
  • 前端
  • AI
GitHub (opens new window)
  • JAVA
  • 仓颉
  • 设计模式
  • 人工智能
  • Spring
  • Mybatis
  • Maven
  • Git
  • Kafka
  • RabbitMQ
  • RocketMQ
  • Redis
  • Zookeeper
  • Nginx
  • 数据库套件
  • MySQL
  • Elasticsearch
  • MongoDB
  • Hadoop
  • ClickHouse
  • Hbase
  • Hive
  • Flink
  • Flume
  • SQLite
  • linux
  • Docker
  • Jenkins
  • Kubernetes
  • 工具
  • 前端
  • AI
GitHub (opens new window)
  • mysql

    • MySQL 问题汇总
    • MySQL 索引介绍
    • MySQL 锁介绍
    • MySQL 索引优化工具 explain
    • MySQL 主从复制(GTID)
    • MySQL 8安装
    • MySQL 8.x新特性总结
    • MySQL UDF以及新类型JSON
    • MySQL 高可用MGR(一) 理论
      • 背景
      • Group Replication原理
        • 1 单主模式
        • 2 多主模式
        • 3 事物隔离级别补充
        • Read Committed
        • Serializable
        • Repeatable Read
        • Read Uncommitted
      • 配置要求和限制
      • mysql主从可以有多少个
      • autoincrementincrement
    • MySQL 高可用MGR(二) 搭建
    • MySQL 高可用MGR(三) 测试
  • Elasticsearch

    • ES 7.8.0(一) 入门介绍
    • ES 7.8.0(二) 读、写和写索引流程以及文档分析过程
    • ES 7.8.0(三) 文档冲突
  • mongodb

    • mongodb
  • hadoop

    • Hadoop 伪分布式及集群
    • Hadoop 指令
    • Hadoop 读写流程详解
    • Hadoop SpringBoot集成
    • Hadoop MapReduce机制
    • Hadoop YARN
    • Hadoop MapReduce配置和编写job及数据倾斜的解决
    • Hadoop MapReduce自定义格式输入输出
  • clickhouse

    • ClickHouse 介绍及安装
    • ClickHouse 数据类型
    • ClickHouse 表引擎
    • ClickHouse SQL操作
    • ClickHouse 副本配置
    • ClickHouse 分片与集群部署
    • ClickHouse Explain及建表优化
    • ClickHouse 语法优化规则
    • ClickHouse 查询优化
    • ClickHouse 数据一致性
    • ClickHouse 物化视图
    • ClickHouse MaterializeMySQL引擎
    • ClickHouse 监控及备份
  • hbase

    • Hbase 介绍及安装
    • Hbase 优化
    • Hbase phoenix安装及使用
    • Hbase LSM-TREE
  • hive

    • Hive 介绍及安装
    • Hive 内外部表、分区表、分桶表概念及hiveSQL命令
    • Hive 数据类型
    • Hive 函数 MySQL联合
    • Hive 数据倾斜和优化
    • Hive Sqoop安装及指令
  • flink

    • Flink 介绍及安装
    • Flink 配置介绍及Demo
    • Flink API讲解
    • Flink 运行架构
    • Flink 时间语义及Watermark
    • Flink 状态管理
    • Flink 容错,检查点,保存点
    • Flink 状态一致性
    • Flink Table API 和 Flink SQL
    • Flink CEP编程
    • Flink Joining编程
    • Flink CDC
  • flume

    • Flume 日志收集系统介绍及安装
    • Flume Source支持的类型
    • Flume Sink支持的类型
    • Flume Channel支持的类型
    • Flume Selector
    • Flume Interceptor拦截器类型
    • Flume Process
  • sqlite

    • SQLite介绍
目录

MySQL 高可用MGR(一) 理论

# 背景

主从复制,一主多从,主库提供读写功能,从库提供只读功能。当一个事务在 master 提交成功时,会把 binlog 文件同步到从库服务器上落地为 relay log 给 slave 端执行,这个过程主库是不考虑从库是否有接收到 binlog 文件,有可能出现这种情况,当主库 commit 一个事务后,数据库发生宕机,刚好它的 binlog 还没来得及传送到 slave 端,这个时候选任何一个 slave 端都会丢失这个事务,造成数据不一致情况。 为了避免出现主从数据不一致的情况,MySQL 引入了半同步复制,添加多了一个从库反馈机制,即半同步复制。这个有两种方式设置:

  1. 主库执行完事务后,同步 binlog 给从库,从库 ack 反馈接收到 binlog,主库提交 commit,反馈给客户端,释放会话;
  2. 主库执行完事务后,主库提交 commit ,同步 binlog 给从库,从库 ack 反馈接收到 binlog,反馈给客户端,释放会话;

虽然满足了一主多从,读写分析,数据一致,但是,依旧有两个弊端:

  1. 写操作只能在 master 上;
  2. 如果 master 宕机,需要人为选择新主并重新给其他的 slave 端执行 change master;

为了解决一系列问题,官方推出了 MySQL Group Replication,从 group replication 发布以后,就有 3 种方法来实现 MySQL 的高可用集群:

  • 异步复制
  • 半同步复制
  • group replication

# Group Replication 原理

MySQL Group Replication 有两种模式,单主模式 single-primary mode 和多主模式 multi-primary mode,在同一个 group 内,不允许两种模式同时存在,并且若要切换到不同模式,必须修改配置后重新启动集群。

# 1 单主模式

在单主模式下,只有一个节点可以读写,其他节点提供只读服务。单主模式下 ,当主节点宕掉,自动会根据服务器的 server_uuid 变量和 group_replication_member_weight 变量值,选择下一个 slave 谁作为主节点,group_replication_member_weight 的值最高的成员被选为新的主节点,该参数默认为 50,建议可以在节点上设置不同值;在 group_replication_member_weight 值相同的情况下,group 根据数据字典中 server_uuid 排序,排序在最前的被选择为主节点。

# 2 多主模式

在 mysql 多主模式下,在组复制中通过 Group Replication Protocol 协议及 Paxos 协议 (一致性算法) (opens new window),形成的整体高可用解决方案,同时增加了 certify (认证) 的概念,负责检查事务是否允许提交,是否与其它事务存在冲突,Group Replication 是由多个节点共同组成一个数据库集群,每个节点都可以单独执行事务,但是 read-write(rw)的操作只有在组内验证后才可以 commit,Read-only (RO) 事务是不需要验证可以立即执行,当一个事务在一个节点上提交之前,会在组内自动进行原子性的广播,告知其他节点变更了什么内容 / 执行了什么事务,然后为该事物建立一个全局的排序,最终,这意味着所有的服务器都以相同的顺序接收相同的事务集。因此,所有服务器都按照相同的顺序应用相同的变更集,因此它们在组中保持一致。 在多主模式下,该组的所有成员都设置为读写模式,在多主模式下,不支持 SERIALIZABLE (严格的) 事务隔离级别,且不能完全支持级联外键约束。

# 3 事物隔离级别补充

# Read Committed

在 Read Committed 隔离级别下,一个事务可能会遇到不可重复读(Non Repeatable Read)的问题。不可重复读是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致。
我们先准备好 students 表的数据:

mysql> select * from students;
+----+-------+
| id | name  |
+----+-------+
|  1 | Alice |
+----+-------+
1 row in set (0.00 sec)
1
2
3
4
5
6
7

然后,分别开启两个 MySQL 客户端连接,按顺序依次执行事务 A 和事务 B:

时刻 事务 A 事务 B
1 SET TRANSACTION ISOLATION LEVEL READ COMMITTED; SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
2 BEGIN; BEGIN;
3 SELECT * FROM students WHERE id = 1;
4 UPDATE students SET name = 'Bob' WHERE id = 1;
5 COMMIT;
6 SELECT * FROM students WHERE id = 1;
7 COMMIT;

当事务 B 第一次执行第 3 步的查询时,得到的结果是 Alice,随后,由于事务 A 在第 4 步更新了这条记录并提交,所以,事务 B 在第 6 步再次执行同样的查询时,得到的结果就变成了 Bob,因此,在 Read Committed 隔离级别下,事务不可重复读同一条记录,因为很可能读到的结果不一致。

# Serializable

Serializable 是最严格的隔离级别。在 Serializable 隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。

虽然 Serializable 隔离级别下的事务具有最高的安全性,但是,由于事务是串行执行,所以效率会大大下降,应用程序的性能会急剧降低。如果没有特别重要的情景,一般都不会使用 Serializable 隔离级别。

默认隔离级别
如果没有指定隔离级别,数据库就会使用默认的隔离级别。在 MySQL 中,如果使用 InnoDB,默认的隔离级别是 Repeatable Read。

# Repeatable Read

在 Repeatable Read 隔离级别下,一个事务可能会遇到幻读(Phantom Read)的问题。幻读是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。

mysql> select * from students;
+----+-------+
| id | name  |
+----+-------+
|  1 | Alice |
+----+-------+
1 row in set (0.00 sec)
1
2
3
4
5
6
7

然后,分别开启两个 MySQL 客户端连接,按顺序依次执行事务 A 和事务 B:

时刻 事务 A 事务 B
1 SET TRANSACTION ISOLATION LEVEL REPEATABLE READ; SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
2 BEGIN; BEGIN;
3 SELECT * FROM students WHERE id = 99;
4 INSERT INTO students (id, name) VALUES (99, 'Bob');
5 COMMIT;
6 SELECT * FROM students WHERE id = 99;
7 UPDATE students SET name = 'Alice' WHERE id = 99;
8 SELECT * FROM students WHERE id = 99;
9 COMMIT;

事务 B 在第 3 步第一次读取 id=99 的记录时,读到的记录为空,说明不存在 id=99 的记录。随后,事务 A 在第 4 步插入了一条 id=99 的记录并提交。事务 B 在第 6 步再次读取 id=99 的记录时,读到的记录仍然为空,但是,事务 B 在第 7 步试图更新这条不存在的记录时,竟然成功了,并且,事务 B 在第 8 步再次读取 id=99 的记录时,记录出现了。

可见,幻读就是没有读到的记录,以为不存在,但其实是可以更新成功的,并且,更新成功后,再次读取,就出现了。

# Read Uncommitted

Read Uncommitted 是隔离级别最低的一种事务级别。在这种隔离级别下,一个事务会读到另一个事务更新后但未提交的数据,如果另一个事务回滚,那么当前事务读到的数据就是脏数据,这就是脏读(Dirty Read)。

mysql> select * from students;
+----+-------+
| id | name  |
+----+-------+
|  1 | Alice |
+----+-------+
1 row in set (0.00 sec)
1
2
3
4
5
6
7

然后,分别开启两个 MySQL 客户端连接,按顺序依次执行事务 A 和事务 B:

时刻 事务 A 事务 B
1 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED; SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
2 BEGIN; BEGIN;
3 UPDATE students SET name = 'Bob' WHERE id = 1;
4 SELECT * FROM students WHERE id = 1;
5 ROLLBACK;
6 SELECT * FROM students WHERE id = 1;
7 COMMIT;

当事务 A 执行完第 3 步时,它更新了 id=1 的记录,但并未提交,而事务 B 在第 4 步读取到的数据就是未提交的数据。随后,事务 A 在第 5 步进行了回滚,事务 B 再次读取 id=1 的记录,发现和上一次读取到的数据不一致,这就是脏读。可见,在 Read Uncommitted 隔离级别下,一个事务可能读取到另一个事务更新但未提交的数据,这个数据有可能是脏数据。

# 配置要求 (opens new window)和限制 (opens new window)

  • inndb 存储引擎;
  • 每个表需要定义显式主键;
  • 隔离级别:官网建议 READ COMMITTED 级别,不支持 SERIALIZABLE 隔离级别;
  • 不建议使用级联外键;
  • IPv4 网络;
  • auto_increment_increment 和 auto_increment_offset 的配置;
  • log-bin = ROW;
  • log_slave_updates = ON;
  • 开启 GTID;
  • 安装引擎:group_replication.so;

# mysql 主从可以有多少个

可以成为一个复制组成员的 MySQL 服务器的最大数量为 9。如果其他成员尝试加入该组,则其请求将被拒绝。从测试和基准测试中可以确定此限制是安全的边界,在此范围内,组可以在稳定的局域网上可靠地运行。

# auto_increment_increment

在服务器上启动组复制时,auto_increment_increment 的值将更改为 group_replication_auto_increment_increment 的值(默认值为 7),而 auto_increment_offset 的值将更改为服务器 ID。 停止组复制时,将还原更改。 这些设置避免为组成员上的写入选择重复的自动增量值,这会导致事务回滚。 组复制的默认自动增量值为 7,表示可用值数与复制组的允许最大大小(9 个成员)之间的平衡。

仅当 auto_increment_increment 和 auto_increment_offset 各自的默认值均为 1 时,才进行更改并还原。如果已将其值从默认值修改,则组复制不会更改它们。 从 MySQL 8.0 开始,当组复制处于只有一个服务器写入的单主模式下时,系统变量也不会被修改。

上次更新: 6/11/2025, 4:10:30 PM
MySQL UDF以及新类型JSON
MySQL 高可用MGR(二) 搭建

← MySQL UDF以及新类型JSON MySQL 高可用MGR(二) 搭建→

Theme by Vdoing | Copyright © 2023-2025
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式