标签 数据一致性 下的文章

在 AI 和大数据应用中,采用对象存储与 GooseFS 等高性能缓存结合的多级存储架构,是平衡成本与性能的最优解。GooseFS 通过其客户端缓存能力,为计算任务提供了高吞吐与低时延的数据访问性能,已在训练加速、模型分发、离线分析等众多核心业务场景中已得到过充分验证。

尽管如此,该架构在业界普遍面临一个核心挑战:跨层数据一致性的管理成本。缓存的引入,意味着系统存在两个数据视图,若不加以管理,将直接导致以下三类严重问题:

  • 读不到新数据:上游在对象存储中新增或更新文件,缓存层若未同步,下游应用将无法访问。
  • 读到脏数据:缓存中的数据副本与持久化层不一致,导致计算结果错误。
  • 读到已删数据:持久化层通过生命周期等策略删除了数据,但缓存层副本依然存在,造成应用逻辑混乱。

传统方案依赖于业务方构建复杂的同步逻辑,这不仅增加了开发负担,也使得架构耦合度增高,尤其难以处理对象存储底层自动化的生命周期操作。为了从根本上解决这一难题,GooseFS 推出了全新的元数据发现功能。该功能通过与持久化存储层建立直接的元数据同步链路,能够主动发现并应用底层的变更。它将复杂的一致性维护工作从业务层下沉至缓存服务本身,让用户可以更纯粹、更无感地享受多级存储带来的性能优势。

元数据发现技术架构深度解析

1

GooseFS 元数据发现功能基于事件驱动架构进行构建,旨在实现缓存层与持久化层之间高效、可靠的元数据同步。其核心链路包含三个关键组件:

  1. 事件源 (COS Notify): 该模块负责捕获 COS 对象存储层的所有关键操作(如 PUT, DELETE)。它内置了事件过滤与容错机制,确保了从源头采集的元数据变更事件的完整性与可靠性。
  2. 持久化缓冲 (Message Queue): 利用高可用的消息队列作为事件的持久化缓冲层。消息队列解耦了事件的生产与消费,同时确保在 GooseFS Master 短暂不可用或处理能力饱和时,任何元数据变更事件都不会丢失。
  3. 智能事件处理 (GooseFS ActiveSync Service): 作为消费端,GooseFS 内核以批处理方式从消息队列中拉取事件。它内置了精密的处理逻辑,包括过滤由 GooseFS 自身写操作产生的冗余事件(避免反馈循环)、合并 Event 进一步提效发现流程,并最终触发文件级别的元数据同步,从而实现对外部新增、覆写、删除操作的及时感知。

2

为在分布式系统中实现可靠的事件处理,GooseFS 元数据发现解决了乱序与容灾的问题,保证元数据发现的时效性与可用性。

由于消息队列分区的特性及其他组件的分布式处理特性,事件的投递顺序无法得到严格保证。这对元数据操作是致命的,例如一个 DELETE 事件先于其对应的 PUT 事件被处理,将导致完全错误的状态。GooseFS 元数据发现以“通知”而非“指令”处理事件,并结合“窗口合并”优化,保证了元数据发现的准确性。在元数据发现的逻辑中,会将每一个事件视为一个“变更通知”。在处理事件时,它会主动请求 COS 以获取该对象的最终元数据状态,确保操作的幂等性与正确性。

同时,避免频繁请求 COS 带来的高延迟,GooseFS 引入了“窗口合并”机制。它会在一个极短的时间窗口内,将针对同一路径前缀的多个事件合并,通过一次批量查询完成状态确认。例如,一个“先删除后上传”的序列会被合并为一次同步操作,极大降低了远端访问频次,提升了同步时效。

考虑元数据发现服务的可靠性,为防止 GooseFS 节点故障等异常情况导致消息丢失,系统必须提供“至少一次”(At-Least-Once)的消费语义。GooseFS 元数据发现引入了事务性同步与持久化日志能力。GooseFS 为每个处理批次引入了唯一的事务ID(SyncTxId)。该 ID 会随着元数据变更一同被原子性地记录到日志中。当发生主节点切换或异常时,新的主节点可以从日志中恢复上一个已提交的 SyncTxId,并从该点继续消费,从而确保任何事件都不会被遗漏。

