GBase 8a
其他
文章

节点替换期间,集群为什么必须处于只读模式?如果允许DDL或DML操作,可能引发什么问题?

发表于2026-03-20 10:30:205次浏览4个评论

节点替换期间,集群必须处于只读模式,这是由 节点替换操作的本质——对集群物理拓扑和元数据进行外科手术式变更 所决定的。如果允许 DDL 或 DML 操作,将引发数据不一致、操作冲突甚至替换失败等一系列严重问题。

一、为什么必须处于只读模式?

节点替换是一个复杂的、多步骤的分布式状态变更过程,其核心步骤包括:

  1. 设置节点状态为 UNAVAILABLE

     

  2. 删除故障节点的 fevent 日志。

     

  3. 切换集群模式为 READONLY

     

  4. 执行替换脚本,进行数据同步和元数据切换。
  5. 切换回 NORMAL 模式。

将集群置于 READONLY 模式,是为了在整个手术过程中创造一个稳定、静止的“手术环境”,具体原因如下:

  1. 保证数据分布映射的静态性
    • 替换的核心是修改数据分布表(Distribution),将故障节点的IP从映射中移除,并用新节点的IP替换。这相当于在修改数据的“住址簿”。
    • 如果在修改“住址簿”的同时,数据还在频繁地“搬家”(DML)或“改建房屋”(DDL),那么新旧映射关系将瞬间错乱,无法保证一致性。
  2. 确保数据同步的基线一致
    • 替换过程中,需要将故障节点上的数据(从其备份分片)同步到新节点上。这个同步操作需要一个明确的、静止的数据快照作为基线
    • 如果同步过程中源数据还在被修改,那么同步过去的数据可能一部分是旧状态,一部分是新状态,导致数据损坏或丢失
  3. 避免与内部恢复机制冲突
    • 集群在替换期间会启动内部的 gcrecover 等进程来恢复和同步数据。这些进程与用户发起的 DML/DDL 会竞争相同的锁和资源,极易导致死锁或操作失败。

“替换过程中的集群模式变化:NORMAL --> READONLY --> NORMAL


 

“替换期间:集群模式为READONLY,只允许进行查询操作,不允许任何dml、ddl以及加载操作。”

二、如果允许DDL/DML操作,会引发什么问题?

允许写操作将直接破坏上述的“手术环境”,导致灾难性后果:

问题1:数据严重不一致(最核心的风险)

  • 场景:在数据从节点A同步到节点B的过程中,用户更新了节点A上的某行数据。
  • 后果:节点B最终获得的数据是更新前的旧版本。集群中从此存在两个不同版本的数据,破坏主备一致性。后续查询可能读到旧数据,且该不一致状态可能永远无法自动修复。

问题2:DDL与替换操作直接冲突,导致替换失败或元数据损坏

  • 场景:替换脚本正在删除故障节点的元数据,同时用户执行了一个 ALTER TABLE 操作。
  • 后果
    • 锁冲突:DDL需要获取表的集群锁,而替换操作也可能持有系统级锁。两者冲突会导致一方失败(通常是用户操作报错)。
    • 元数据分裂:DDL可能修改了表的分布信息,而替换脚本基于旧的分布信息进行操作,导致新节点加入后,表的分布映射出现逻辑错误,部分数据可能“找不到家”。

问题3:事务与恢复流程交织,引发死锁

  • 场景:用户事务T1更新了某行数据(持有行锁),同时替换触发的 gcrecover 进程也需要修复该行数据(申请相同锁)。
  • 后果:形成分布式死锁。替换进程被挂起,导致替换超时失败,集群可能卡在 READONLY 状态无法恢复。

     

  • 如果 replace.py 进程被强杀,可能导致“集群状态处于READONLY状态无法自行恢复正常”。

     

问题4:写入丢失或重复

  • 场景:在切换分布表版本的瞬间(旧表删除、新表生效),一个 INSERT 操作正在执行。
  • 后果:该写入可能只作用于即将失效的旧分布表,导致数据写入后瞬间“消失”。或者,由于映射混乱,数据被错误地写入到两个地方。

三、集群的容错设计:gcluster_mode_wait 参数

GBase 8a 并非粗暴地直接拒绝写操作,而是提供了一个优雅的容错参数:

  • gcluster_mode_wait(在 gbase_8a_gcluster.conf 中):
    • = 1 (默认):替换期间,用户的写操作会自动等待,直到替换完成、集群切回 NORMAL 模式后,再继续执行。这保证了业务SQL的连续性,不会因替换而报错。

       

    • = 0:替换期间,写操作直接报错退出。

       

  • “注:参考集群配置文件...中的gcluster_mode_wait参数:0: 表示节点替换过程中出现写操作报错退出。1: (默认)表示节点替换过程中,让用户的写操作无限等待,直到节点替换完成,再继续执行写操作。”

这个设计至关重要:它意味着对于应用来说,节点替换是透明且无感知的(除了可能的延迟)。应用不需要修改代码,只需等待即可。

四、总结

节点替换期间强制只读模式,是分布式数据库在提供高可用性能力时,为保障数据强一致性而必须做出的权衡

  • 根本原因:替换是物理拓扑变更,必须在一个数据静止的瞬间快照上完成,否则无法保证变更前后数据映射和内容的一致性。
  • 引发问题:若允许写操作,会导致数据不一致、元数据损坏、操作死锁、写入丢失
  • 最佳实践:利用默认的 gcluster_mode_wait=1,让业务写入优雅等待,实现运维操作对业务的零中断影响

这体现了GBase 8a运维设计的一个核心思想:通过内部的、短暂的、受控的“只读窗口”,来换取全局的、长期的数据安全和服务连续性

评论

登录后才可以发表评论
nodddddd发表于 4个月前
学到了
爱笑的眼睛发表于 2个月前
来了
用户头像
柒柒天晴发表于 2个月前
厉害了
用户头像
山佳发表于 2个月前
来了