mcpField
M
mariadb-replication-and-ha

mariadb-replication-and-ha

github.com/mariadb数据与数据库17126 次安装2 周前更新
代码仓库

关于 mariadb-replication-and-ha

为 MariaDB 运维与开发场景提供复制和高可用配置指导,覆盖异步、半同步复制与 Galera Cluster,并指出版本差异及常见 MySQL 配置误区。

主要功能

  1. 01比较三种复制与高可用方案
  2. 02说明 GTID 配置和故障切换
  3. 03介绍并行复制与多源复制
  4. 04梳理版本相关的复制改进
  5. 05纠正常见 MySQL 与 MariaDB 混淆

适用场景

  1. 01为读扩展或备份配置异步复制
  2. 02规划降低故障切换数据损失的方案
  3. 03部署 Galera 多主高可用集群
  4. 04排查复制延迟与 GTID 配置问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mariadb/skills --skill mariadb-replication-and-ha

安装后在 Claude Code 中输入/mariadb-replication-and-ha确认已加载。

详细介绍

MariaDB 复制和高可用性

最后更新:2026-06-24

MariaDB 提供三个级别的复制方案,可根据一致性和可用性要求选择:

方案一致性故障转移最适用于
标准异步复制最终一致手动或借助工具读扩展、备份、低延迟写入
半同步复制最终一致(与异步复制相同)手动或借助工具确保客户端收到确认前,副本已收到每次提交——限制故障转移时的数据丢失(只有使用 AFTER_SYNC 才能实现零数据丢失)
Galera Cluster同步(多主)自动零数据丢失的高可用性、多数据中心写入

要求: GTID 复制、半同步复制和并行复制(包括 optimistic 模式)均为内置功能,并且早在当前所有受支持的版本发布前就已提供——假定它们在 11.8 LTS 基准版本中可用。当前 LTS 版本为 11.8(2025 年 5 月 GA)。

默认上下文: 除非用户指定其他版本,否则假定使用 MariaDB 11.8 LTS。在相关情况下,可以建议使用标记为 12.x 或 13.0 的功能(包括作为升级选项),但务必说明最低版本要求——不要将其描述为 11.8 中可用的功能。

LLM 常见错误

你可能会看到的内容正确说法
CHANGE REPLICATION SOURCE TO、SOURCE_* 连接选项MariaDB 不支持 CHANGE REPLICATION SOURCE TO——应使用 CHANGE MASTER TO 和 MASTER_* 选项。自 10.5.1 起,START REPLICA / SHOW REPLICA STATUS 是规范写法;START SLAVE / SHOW SLAVE STATUS 是旧别名
replica_parallel_type,取值为 DATABASE 或 LOGICAL_CLOCKMariaDB 使用 slave_parallel_mode(optimistic / conservative / aggressive / minimal / none)——实现方式不同;MySQL 的模式设置不能直接迁移过来。线程池大小:slave_parallel_threads
MySQL GTID 格式或 gtid_mode=ON 语法MariaDB GTID 使用不同的格式(domain-server-seq)和不同的命令——MySQL 与 MariaDB 的 GTID 不兼容
MySQL Group Replication 或 InnoDB Cluster——START GROUP_REPLICATION、group_replication_* 变量、MySQL Shell dba.createCluster()MariaDB 没有 Group Replication,也没有 InnoDB Cluster——Group Replication 与 MariaDB 不兼容。同步多主的对应方案是内置的 Galera Cluster
“安装 Galera 插件”无需加载 Galera 插件——wsrep 支持已内置于 MariaDB 服务中。但集群仍需单独安装 Galera wsrep 提供程序库(galera-4 / libgalera_smm.so,通过 wsrep_provider 设置);在 12.3+ 中必须自行安装(参见 Galera Cluster 部分)
假设 Galera 中的 AUTO_INCREMENT 值连续递增Galera 按设计会在各节点的自动递增序列中产生间隔——切勿依赖数值连续
在 Galera 环境中使用 LOCK TABLES 或 GET_LOCK()Galera 不支持这些操作——请改用事务
把副本当作备份复制不是备份——主库上的 DROP TABLE 会立即复制到所有副本
Galera 集群中的无主键表Galera 中的所有表都必须有主键——对无键表执行 DELETE 会失败

标准异步复制

基础架构:一个主库,一个或多个副本。主库写入二进制日志;副本异步应用更改。