经过上述优化,元数据发现可实现近实时的元数据同步,在高 QPS 的 COS 请求负载下,元数据变更可在分钟级同步至 GooseFS。

此外,为确保服务的线上稳定性,我们部署了完善的监控、告警与数据对账能力,能够对同步链路中的任何异常进行及时感知和修复,保障了元数据变更的最终一致性。

在控制台开启元数据发现能力

将 GooseFS 集群升级至 1.5.1 及更新的版本后,将可以通过控制台命名空间入口,便捷开启元数据发现功能。具体步骤如下:

  1. 登录 GooseFS 控制台。
  2. 在左侧导航中,选择 GooseFS > 实例列表,进入 GooseFS 集群列表页面。
  3. 选择需要创建命名空间的 GooseFS 集群,进入集群详情页面,在侧边栏中单击命名空间,进入命名空间子页面。
  4. 在命名空间页面,单击新增命名空间 ,在弹窗中填写如下字段。

3

  • COS 请求事件支持以下选项:

    • 按事件类型选择:支持通过任意方式上传对象完成后触发、仅删除对象内容后触发。
    • 按具体事件选择:支持仅通过 COS PUT Object、POST Object、PUT Object - Copy、Complete Multipart Upload 接口调用触发。
  • 同步范围支持配置整个命名空间的挂载范围,或命名空间的挂载范围下的子目录。

若您需要修改元数据发现配置,可在命名空间列表页点击更新已配置的命名空间,重新编辑配置或关闭命名空间。

一、背景

得物经过10年发展,计算任务已超10万+,数据已经超200+PB,为了降低成本,计算引擎和存储资源需要从云平台迁移到得物自建平台,计算引擎从云平台Spark迁移到自建Apache Spark集群、存储从ODPS迁移到OSS。

在迁移时,最关键的一点是需要保证迁移前后数据的一致性,同时为了更加高效地完成迁移工作(目前计算任务已超10万+,手动比数已是不可能),因此比数平台便应运而生。

二、数据比对关键挑战与目标

关键挑战一:如何更快地完成全文数据比对

现状痛点:

在前期迁移过程中,迁移同学需要手动join两张表来识别不一致数据,然后逐条、逐字段进行人工比对验证。这种方式在任务量较少时尚可应付,但当任务规模达到成千上万级别时,就无法实现并发快速分析。

核心问题:

  • 效率瓶颈:每天需要完成数千任务的比对,累计待迁移任务达10万+,涉及表数十万张。
  • 扩展性不足:传统人工比对方式无法满足大规模并发处理需求。

关键挑战二:如何精准定位异常数据

现状痛点:

迁移同学在识别出不一致数据后,需要通过肉眼观察来定位具体问题,经常导致视觉疲劳和分析效率低下。

核心问题:

  • 分析困难:在比对不通过的情况下,比对人员需要人工分析失败原因。
  • 复杂度高:面对数据量庞大、加工逻辑复杂的场景,特别是在处理大JSON数据时,肉眼根本无法有效分辨差异。
  • 耗时严重:单次比对不通过场景的平均分析时间高达1.67小时/任务。

比数核心目标

基于以上挑战,数据比对系统需要实现以下核心目标:

  • 高并发处理能力:支持每天数千任务的快速比对,能够处理10万+待迁移任务和数十万张表的规模。
  • 自动化比对机制:实现全自动化的数据比对流程,减少人工干预,提升比对效率。
  • 智能差异定位:提供精准的差异定位能力,能够快速识别并高亮显示不一致的字段和数据。
  • 可视化分析界面:构建友好的可视化分析平台,支持大JSON数据的结构化展示和差异高亮。
  • 性能优化:将用户单次比对分析时间从小时级大幅缩短至分钟级别。
  • 可扩展架构:设计可水平扩展的系统架构,能够随着业务增长灵活扩容。

三、解决方案实现原理

