diff --git a/code/ES6/src/01_block_bindings/01_var.js b/code/ES6/src/01_block_bindings/01_var.js new file mode 100644 index 0000000..1cf6ba4 --- /dev/null +++ b/code/ES6/src/01_block_bindings/01_var.js @@ -0,0 +1,13 @@ +function test(flag) { + if (flag) { + var value = "blue"; + console.log(value); + } else { + console.log(value); + } + console.log(value); +} + +test(true); +test(false); + diff --git a/code/ES6/src/01_block_bindings/02_let.js b/code/ES6/src/01_block_bindings/02_let.js new file mode 100644 index 0000000..244e88c --- /dev/null +++ b/code/ES6/src/01_block_bindings/02_let.js @@ -0,0 +1,13 @@ +function test(flag) { + if (flag) { + let value = "blue"; + console.log(value); + } else { + console.log(value); //value在此处不能访问 + } + console.log(value); //value在此处不能访问 +} + +test(true); +test(false); + diff --git a/code/ES6/src/01_block_bindings/03_the_temporal_dead_zone.js b/code/ES6/src/01_block_bindings/03_the_temporal_dead_zone.js new file mode 100644 index 0000000..efde477 --- /dev/null +++ b/code/ES6/src/01_block_bindings/03_the_temporal_dead_zone.js @@ -0,0 +1,5 @@ +(function test() { + console.log(typeof value); // 引用错误 + let value = "blue"; + console.log(value); +})(); diff --git a/code/ES6/src/01_block_bindings/04_no_temporal_dead_zone.js b/code/ES6/src/01_block_bindings/04_no_temporal_dead_zone.js new file mode 100644 index 0000000..eaa0395 --- /dev/null +++ b/code/ES6/src/01_block_bindings/04_no_temporal_dead_zone.js @@ -0,0 +1,5 @@ +console.log(typeof value); +(function test() { + let value = "blue"; + console.log(value); +})(); diff --git a/code/ES6/src/01_block_bindings/05_var_for.js b/code/ES6/src/01_block_bindings/05_var_for.js new file mode 100644 index 0000000..9e04fd1 --- /dev/null +++ b/code/ES6/src/01_block_bindings/05_var_for.js @@ -0,0 +1,9 @@ +let list = []; +for (var i = 0; i < 10; i++) { + list.push(function () { + console.log(i); + }); +} +list.forEach(function (func) { + func(); +}); diff --git a/code/ES6/src/01_block_bindings/06_let_for.js b/code/ES6/src/01_block_bindings/06_let_for.js new file mode 100644 index 0000000..849aaef --- /dev/null +++ b/code/ES6/src/01_block_bindings/06_let_for.js @@ -0,0 +1,9 @@ +let list = []; +for (let i = 0; i < 10; i++) { + list.push(function () { + console.log(i); + }); +} +list.forEach(function (func) { + func(); +}); diff --git a/code/ES6/src/02_strings_template/01_string_methods.js b/code/ES6/src/02_strings_template/01_string_methods.js new file mode 100644 index 0000000..d635ace --- /dev/null +++ b/code/ES6/src/02_strings_template/01_string_methods.js @@ -0,0 +1,26 @@ +let msg = "Hello world!"; +console.log(msg.startsWith("Hello")); // true +console.log(msg.endsWith("!")); // true +console.log(msg.includes("o")); // true +console.log(msg.startsWith("o")); // false +console.log(msg.endsWith("world!")); // true +console.log(msg.includes("x")); // false +console.log(msg.startsWith("o", 4)); // true +console.log(msg.endsWith("o", 8)); // true +console.log(msg.includes("o", 8)); // false + +console.log("x".repeat(3)); // "xxx" +console.log("hello".repeat(2)); // "hellohello" +console.log("abc".repeat(4)); // "abcabcabcabc" + +'x'.padStart(5, 'ab'); // 'ababx' +'x'.padStart(4, 'ab'); // 'abax' + +'x'.padEnd(5, 'ab'); // 'xabab' +'x'.padEnd(4, 'ab'); // 'xaba' +'xxx'.padStart(2, 'ab'); // 'xxx' +'xxx'.padEnd(2, 'ab'); // 'xxx' + +'abc'.padStart(10, '0123456789'); //'0123456abc' +'x'.padStart(4); // ' x' +'x'.padEnd(4); // 'x ' diff --git a/code/ES6/src/02_strings_template/02_template.js b/code/ES6/src/02_strings_template/02_template.js new file mode 100644 index 0000000..86cdf62 --- /dev/null +++ b/code/ES6/src/02_strings_template/02_template.js @@ -0,0 +1,23 @@ +// 1.模板字面量 +let name = "Nicholas", + message01 = `Hello, ${name}.`; +console.log(message01); // "Hello, Nicholas." + +// 2.支持JS表达式 +let count = 10, + price = 0.25, + message02 = `${count} items cost $${(count * price).toFixed(2)}.`; +console.log(message02); // "10 items cost $2.50." + +// 3.多行字符串 +let message03 = `Multiline +string`; +console.log(message03); // Hello, + // string + +// 4.多行字符串与模板嵌套 +let fullName = "Nicholas", + message04 = `Hello, + my name is ${fullName}.`; +console.log(message04); // Hello, + // my name is Nicholas. diff --git a/notes/MySQL_Mycat中间件.md b/notes/MySQL_Mycat中间件.md index 47b6628..69b8ad7 100644 --- a/notes/MySQL_Mycat中间件.md +++ b/notes/MySQL_Mycat中间件.md @@ -153,23 +153,17 @@ GO0bnFVWrAuFgr1JMuMZkvfDNyTpoiGU7n/Wlsa151CirHQnANVk3NzE3FErx8v6pAcO0ctX3xFecmSr + **switchType**: - 默认值为 1,代表自动切换; - - 设置为 2,代表基于 MySQL 主从同步的状态来决定是否切换; - - 设置为 3,代表基于 MySQL galary cluster 的切换机制进行切换; - - 如果你的集群基于 MMM 或 MHA 等高可用架构实现自动切换,则可以将该值设置为 -1,代表不切换。 + + 默认值为 1,代表自动切换; + + 设置为 2,代表基于 MySQL 主从同步的状态来决定是否切换; + + 设置为 3,代表基于 MySQL galary cluster 的切换机制进行切换; + + 如果你的集群基于 MMM 或 MHA 等高可用架构实现自动切换,则可以将该值设置为 -1,代表不切换。 + **balance**: - balance="0" :不开启读写分离机制,所有读请求都发送到当前可用的 writeHost 上。 - - balance="1" :全部的 readHost 与 stand by writeHost 参与读操作。stand by writeHost 通常指的是双主复制中处于 stand 状态的主节点,即假设集群复制架构为 Master1 -> Slave1,Master2 -> Slave2,并且 M1 与 M2 互为主备 ),此时 Master2 ,Slave1,Slave2 都会参与读的负载。 - - balance="2" :所有读请求随机在 writeHost、 readhost 上进行分发。 - - balance="3" :所有读请求随机分发到 writeHost 对应的 readhost 执行,writerHost 不负担读压力。 + + `balance="0"` :不开启读写分离机制,所有读请求都发送到当前可用的 writeHost 上。 + + `balance="1"` :全部的 readHost 与 stand by writeHost 参与读操作。stand by writeHost 通常指的是双主复制中处于 stand 状态的主节点,即假设集群复制架构为 Master1 -> Slave1,Master2 -> Slave2,并且 M1 与 M2 互为主备 ),此时 Master2 ,Slave1,Slave2 都会参与读的负载。 + + `balance="2"` :所有读请求随机在 writeHost、 readhost 上进行分发。 + + `balance="3"` :所有读请求随机分发到 writeHost 对应的 readhost 执行,writerHost 不负担读压力。 ### 4.3 rule.xml @@ -237,7 +231,6 @@ Mycat 读写分离的配置非常简单,只需要通过配置 balance,writeH 综合以上全部内容,这里给出一个分库分表的示例,其架构如下:
- 如上图所示,这里模拟的是一个电商数据库,并对其执行分库分表操作: - 将用户相关表,订单相关表,商品相关表分表拆分到单独的数据库中; @@ -351,7 +344,7 @@ Mycat 读写分离的配置非常简单,只需要通过配置 balance,writeH Access denied for user 'xxx', because password is error ``` -这是由于从 MySQL 8.0.4 开始使用 caching_sha2_password 作为认证的插件,而之前版本的插件为 mysql_native_password,我在测试中使用的 Mycat 版本为 1.6.7,它并不支持 caching_sha2_password 。因此在登录时候需要通过 `--default_auth` 来指定使用原有的认证插件。 +这是由于从 MySQL 8.0.4 开始使用 `caching_sha2_password` 作为认证的插件,而之前版本的插件为 `mysql_native_password`,我在测试中使用的 Mycat 版本为 1.6.7,它并不支持 `caching_sha2_password` 。因此在登录时候需要通过 `--default_auth` 来指定使用原有的认证插件: ```shell # 1.6.7 版本 Mycat 默认的连接端口号为 8066 diff --git a/notes/MySQL_PXC集群.md b/notes/MySQL_PXC集群.md index 16a834d..3f7f407 100644 --- a/notes/MySQL_PXC集群.md +++ b/notes/MySQL_PXC集群.md @@ -16,16 +16,15 @@ Percona XtraDB Cluster (简称 PXC) 是 Percona 公司开源的实现 MySQL 高可用的解决方案。它将 Percona Server 和 Percona XtraBackup 与 Galera 库集成,以实现多主同步复制。和 MySQL 传统的异步复制相比,它能够保证数据的强一致性,在任何时刻集群中任意节点上的数据状态都是完全一致的,并且整个架构实现了去中心化,所有节点都是对等的,即允许你在任意节点上进行写入和读取,集群会把数据状态同步至其他所有节点。但目前 PXC 集群只支持 InnoDB 存储引擎,并具有以下限制: + 添加新节点时,必须从现有节点之一复制完整数据集。如果是 100GB,则复制 100GB。为了减少网络开销,建议在搭建集群前使用备份的方式将所有节点的数据状态调整至一致。 -+ 不支持 LOCK TABLES ,在多主设置的情况下也不受支持 UNLOCK TABLES。 ++ 不支持 LOCK TABLES ,在多主设置的情况下也不支持 UNLOCK TABLES。 + 不支持锁定功能,如 GET_LOCK(),RELEASE_LOCK() 等。 + 由于可能在提交时回滚,因此也不支持 XA 事务 (分布式事务) 。 + 所有表必须具有主键。 + 由于节点是对等的,所以整个集群的写吞吐量受限于性能最差的节点,如果一个节点变慢,则整个群集都会变慢。因此应该保证所有节点的硬件配置一致,并避免单个节点超负载运行。 -+ 允许的最大事务大小由 wsrep_max_ws_rows 和 wsrep_max_ws_size 参数共同定义,因此超大型事务会被拆分为一系列小型事务,如加载大数据集 LOAD DATA INFILELOAD DATA。 ++ 允许的最大事务大小由 wsrep_max_ws_rows 和 wsrep_max_ws_size 参数共同定义,因此超大型事务会被拆分为一系列小型事务,如加载大数据集 LOAD DATA INFILE。 + 由于在集群级别采用乐观锁进行并发控制,所以事务在 COMMIT 阶段仍然有被中止的可能。如两个事务在不同的集群节点上提交对相同的行的写入,此时只有其中一个可以成功提交,另一个将被中止。
- 虽然 PXC 集群存在以上限制,但就目前而言,它仍然是解决数据一致性和高可用性的最好方案,其搭建步骤如下: ## 二、集群搭建 diff --git a/notes/MySQL_基础.md b/notes/MySQL_基础.md index 18c3a52..30b3330 100644 --- a/notes/MySQL_基础.md +++ b/notes/MySQL_基础.md @@ -31,13 +31,13 @@ ### 1.1 InnoDB -InnoDB 是 MySQL 5.5 之后默认的存储引擎,它是一种兼具高可靠和高性能的存储引擎,主要具备以下优势: +InnoDB 是 MySQL 5.5 之后默认的存储引擎,它兼具高可靠和高性能的特性,主要具备以下优势: -+ DML 操作完全遵循 ACID 模型,支持事务,支持崩溃恢复,能够极大的保护用户的数据安全; -+ InnoDB 支持多版本并发控制,它会保存旧版本的数据信息,以支持并发和事务的回滚; ++ DML 操作完全遵循 ACID 模型,支持事务,支持崩溃恢复,能够极大地保护用户的数据安全; ++ 支持多版本并发控制,它会保存数据的旧版本信息,从而可以支持并发和事务的回滚; + 支持行级锁,支持类似 Oracle 的一致性读的特性,从而可以承受高并发地访问; -+ InnoDB 组织数据时默认按照主键进行聚簇,从而可以提高主键查找的效率。对于频繁访问的数据,InnoDB 还会为其自建立哈希索引,从而提高等值查询的效率,这称为自适应哈希索引。 -+ InnoDB 基于磁盘进行存储,所有存储记录按**页**的方式进行管理。为弥补 CPU 速度与磁盘速度之间的鸿沟,InnoDB 引用缓存池 (Buffer Pool) 来提高数据的整体性能。查询时,会将目标页读取缓存中;修改时,会先修改缓冲池中的页,然后再遵循 CheckPoint 机制将页刷回磁盘。所有缓存页通过最近最少使用原则 ( LRU ) 来进行定期清理。 ++ InnoDB 组织数据时默认按照主键进行聚簇,从而可以提高主键查找的效率。对于频繁访问的数据,InnoDB 还会为其建立哈希索引,从而提高等值查询的效率,这称为自适应哈希索引。 ++ InnoDB 基于磁盘进行存储,所有存储记录按 **页** 的方式进行管理。为弥补 CPU 速度与磁盘速度之间的鸿沟,InnoDB 引用缓存池 (Buffer Pool) 来提高数据的整体性能。查询时,会将目标页读取缓存中;修改时,会先修改缓冲池中的页,然后再遵循 CheckPoint 机制将页刷回磁盘。所有缓存页通过最近最少使用原则 ( LRU ) 来进行定期清理。 + InnoDB 支持两次写 (DoubleWrite) ,从而可以保证数据的安全,提高系统的可靠性。 一个 InnoDB 引擎完整的内存结构和磁盘结构如下图所示: @@ -45,7 +45,6 @@ InnoDB 是 MySQL 5.5 之后默认的存储引擎,它是一种兼具高可靠
- ### 1.2 MyISAM MyISAM 是 MySQL 5.5 之前默认的存储引擎。创建 MyISAM 表时会创建两个同名的文件: @@ -120,19 +119,15 @@ mysql> SELECT * FROM total; **平衡二叉树数据结构**:
- **红黑树数据结构**:
- **Btree 数据结构**:
- **B+ Tree 数据结构**
- > 以上图片均通过数据结构可视化网站 [Data Structure Visualizations](https://www.cs.usfca.edu/~galles/visualization/Algorithms.html) 自动生成,感兴趣的小伙伴也可自行尝试。 从上面的图示中我们可以看出 B+ Tree 树具有以下优点: @@ -144,7 +139,7 @@ mysql> SELECT * FROM total; ### 2.2 B+ tree 索引 -对于 InnoDB ,因为主键索引是聚集索引,所以其叶子节点存储的就是实际的数据。而非主键索引存储则是主键的值 : +对于 InnoDB ,因为主键索引是聚集索引,所以其叶子节点存储的就是实际的数据。而非主键索引存储的则是主键的值 :
对于 MyISAM,因为主键索引是非聚集索引,所以其叶子节点存储的只是指向数据位置的指针: @@ -288,25 +283,21 @@ InnoDB 存储引擎完全支持 ACID 模型: 一个事务的更新操作被另外一个事务的更新操作锁覆盖,从而导致数据不一致:
- **2. 脏读** 在不同的事务下,一个事务读取到其他事务未提交的数据:
- **3. 不可重复读** 在同一个事务的两次读取之间,由于其他事务对数据进行了修改,导致对同一条数据两次读到的结果不一致:
- **4.幻读** 在同一个事务的两次读取之间,由于其他事务对数据进行了修改,导致第二次读取到第一次不存在数据,或第一次原本存在的数据,第二次却读取不到,就好像之前的读取是 “幻觉” 一样:
- ### 4.4 隔离级别 想要解决以上问题,可以通过设置隔离级别来实现:InnoDB 支持以下四个等级的隔离级别,默认隔离级别为可重复读: diff --git a/notes/MySQL_备份.md b/notes/MySQL_备份.md index dd2dc19..89d6755 100644 --- a/notes/MySQL_备份.md +++ b/notes/MySQL_备份.md @@ -26,7 +26,7 @@ **物理备份 与 逻辑备份** -+ 物理备份:备份的是完整的数据库目录和数据文件。由于其基本都是 IO 复制,并不含任何逻辑转换,因此其备份和恢复速度通常都比较快。 ++ 物理备份:备份的是完整的数据库目录和数据文件。采用该模式会进行大量的 IO 操作,但不含任何逻辑转换,因此备份和恢复速度通常都比较快。 + 逻辑备份:通过数据库结构和内容信息来进行备份。因为要执行逻辑转换,因此其速度较慢,并且在以文本格式保存时,其输出文件的大小大于物理备份。逻辑备份的还原的粒度可以从服务器级别(所有数据库)精确到具体表,但备份不会包括日志文件、配置文件等与数据库无关的内容。 **全量备份 与 增量备份** @@ -36,8 +36,8 @@ **在线备份 与 离线备份** -+ 在线备份:在数据库服务运行状态下进行备份。此时其他客户端依旧可以连接到数据库,但为了保证数据的一致性,在备份期间必然会存在对数据加锁的操作,此时客户端的访问仍然可能受限。 -+ 离线备份:在数据库服务停机状态下进行备份。此时备份过程更加简单,但会此时由于无法提供对外服务,通常会对业务造成比较大的影响。 ++ 在线备份:数据库服务在运行状态下进行备份。此时其他客户端依旧可以连接到数据库,但为了保证数据的一致性,在备份期间可能会对数据进行加锁,此时客户端的访问依然会受限。 ++ 离线备份:在数据库服务停机状态下进行备份。此备份过程简单,但由于无法提供对外服务,通常会对业务造成比较大的影响。 ### 2.2 备份工具 @@ -74,7 +74,7 @@ options 代表可选操作,常用的可选参数如下: + **--password[=password], -p[password]** - 指定密码。通常不用在命令行中明文指定,按照提示输出即可。 + 指定密码。通常无需在命令行中明文指定,按照提示输出即可。 + **--default-character-set=charset_name** @@ -82,19 +82,19 @@ options 代表可选操作,常用的可选参数如下: + **--events, -E** - 备份包含包含数据库中的事件。 + 备份包含数据库中的事件。 + **--ignore-table=db_name.tbl_name** - 不需要进行备份的表,必须使用数据库和表名来指定。也可以作用于视图。 + 不需要进行备份的表,必须使用数据库和表名来共同指定。也可以作用于视图。 + **--routines, -R** - 备份包含包含数据库中的存储过程和自定义函数。 + 备份包含数据库中的存储过程和自定义函数。 + **--triggers** - 备份包含包含数据库中的触发器。 + 备份包含数据库中的触发器。 + **--where='where_condition', -w 'where_condition'** @@ -108,11 +108,9 @@ options 代表可选操作,常用的可选参数如下: 锁定当前数据库中所有表,能够保证当前数据库中表的一致性,但不能保证全局的一致性。 - 由于--lock-tables每个数据库的锁表都是单独的,因此该选项不保证转储文件中的表在数据库之间在逻辑上是一致的。不同数据库中的表可能会以完全不同的状态转储。 - + **--single-transaction** - 此选项会将事务隔离模式设置为: REPEATABLE READ 并开启一个事务,从而保证备份数据的一致性。主要用于事务表,如 InnoDB 表。 但是此时仍然不能在备份表上执行 ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE 等操作,因为 REPEATABLE READ 隔离并不能隔离这些操作。 + 此选项会将事务隔离模式设置为 REPEATABLE READ 并开启一个事务,从而保证备份数据的一致性。主要用于事务表,如 InnoDB 表。 但是此时仍然不能在备份表上执行 ALTER TABLE, CREATE TABLE, DROP TABLE, RENAME TABLE, TRUNCATE TABLE 等操作,因为 REPEATABLE READ 并不能隔离这些操作。 另外需要注意的是 --single-transaction 选项与 --lock-tables 选项是互斥的,因为 LOCK TABLES 会导致任何正在挂起的事务被隐式提交。转储大表时,可以将 --single-transaction 选项与 --quick 选项组合使用 。 @@ -256,6 +254,8 @@ yum install percona-xtrabackup-80 ### 4.2 全量备份 +全量备份的具体步骤如下: + #### 1. 创建备份 Xtrabackup 全量备份的基本语句如下,可以使用 target-dir 指明备份文件的存储位置,parallel 则是指明操作的并行度: @@ -266,7 +266,7 @@ xtrabackup --backup --user=root --password --parallel=3 --target-dir=/data/bac 以上进行的是整个数据库实例的备份,如果需要备份指定数据库,则可以使用 --databases 进行指定。 -另外一个容易出现的异常是:Xtrabackup 在进行备份时,默认会去 `/var/lib/mysql/mysql.sock` 文件里获取数据库的 socket 信息,如果你修改了数据库的 socket 配置,则需要使用 --socket 参数进行重新指定,否则会抛出找不到连接的异常。备份完整后需要立即执行的另外一个操作是 prepare。 +另外一个容易出现的异常是:Xtrabackup 在进行备份时,默认会去 `/var/lib/mysql/mysql.sock` 文件里获取数据库的 socket 信息,如果你修改了数据库的 socket 配置,则需要使用 --socket 参数进行重新指定,否则会抛出找不到连接的异常。备份完整后需要立即执行的另外一个操作是 prepare 。 #### 2. 准备备份 diff --git a/notes/MySQL_复制.md b/notes/MySQL_复制.md index 1756b60..c2e0628 100644 --- a/notes/MySQL_复制.md +++ b/notes/MySQL_复制.md @@ -62,7 +62,6 @@ MySQL 的复制原理如下图所示:
- ### 2.2 配置步骤 首先主节点需要开启二进制日志,并且在同一个复制环境下,主备节点的 server-id 需要不一样: @@ -328,12 +327,12 @@ mysql> SHOW STATUS LIKE 'Rpl_semi_sync_slave_status'; #### 4. 可选配置 -半同步日志还有以下两个可选配置:一个是 rpl_semi_sync_master_wait_for_slave_count,它表示主节点需要至少等待几个从节点复制完成,默认值为 1,因为等待过多从节点可能会导致长时间的延迟,所以通常使用默认值即可。另一个常用参数是 rpl_semi_sync_master_wait_point ,它主要是用于控制等待的时间点,它有以下两个可选值: +半同步日志还有以下两个可选配置:一个是 `rpl_semi_sync_master_wait_for_slave_count`,它表示主节点需要至少等待几个从节点复制完成,默认值为 1,因为等待过多从节点可能会导致长时间的延迟,所以通常使用默认值即可。另一个常用参数是 `rpl_semi_sync_master_wait_point` ,它主要是用于控制等待的时间点,它有以下两个可选值: -- `AFTER_SYNC`(默认值):主服务器将每个事务写入其二进制日志,并将二进制日志同步到磁盘后开始进行等待。在收到从节点的确认后,才将事务提交给存储引擎并将结果返回给客户端。 -- `AFTER_COMMIT`:主服务器将每个事务写入其二进制日志并同步到磁盘,然后将事务提交到存储引擎,提交后再进行等待。在收到从节点的确认后,才将结果返回给客户端。 +- **AFTER_SYNC**(默认值):主服务器将每个事务写入其二进制日志,并将二进制日志同步到磁盘后开始进行等待。在收到从节点的确认后,才将事务提交给存储引擎并将结果返回给客户端。 +- **AFTER_COMMIT**:主服务器将每个事务写入其二进制日志并同步到磁盘,然后将事务提交到存储引擎,提交后再进行等待。在收到从节点的确认后,才将结果返回给客户端。 -第二种方式是 MySQL 5.7.2 之前默认方式,但这种方式会导致数据的丢失,所以在 5.7.2 版本后就引入了第一种方式作为默认方式,它可以实现无损复制 (lossless replication),数据基本无丢失,因此 rpl_semi_sync_master_wait_point 参数通常也不用进行修改,采用默认值即可。想要查看当前版本该参数的值,可以使用如下命令: +第二种方式是 MySQL 5.7.2 之前默认方式,但这种方式会导致数据的丢失,所以在 5.7.2 版本后就引入了第一种方式作为默认方式,它可以实现无损复制 (lossless replication),数据基本无丢失,因此 `rpl_semi_sync_master_wait_point` 参数通常也不用进行修改,采用默认值即可。想要查看当前版本该参数的值,可以使用如下命令: ```shell mysql> SHOW VARIABLES LIKE 'rpl_semi_sync_master_wait_point'; @@ -357,7 +356,6 @@ MMM (Master-Master replication manager for MySQL) 是由 Perl 语言开发的一 除了管理双主节点,MMM 也负责管理所有 Slave节点,在出现宕机、复制延迟或复制错误,MMM 会移除该节点的 VIP,直至节点恢复正常。MMM 高可用的架构示例图如下:
- MMM 架构的缺点在于虽然其能实现自动切换,但却不会主动补齐丢失的数据,所以会存在数据不一致性的风险。另外 MMM 的发布时间比较早,所以其也不支持 MySQL 最新的基于 GTID 的复制,如果你使用的是基于 GTID 的复制,则只能采用 MHA。 ### 5.2 MHA @@ -365,7 +363,6 @@ MMM 架构的缺点在于虽然其能实现自动切换,但却不会主动补 MHA (Master High Availability) 是由 Perl 实现的一款高可用程序,相对于 MMM ,它能尽量避免数据不一致的问题。它监控的是一主多从的复制架构,架构如下图所示:
- 在 Master 节点宕机后,其处理流程如下: 1. 尝试从宕机 Master 中保存二进制日志;