自 MariaDB 10.10 起,基于 GTID 的复制为默认设置(MDEV-19801),在 10.11 LTS、11.4 LTS 和 11.8 LTS 中也仍是默认设置。在副本首次启动、执行 RESET SLAVE,或执行省略 MASTER_USE_GTID 的 CHANGE MASTER TO 时,副本默认使用 slave_pos,而不是旧版的文件/位置方式。如果你的配置依赖旧行为,请显式设置 MASTER_USE_GTID=no。

-- On replica (10.10+ — MASTER_USE_GTID is optional, slave_pos is the default):
CHANGE MASTER TO
  MASTER_HOST='primary.host',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='password',
  MASTER_USE_GTID = slave_pos;

START SLAVE;

将副本提升为主库——过去会使用 MASTER_USE_GTID=current_pos 来包含本地写入的 GTID。current_pos 自 10.10 起已弃用(MDEV-20122)。请改用 MASTER_DEMOTE_TO_SLAVE=1:它会将旧主库的 gtid_binlog_pos 转换为 gtid_slave_pos,使降级后的服务器能够顺利连接到新主库,且不会出现竞态条件。

-- On the former primary, being demoted to a replica (10.10+):
CHANGE MASTER TO
  MASTER_HOST='new_primary.host',
  ...,
  MASTER_DEMOTE_TO_SLAVE=1;
START SLAVE;

从 MariaDB 13.0 起,CHANGE MASTER 还会重置 SHOW SLAVES STATUS 中的 Master_Server_Id。在较旧版本中,这个字段可能会在主库切换后保留过期值;在 13.0 之前的服务器上重新配置复制时,请明确检查该字段。

MariaDB GTID 格式

MariaDB GTID 包含三个部分:domain_id-server_id-sequence(例如,0-1-247)。

这不同于 MySQL 的 server_uuid:sequence 格式。两者不兼容——MariaDB 主库无法使用 GTID 复制到 MySQL 副本,反之亦然。

Domain ID(gtid_domain_id)用于标识独立的复制流。规则取决于写入是否并发,而非服务器数量——一个常见且有害的错误是给每台服务器分配自己的 domain ID:

  • **单个活动主库,包括简单故障转移:**所有服务器都将 gtid_domain_id = 0 保持默认值。在 A → B 这对服务器中,如果之后将 B 提升为主库(即变为 B → A),A 和 B 共享同一个 domain ID——不要给它们分配不同的 domain ID。
  • 多个主库并发更新(多源,或同一拓扑中的多主库):为每个并发更新的主库分配各自独立的 gtid_domain_id,这样每个流都能保持独立有序,并确保 GTID 自动副本切换正常工作。
-- Multi-source / multi-primary ONLY — each concurrently-written primary gets its own domain:
SET GLOBAL gtid_domain_id = 1;   -- on primary A
SET GLOBAL gtid_domain_id = 2;   -- on primary B

否则,为每台服务器分配不同的 domain ID 会使 GTID 位置变得复杂,并破坏单一有序的二进制日志流。请参阅全局事务 ID。

启用 gtid_strict_mode,并同时配置 domain ID——它可以在错误损坏副本位置之前,捕获 GTID 顺序错误或混用 domain 的问题:

# my.cnf on all servers:
gtid_strict_mode = ON

严格模式开启后,如果违反 GTID 顺序规则,副本会报错并停止,而不会悄悄应用顺序错误的事务。如果未启用严格模式,domain ID 配置错误可能一直未被发现,直到唯一的解决办法变成完整重新同步。

在多源复制中,复制命令和变量(START SLAVE、SHOW SLAVE STATUS,……)会作用于 default_master_connection 指定的连接。该变量过去仅限于会话级别——你必须在每个会话中先执行 SET SESSION default_master_connection='name',才能对相应源执行命令。从 MariaDB 13.0 起(MDEV-9247),也可以将其设为全局变量,从而为所有会话指定一个选定的命名连接作为默认连接。

并行复制

默认情况下,副本会串行应用事件——slave_parallel_threads 的默认值为 0,这意味着无论模式设置为何,并行复制开箱即用时均处于关闭状态。要启用它:

# my.cnf on replica:
slave_parallel_threads = 4          # must be > 0 to enable parallel apply
slave_parallel_mode = optimistic    # default since 10.5.1 — tries parallel, retries on conflict

optimistic 模式会并行应用事务,并在发生冲突时重试。对于无法接受冲突重试的严格工作负载,请使用 conservative。