快速完成全文数据比对方法

比数方法调研

待比对两表数据大小:300GB,计算资源:1000c


经过调研分析比数平台采用第二种和第三种相结合的方式进行比数。

先Union再分组数据一致性校验原理

假如我们有如下a和b两表张需要进行数据比对

表a:


表b:


表行数比较:

select count(1) from a ;
select count(1) from b ;

针对上面的查询结果,如果数量不一致则退出比对,待修复后重新比数;数量一致则继续字段值比较。

字段值比较:

第一步:union a 和 b

select 1 as _t1_count, 0 as _t2_count, `id`, `name`, `age`, `score`
from a
union all
select 0 as _t1_count, 1 as _t2_count, `id`, `name`, `age`, `score`
from b

第二步:sum(_t1_count),sum(_t2_count) 后分组

select sum(_t1_count) as sum_t1_count, sum(_t2_count) as sum_t2_count, `id`, `name`, `age`, `score`
from (
select 1 as _t1_count, 0 as _t2_count, `id`, `name`, `age`, `score`
from a
union all
select 0 as _t1_count, 1 as _t2_count, `id`, `name`, `age`, `score`
from b
) as union_table
group by `id`, `name`, `age`, `score`


第三步:把不一致数据写入新的表中(即上面表中sum_t1_count和sum_t2_count不相等的数据)

drop table if exists a_b_diff_20240908;
create table a_b_diff_20240908 as select * from (
select sum(_t1_count) as sum_t1_count, sum(_t2_count) as sum_t2_count, `id`, `name`, `age`, `score`
from (
select 1 as _t1_count, 0 as _t2_count, `id`, `name`, `age`, `score`
from a
union all
select 0 as _t1_count, 1 as _t2_count, `id`, `name`, `age`, `score`
from b
) as union_table
group by `id`, `name`, `age`, `score`
having sum(_t1_count) <> sum(_t2_count)
) as tmp

如果a_b_diff_20240908没有数据则两张表没有差异,比数通过,如有差异如下:

第四步:读取不一致记录表,根据主键(比如id)找出不一致字段并写到结果表中。

第五步:针对不一致字段的数据进行根因分析,如 json 、数组顺序问题、浮点数精度问题等,给出不一致具体原因。

哈希值聚合实现高效一致性校验

针对上面union后sum 再 group by 方式 在数据量大的时候还是非常耗资源和时间的,考虑到比数任务毕竟有70%都是一致的,所以我们可以先采用哈希值聚合比较两表的的值是否一致,使用这种高效的方法先把两表数据一致的任务过滤掉,剩下的再采用上面方法继续比较,因为还要找出是哪个字段哪里不一致。原理如下:

SELECT count (*),SUM(xxhash64(cloum1)^xxhash64(cloum2)^...) FROM tableA 
EXCEPT 
SELECT count(*),SUM(xxhash64(cloum1)^xxhash64(cloum2)^...) FROM tableB

如果有记录为空说明数据一致,不为空说明数据不一致需要采用上面提到union 分组的方法去找出具体字段哪里不一样。

通过哈希值聚合,单个任务比数时间从500s降低到160s,节省大约70%的时间。

找到两张表不一致数据后需要对两张的数据进行分析确定不一致的点在哪里?这里就需要知道表的主键,根据主键逐个比对两张表的其他字段,因此系统会先进行主键的自动探查,以及无主键的兜底处理。

精准定位异常数据实现方法

自动探查主键:实现原理如下

刚开始我们采用的前5个字段找主键的方式,如下:

针对表a的前5个字段 循环比对
select count(distinct id) from a 与 select count(1) from a 比较 ,如相等主键为id ,不相等继续往下执行
select count(distinct id,name) from a 与 select count(1) from a比较,如相等主键为id,name ,不相等继续往下执行
select count(distinct id,name,age) from a 与 select count(1) from a比较,如相等主键为id,name,age ,不相等继续往下执行,直到循环结束

采用上面的方法不一致任务中大约有49.6%任务自动探查主键失败:因此需重点提升主键识别能力。

针对以上主键探查成功率低的问题,后续进行了一些迭代,优化后的主键探查流程如下:

一、先采用sum(hash)高效计算方式进行探查:

1.先算出两张表每个字段的sum(hash)值  。

select sum(hash(id)),sum(hash(name)),sum(hash(age)),sum(hash(score)) from a 
union all 
select sum(hash(id)),sum(hash(name)),sum(hash(age)),sum(hash(score)) from b;

2.找出值相等的所有字段,本案例中为 id, name。

3.对id,name 可能是主键进一步确认,先进行行数校验,如 select count(distinct id,name) from a 的值等于select count(1) from a 则进一步校验,否则进入到第二种探查主键方式。

4.唯一性验证,如果值为0则表示探查主键成功,否则进入到第二种探查主键方式。

slect count(*) from ((select id,name from a ) expect (select id,name from b))

二、传统distinct方式探查:

针对表a的前N(所有字段数/2或者前N、后N等)个字段 循环比对:

1.select count(distinct id) from a与select count(1) from a比较 ,如相等主键为id ,不相等继续往下执行。

2.select count(distinct id,name) from a 与 select count(1) from a比较,如相等主键为id,name ,不相等继续往下执行。

3.select count(distinct id,name,age) from a 与 select count(1) from a比较,如相等主键为id,name,age ,不相等继续往下执行,直到循环结束。

三、全字段排序模拟:

如果上面两种方式还是没有找到主键则把不一致记录表进行全字段排序然后对第一条和第二条记录挨个字段进行分析,找出不一致内容,示例如下:

slect * from a_b_diff_20240908 order by id,name,age,score asc limit 10;


通过以上结果表可以得出两表的age字段不一致 ,score不一致(但按key排序后一致)。

如果以上自动化分析还是找不到不一致字段内容,可以人工确认表的主键后到平台手动指定主键字段,然后点击后续分析即可按指定主键去找字段不一致内容。

通过多次迭代优化找主键策略,找主键成功率从最初的50.4%提升到75%,加上全字段order by排序后最前两条数据进行分析,相当于可以把找主键的成功率提升到90%以上。

根因分析:实现原理如下

当数据不一致时,平台会根据主键找出两个表哪些字段数据不一致并进行分析,具体如下:

  • 精准定位: 明确指出哪条记录、哪个字段存在差异,并展示具体的源数据和目标数据值。
  • 智能根因分析: 内置了多种差异模式识别规则,能够自动分析并提示不一致的可能原因,例如:
  • 精度问题:如浮点数计算1.0000000001与1.0的差异。
  • JSON序列化差异:如{"a":1, "b":2}与{"b":2, "a":1},在语义一致的情况下,因键值对顺序不同而被标记为差异。同时系统会提示排序后一致。
  • 空值处理差异:如NULL值与空字符串""的差异判定。
  • 日期时区转换问题:时间戳在不同时区下表示不同。

  • 比对结果统计: 提供总数据量、一致数据量、不一致数据量及不一致率百分比,为项目决策提供清晰的量化依据。
  • 比数人员根据平台分析的差异原因,决定是否手动标记通过或进行任务修复。
  • 效果展示:

四、比数平台功能介绍

数据比对基本流程

任务生成:三种比对模式

  • 两表比对: 最直接的比对方式。用户只需指定源表与目标表,平台即可启动全量数据比对。它适用于临时比对的场景。
  • 任务节点比对: 一个任务可能输出多个表,逐一配置这些表的比对任务繁琐且易遗漏,任务节点比对模式完美解决了这一问题。用户只需提供任务节点ID,平台便会自动解析该节点对应的SQL代码,提取出所有输出表,并自动生成比对任务,极大地提升任务迁移比对效率。
  • SQL查询比对: 业务在进行SDK迁移只关心某些查询在迁移后数据是否一样,因此需要对用户提交的所有查询SQL进行比对,平台会分别在ODPS和Spark引擎上执行该查询,将结果集导出到两张临时表,再生成比对任务。

前置校验:提前发现问题