与 MySQL 不同: MariaDB 的 slave_parallel_mode(optimistic、conservative 等)是其独立实现,并不等同于 MySQL 的 replica_parallel_type(DATABASE / LOGICAL_CLOCK)。直接复制粘贴 MySQL 的并行复制模式配置将无法生效。连接池大小由 slave_parallel_threads(别名 slave_parallel_workers)决定。

从 MariaDB 12.1 起,并行复制也适用于在两个 Galera 集群之间进行异步复制(MDEV-20065),这对跨数据中心或灾难恢复设置很有用,其中一个 Galera 集群是另一个集群的异步副本。

10.7–10.11 LTS 中的复制改进
  • 两阶段 ALTER TABLE 复制(10.8+、MDEV-11675、binlog_alter_two_phase)——选择启用:启用后,大型 ALTER TABLE 可以在主库仍在执行时就在副本上启动,而不必等到主库执行完毕后才启动,这可以减少架构变更期间的复制延迟。默认关闭。请将其视为高级/实验性功能——在生产环境中依赖它之前,应进行全面验证,而不是默认启用。
  • 支持 GTID 的 mariadb-binlog(10.8+、MDEV-4989)——--start-position 和 --stop-position 接受 GTID 列表,因此时间点重放工具可以直接指定 GTID,而无需使用 binlog 文件/偏移量对。(另外,默认开启的 --gtid-strict-mode 仅起保护作用:它会检查每个 domain 的 GTID 序列号是否单调递增,并在事件顺序错乱时中止;它不会启用 GTID 定位。)请参阅 mariadb-binlog。
  • slave_max_statement_time(10.10+、MDEV-27161)——限制副本 SQL 线程中单条语句的最长运行时间。如果复制的语句超出此限制,SQL 线程将因错误而停止(错误 3024),使运行缓慢或失控的查询显现出来,而不是让延迟在不知不觉中持续增长。它不会跳过该语句并继续执行——复制会暂停,直到你调查并重新启动。
  • mariadb-binlog --do-domain-ids / --ignore-domain-ids / --ignore-server-ids(10.9+、MDEV-20119)——提取 binlog 事件时进行 domain/server 过滤。
  • 多源复制的 CHANNEL 语法(10.7+、MDEV-26307)——MySQL 风格的 FOR CHANNEL 'name' 子句现在可用于 CHANGE MASTER TO、START SLAVE 等语句。
11.4 LTS 中的复制改进
  • 二进制日志磁盘空间全局限制(11.4+,MDEV-31404)——max_binlog_total_size(别名 binlog_space_limit,默认值 0 = 不限)会在所有二进制日志的总大小超过阈值时触发清理。将其与 --slave-connections-needed-for-purge(默认值 1)结合使用,可确保配置的副本断开连接时不会执行清理。新的状态变量 binlog_disk_use 会报告当前磁盘使用量。
  • 二进制日志的 GTID 索引(11.4+,MDEV-4991)——新增的 GTID 到位置索引,让重新连接的副本无需扫描整个二进制日志文件,即可直接定位到起始位置。由 binlog_gtid_index(默认值 ON)、binlog_gtid_index_page_size 和 binlog_gtid_index_span_min 控制。状态变量 binlog_gtid_index_hit / binlog_gtid_index_miss 可用于确认索引是否正在使用。
  • START SLAVE UNTIL 的 SQL_BEFORE_GTIDS / SQL_AFTER_GTIDS(11.4+,MDEV-27247)——支持更精细地停止复制,适用于分阶段故障转移或 PITR 重放。
  • 更详细的复制延迟字段(11.4+,MDEV-29639)——SHOW REPLICA STATUS 新增 Master_last_event_time、Slave_last_event_time、Master_Slave_time_diff,相比仅使用 Seconds_Behind_Master,更便于解读延迟(11.6 中的更新以此为基础,见下文)。
11.7 中的二进制日志性能改进
  • 提交大型事务不再冻结其他事务(11.7+,MDEV-32014)——此前,启用 log_bin 时提交非常大的事务,会让所有其他事务一直停滞,直到二进制日志写入完成。此瓶颈现已消除。
  • 二进制日志崩溃恢复期间异步回滚已准备的事务(11.7+,MDEV-33853)——存在大量已准备事务时,崩溃后的启动速度更快。
  • slave_abort_blocking_timeout(11.7+,MDEV-34857)——副本上的长时间运行查询阻塞复制进度超过阈值时,可将其终止。适用于偶尔运行长时间分析查询的只读副本。