在启动耗时的全量比对之前,需要对任务进行前置校验,确保比对是在表结构一致、集群环境正常的情况下进行,否则一旦启动比数会占用大量计算资源,最后结果还是比数不通过,会影响比数平台整体的运行效率。因此比数平台一般会针对如下问题进行前置拦截。

  • 元数据一致性校验: 比对双方的字段名、字段类型、字段顺序、字段个数是否一致。
  • 函数缺失校验: 针对Spark引擎,校验SQL中使用的函数是否存在、是否能被正确识别,避免因函数不支持而导致的比对失败。
  • 语法问题校验: 分析SQL语句的语法结构,确保其在目标引擎中能够被顺利解析,避免使用了某些特定写法会导致数据出现不一致情况,提前发现语法层面问题,并对任务进行改写。

更多校验点如下:




通过增加以上前置校验拦截,比数任务数从每天3000+下降到1500+, 减少50% 的无效比数,其中UDF缺失最多,有效拦截任务1238,缺少函数87个(帮比数同学快速定位,一次性解决函数缺失问题,避免多次找引擎同学陆陆续续添加,节省双方时间成本)。

破解比数瓶颈:资源分配与任务调度优化

由于比数平台刚上线的时候只有计算迁移团队在使用,后面随着更多的团队开始使用,性能遇到了如下瓶颈:

1.资源不足问题: 不同业务(计算迁移、存储迁移、SDK迁移)的任务相互影响,基本比数任务与根因分析任务相互抢占资源。

2.任务编排不合理: 没有优先级导致大任务阻塞整体比数进程。

3.引擎参数设置不合理: 并行度不够、数据分块大小等高级参数。

针对以上问题比数平台进行了如下优化:

  • 按不同业务拆分成多个队列来运行,保证各个业务之间的比数任务可以同时进行,不会相互影响。
  • 根因分析使用单独的队列,与数据比对任务的队列分开,避免相互抢占资源发生“死锁”。
  • 相同业务内部按批次分时段、分优先级运行,保障重要任务优先进行比对。
  • 针对Spark引擎默认调优了公共参数、并支持用户自主设置其他高级参数。

通过以上优化达到到了如下效果:

  • 比数任务从每天22点完成提前至18点前,同时支持比数同学自主控制高优任务优先执行,方便比数同学及时处理不一致任务。
  • 通过优化资源队列使用方式,使系统找不到主键辅助用户自主找主键接口响应时间从58.5秒降到 26.2秒。

五、比数平台收益分享

平台持续安全运行500+天,每日可完成2000+任务比对,有效比数128万+次,0误判。

  • 助力计算迁移团队节省45+人日/月,完成数据分析、离线数仓空间任务的比对、交割。
  • 助力存储迁移团队完成20%+存储数据的迁移。
  • 助力引擎团队完成800+批次任务的回归验证,确保每一次引擎发布的安全及高效。
  • 助力SDK迁移团队完成80%+应用的迁移。

六、未来演进方向

接下来,平台计划在以下方面持续改进:

智能分析引擎: 针对Json复杂嵌套类型的字段接入大模型进行数据根因分析,找出不一致内容。

比对策略优化: 针对大表自动切分进行比对,降低比数过程出现因数据量大导致异常,进一步提升比对效率。

通用方案沉淀: 将典型的比对场景和解决方案能用化,应用到更多场景及团队中去。

七、结语

比数平台是得物在迁移过程中,为了应对海量任务、大数据量、字段内容复杂多样、异常数据难定位等挑战,确保业务迁移后数据准确而专门提供的解决方案,未来它不单纯是一个服务计算迁移、存储迁移、SDK迁移、Spark版本升级等需要的数据比对工具,而是演进为数据平台中不可或缺的基础设施。

往期回顾

1.得物App智能巡检技术的探索与实践

2.深度实践:得物算法域全景可观测性从 0 到 1 的演进之路 

3.前端平台大仓应用稳定性治理之路|得物技术

4.RocketMQ高性能揭秘:承载万亿级流量的架构奥秘|得物技术

5.PAG在得物社区S级活动的落地

文 /Galaxy平台

关注得物技术,每周更新技术干货

要是觉得文章对你有帮助的话,欢迎评论转发点赞~

未经得物技术许可严禁转载,否则依法追究法律责任。

聊聊复制过滤的那些隐藏陷阱

适合读者:DBA / 后端架构师 / 运维工程师

关键词:MySQL 复制、binlog_do_db、replicate_do_db、数据不一致

一、背景

在许多 MySQL 体系的数据库环境中,为了降低 binlog / relay log 日志量、缓解从库复制压力或减少同步延迟,往往会引入 主库 binlog 过滤从库复制过滤 的配置方案。 这些手段在一定程度上能够缓解资源消耗,但如果对其工作机制理解不充分,使用了不合理的过滤策略,极易引入隐蔽且不可逆的数据不一致风险。更为危险的是,这类问题在系统运行过程中通常不会立刻暴露,当业务侧发现数据异常时,往往已经无法通过常规手段进行补救。

本文将从 主库与从库两种过滤方式的实现机制入手,分析它们各自的优缺点及潜在风险。

二、复制过滤的判断逻辑

明确主库和从库在处理 SQL 和 row event 时的判断逻辑存在差异。

2.1 主库:是否写 binlog

判断发生在 SQL 执行完成之后。

binlog_do_db / binlog_ignore_db 仅根据当前会话的 USE db 判断,而不关注 SQL 实际操作的目标表。

2.2 从库:是否执行 relay log

判断发生在 SQL Thread 回放阶段

判断依据包括:

  1. replicate_* 复制过滤参数
  2. row event 真实的 db / table
  3. 表是否存在
  4. GTID 执行状态

结论:当主库和从库判断条件不一致时,即使 binlog 已记录,从库也可能未执行对应 row event,从而导致数据不一致。

三、主库过滤参数及风险

3.1 binlog_do_db / binlog_ignore_db 的行为示例

主库参数设置:
binlog_do_db = db1

主库执行SQL:
USE db1;
INSERT INTO db2.t2 VALUES (1);

执行结果:

  1. 主库 binlog 会记录该事务。
  2. 记录的 row event 目标表为 db2.t2,与 USE db1 不一致。

3.2 相关风险

  1. binlog 语义与实际操作对象脱钩
  2. 新从库或延迟从库无法补全缺失数据
  3. binlog 回放、审计等可能出现语义错误

四、从库复制过滤参数及风险

4.1 常用复制过滤参数

从库复制过滤前提条件就是主库的binlog必须完整。

  1. Replicate_Do_DB:
  2. Replicate_Ignore_DB:
  3. Replicate_Do_Table:
  4. Replicate_Ignore_Table:
  5. Replicate_Wild_Do_Table:
  6. Replicate_Wild_Ignore_Table:

4.2 复制或忽略库参数

说明:

Replicate_Do_DB/Replicate_Ignore_DB 这两个参数一个是只同步某些库,另一个是只忽略某些库,判断依据是relay log中记录use的数据库,并不是SQL语句实际操作的库。

测试:

  1. 从库配置复制过滤
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Do_DB = test1;
START SLAVE;
  1. 主库不配置过滤并执行操作
USE test;
CREATE TABLE TEST1.T1 LIKE TEST.T1;
INSERT INTO TEST1.T1 VALUES(1,'A');
  1. 验证数据

主库查看数据:

greatsql> SELECT * FROM TEST1.T1;
+----+-------+
| id | cname |
+----+-------+
|  1 | A     |
+----+-------+
1 row in set (0.00 sec)

从库查看数据:

greatsql> SELECT * FROM TEST1.T1;
ERROR 1146 (42S02): Table 'test1.t1' doesn't exist

结论:

从库报错表不存在,所以这样会导致从库同步数据失败,因为use的是test库。

风险:

多库写入(跨库SQL)、存储过程、触发器、应用层不指定USE库都会导致数据不同步的风险。

4.3 复制或忽略表参数

说明:

Replicate_Do_Table/Replicate_Ignore_Table 这两个参数一个是只同步指定表,另一个是只忽略指定表,两个参数都不支持通配符,可以精确到表但使用要确保库名表名正确。

测试:

  1. 从库配置复制过滤
STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Ignore_Table= (test1.t1_tmp);
START SLAVE;
  1. 主库不配置过滤并执行DDL操作
RENAME TABLE test1.t1 TO test1.t1_bak;
RENAME TABLE test1.t1_tmp TO test1.t1;
  1. 验证数据

主库查看数据:

greatsql> use test1
Database changed
greatsql> show tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| t1              |
| t1_bak          |
+-----------------+
2 rows in set (0.01 sec)

从库查看数据:

greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| t1_bak          |
| t1_tmp          |
+-----------------+
2 rows in set (0.01 sec)

结论:

由于主库执行rename操作将t1表更为t1_bak,t1_tmp更为t1,而从库忽略了t1_tmp导致sql同步失败,如果业务往新t1表插入数据从库就会因表不存在而断开复制链路,这是典型的“表级过滤被 DDL 绕过”事故。

风险:

  1. 未匹配的表默认全部不复制
  2. 新增表需要人工维护配置
  3. 与 DDL 操作存在天然冲突
  4. 如果过滤表过多添加在配置文件中只能一个参数匹配一个表

4.4 指定复制或忽略库参数

说明:

Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table 这两个参数一个是同步指定表,另一个是忽略指定表,两个参数都支持通配符,使用要确保库名表名没有通配符的隐患存在。

匹配方式%_(LIKE 语义)

测试:

  1. 从库配置复制过滤

忽略日志类表,不需要同步到从库。

STOP SLAVE;
CHANGE REPLICATION FILTER Replicate_Wild_Ignore_Table = (test1.log%);
START SLAVE;
  1. 主库不配置过滤并执行DML操作

一年后业务上线新业务test1.log_important

  1. 验证表结构

主库查看数据:

greatsql> USE test1
Database changed
greatsql> SHOW tables;
+-----------------+
| Tables_in_test1 |
+-----------------+
| log_important   |
+-----------------+
1 row in set (0.00 sec)

从库查看数据:

greatsql> USE test1
Database changed
greatsql> SHOW tables;
Empty set (0.00 sec)

结论:

log_importantlog_% 命中新业务数据未同步到从库,主从复制正常但是从库数据丢失,如果主库故障切换到从库才发现数据不一致就会导致故障,这是典型的“通配规则忽略业务表”事故。

风险:

  1. 匹配范围过宽
  2. 新表“自动进入过滤范围”
  3. DDL 影响范围不可控

五、最常见的踩坑配置

主库从库风险是否推荐
binlog_do_dbReplicate_Do_DB/Replicate_Ignore_DB跨库静默丢数据不推荐
binlog_do_dbreplicate_wild_ignore从库失效不推荐
binlog_ignore_db无过滤永久不可补不推荐
无过滤Replicate_Do_DB/Replicate_Ignore_DB跨库静默丢数据不推荐
无过滤Replicate_Do_Table/Replicate_Ignore_Table与DDL操作存在冲突,人工维护成本高可用,前提是过滤表数量少
无过滤Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table匹配范围过宽,通配符需要转义可用,前提是确保通配符不会影响其他表

六、最终建议(可直接当规范)

  1. 如果可以不做过滤就不做,做了就会有数据风险。
  2. 主库禁止做库表忽略,主库的binlog必须完整。
  3. 从库Replicate_Do_DB/Replicate_Ignore_DB最好不使用,业务操作并非DBA可以控制,但数据不一致就是DBA的锅。
  4. 从库Replicate_Do_Table/Replicate_Ignore_Table看似精确,但对 DDL 极其敏感,一旦表结构或命名发生变化,复制语义就可能在无感知的情况下被破坏。
  5. 从库Replicate_Wild_Do_Table/Replicate_Wild_Ignore_Table可以使用,库表都可做过滤,前提是一定要做转义,规避不应该发生的数据问题。
  6. 有条件可以使用GreatSQL 的gt checksum工具定期做主从数据校验。