监控复制延迟
SHOW SLAVE STATUS\G
-- Key fields:
-- Seconds_Behind_Master: estimated lag in seconds
-- Last_SQL_Error: last error stopping the SQL thread
-- Relay_Log_Pos vs Read_Master_Log_Pos: how far behind the relay log is

对于对延迟敏感的应用,当 Seconds_Behind_Master > 5 时发出警报。值为 NULL 表示复制未运行。注意:在空闲的主库上,Seconds_Behind_Master 可能会产生误导;应使用心跳工具(例如 pt-heartbeat)进行准确测量。

从 MariaDB 11.6(MDEV-33856)开始,Seconds_Behind_Master 的定义经过优化,SHOW ALL REPLICAS STATUS 新增了三列,并新增了 Information Schema 表 SLAVE_STATUS,可更细致地查看延迟情况(例如,分别测量 IO 线程和 SQL 线程的延迟)。

半同步复制

主库首先将每笔事务写入并 fsync 到自身的二进制日志中,确保事务在本地持久化;然后才会等待至少一个副本确认已收到该事务,再向客户端报告提交完成。rpl_semi_sync_master_wait_point 设置用于控制等待时机:使用 AFTER_SYNC 时,主库会在更改变为可见之前等待,因此故障转移到已确认的副本时不会丢失数据;使用 AFTER_COMMIT(MariaDB 的默认值)时,事务在等待之前已提交并可见,因此在这段时间内发生崩溃,故障转移时仍可能丢失该事务。请参阅半同步复制。

-- Enable on primary:
SET GLOBAL rpl_semi_sync_master_enabled = 1;

-- Enable on replica:
SET GLOBAL rpl_semi_sync_slave_enabled = 1;

如果在 rpl_semi_sync_master_timeout(默认值为 10 秒)内没有副本确认,主库会回退到异步模式。MariaDB 10.3 起内置此功能,无需插件。

适用场景:希望客户端收到提交成功响应之前,至少有一个副本已收到每笔事务,例如,为故障转移时的数据丢失设定上限(使用 AFTER_SYNC)。请注意,半同步只会延迟客户端所见的提交完成时间;它不会提高主库自身副本的持久性,而且在任何副本收到事务之前丢失的事务,无论是否使用半同步都会丢失。

Galera Cluster

多主同步复制——所有节点都接受读写操作,变更会在提交前通过集群认证。不存在单点故障。MariaDB 内置支持。

打包方式变更(12.3+): 默认情况下,Galera 库不再作为服务端软件包依赖项包含,也不再包含在 MariaDB 软件仓库中(MDEV-38744)。在 12.3+ 上设置 Galera 节点时,必须单独安装 galera-4(或发行版提供的等效软件包)。MariaDB 服务端仍原生支持 Galera——只有库的分发方式发生了变化。

开发者须知

如果不了解以下限制,在 Galera 中就会遇到问题:

所有表都必须有主键:

-- ✗ DELETE fails in Galera on keyless tables:
CREATE TABLE logs (message TEXT);

-- ✅ Always define a PK:
CREATE TABLE logs (id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY, message TEXT);

AUTO_INCREMENT 值会有间隔——Galera 为每个节点设置 auto_increment_increment 和 auto_increment_offset 以避免冲突,因此生成的 ID 不会连续。在 Galera 中,切勿依赖连续的自增值。

不支持 LOCK TABLES、GET_LOCK() 和 FLUSH TABLES {table list} WITH READ LOCK——请改用事务。注意:支持全局的 FLUSH TABLES WITH READ LOCK(不带表列表):

-- ✗ Not supported in Galera:
LOCK TABLES orders WRITE;
-- ✅ Use a transaction instead:
BEGIN;
SELECT ... FOR UPDATE;
UPDATE ...;
COMMIT;

仅支持 InnoDB——Galera 只复制 InnoDB 表。MyISAM 可通过 wsrep_replicate_myisam 获得实验性支持,但不建议用于生产环境。

事务大小限制——默认上限:128K 行(wsrep_max_ws_rows)和 2GB(wsrep_max_ws_size)。超大型事务会显著降低集群性能,可能需要调整配置。注意:在 MariaDB 13.0+ 中,binlog_row_event_max_size 的默认值为 64 KB(高于旧版的 8 KB)——在为写入繁重的工作负载设置复制事件大小时需要考虑这一点。

二进制日志必须采用 ROW 格式——不要在 Galera 集群运行期间更改 binlog_format。

冲突时重试写集(12.1+)——wsrep_applier_retry_count 控制应用器在报错前重试写集的次数。如果工作负载在繁忙的集群中遇到暂时性的认证冲突,可调整此值。

自动管理 SST 用户账户(11.6+,MDEV-31809)——Galera 现在会自动管理专用的 SST(状态快照传输)用户账户;你不再需要在每个节点上手动创建该账户并授予权限。

加入集群的节点 IP 允许列表(10.10+,MDEV-27246)——wsrep_allowlist 会限制哪些 IP 可以发起 SST/IST 请求,从而缩小 Galera 集群节点间流量的攻击面。

查询缓存: 后续 MariaDB 版本已移除查询缓存,而且从 MariaDB 10.1.2 起,Galera 就不需要查询缓存。现代安装无需采取任何操作。

陈旧读取与一致性

Galera 属于“虚拟同步”——一个节点上已提交的写入,在经过额外同步前,可能无法立即在另一个节点上看到:

-- Force a sync point before reading (performance cost):
SET SESSION wsrep_sync_wait = 1;
SELECT * FROM orders WHERE id = 42;

只有在需要严格的读后写一致性时才使用 wsrep_sync_wait。对于大多数读取,节点间的最终一致性(毫秒级)是可以接受的。

Galera 中的更新丢失

Galera 无法防止读-改-写模式中的更新丢失。请明确使用 SELECT ... FOR UPDATE:

-- ✗ Race condition — another node could modify between SELECT and UPDATE:
SELECT balance FROM accounts WHERE id = 1;
-- ... application logic ...
UPDATE accounts SET balance = new_value WHERE id = 1;

-- ✅ Lock the row at read time:
BEGIN;
SELECT balance FROM accounts WHERE id = 1 FOR UPDATE;
UPDATE accounts SET balance = new_value WHERE id = 1;
COMMIT;

复制不是备份

在主节点上执行 DROP TABLE 或 DELETE FROM table 会立即复制到所有副本。复制可以防范硬件故障,但无法防范意外的数据更改。请按独立于复制的计划定期维护备份(mariadb-dump、mariadb-backup)。

延迟复制是一种缓解措施——有意让副本延迟指定时间:

CHANGE MASTER TO MASTER_DELAY = 3600;  -- 1 hour lag

这样可以为意外更改提供恢复窗口,但仍不能替代备份。

时间点恢复(13.0 新增)——innodb_log_archive 变量(MDEV-37949)可让 InnoDB 将预写日志保留为连续的文件序列,而不是覆盖循环使用的重做日志。与基础备份结合使用后,此功能旨在支持 PITR 和增量备份,而无需仅依赖二进制日志。此功能是 13.0 滚动发行版中的新增功能(不属于 11.8 LTS 基线)——请将其视为近期新增功能,并在依赖它进行恢复前进行验证。

故障转移工具

  • 内置(无需代理)——Galera 故障转移是自动的:任何存活节点都会继续接受写入。对于异步/GTID 复制,MariaDB 可通过 GTID 和 MASTER_DEMOTE_TO_SLAVE 原生执行受控的主节点切换(参见上文的标准异步复制),通常由你自己的脚本或编排器驱动。
  • ProxySQL——开源(GPLv3)代理,广泛用于 MariaDB 的读写分离和连接池。
  • MaxScale——MariaDB Corporation 的代理,提供自动故障转移、读写分离和连接路由(可检测主节点故障并提升最新的副本;需要 GTID 复制)。非开源——近期版本(25.01+)为闭源商业软件,早期版本则采用源代码可用的 Business Source License(BSL),并非 OSI 开源许可证。mariadb.com/docs/maxscale

基本的 Galera 高可用无需代理;ProxySQL 或 MaxScale 可提供连接路由。

Galera 负载均衡需要了解集群状态的监控。 不要对所有 Galera 节点进行均等路由——处于 SST(完整数据复制)或失同步状态的节点可能仍在线并接受连接,但可能落后数百万个事务。请检查 wsrep_local_state:只有 4(Synced)才适合接收流量。ProxySQL 可配置健康检查来监控 wsrep_ 状态变量;MaxScale 使用 galeramon 监控器来实现这一目的。如果不根据状态进行路由,写入供体节点或失同步节点可能导致读取到过时数据或出现完整性问题。

资料来源

有关此处未涵盖的主题,请参阅 MariaDB 官方文档:mariadb.com/docs。

评论

支持 Markdown