本文将为您列举一些常见数据质量方面的场景,方便您排查是否存在符合的场景,根据对应解决方案解决数据同步质量问题。

背景信息

讲述数据集成数据同步的原理机制,理解数据同步的过程,进而对数据同步的执行效果有判断能力,判断数据同步效果具体包括:数据同步的数据量、目标端数据实际数量等。

同步原理

DataWorks数据集成的同步任务在执行时称之为一个Job,为了最大化提高数据同步的效率,任务在执行时会将split切分成多个子作业,每个子作业称之为一个Task。这些Task以单机或者多机的方式并发执行,每个Task读取一个数据区间内的数据,多个Task最终完成整体的数据同步业务。

说明 在数据同步过程中,涉及到读插件Reader,写插件Writer。
  • Reader插件连接具体的数据源头读取数据,并将数据放到内部缓冲队列,Writer插件从数据缓冲队列消费数据并将数据写出到目标存储中。
  • 由Reader插件和Writer插件完成具体的数据同步过程,同步插件会遵循数据源本身的数据读写协议,以及数据读写规则(如数据约束等)。因此在检查源头、目标数据源的实际同步效果时,会受到实际数据读写协议、读写规则方面的影响。

写端数据一致性排查

数据集成的Writer插件用来将源头读取到的数据写出至数据目标端,每一个目标存储类型都会有对应的Writer插件,Writer插件会根据用户配置的数据写出模式(包括冲突替换策略),使用JDBC或者对应数据源SDK最终将数据提交给目标存储。
说明 数据实际在目标端写出效果和数据内容,写出模式、目标表约束信息有关。
如果数据同步任务执行完成后,对于数据同步质量(数据条数、数据内容)有相关疑问,在写出端您可以尝试从下列常见情况对照排查:
原因问题描述 解决方案
写出模式选择导致Writer插件会使用选择的写出模式将源头数据在目标端执行重放,如果源头数据和目标表结构出现数据约束,会对应导致数据插入失败(脏数据)、数据插入忽略、数据插入替换等行为。使用正确的写出模式,评估数据内容约束是否存在,以及是否合理。以下介绍最常见的关系型数据库的写出模式(不同数据源类型写出模式不同):
insert into将数据使用insert into的SQL语句写出至目标端,如果写出数据和目标存储已有数据发生数据约束(主键冲突、唯一键约束、外键约束等),则来源数据会作为脏数据,不会实际写出至目标端。您可以留意同步日志中的脏数据条数和内容信息。
replace into将数据使用replace into的SQL语句写出到目标端。
  • 如果写出数据和目标存储已有数据发生数据约束(主键冲突、唯一键约束、外键约束等),数据库则使用来源数据替换目标表已有数据,在目标表存在多个数据约束的情况下,数据替换可能会替换掉多条目标记录
  • 如果写出数据和目标存储已有数据没有发生数据约束,数据库则将来源数据插入(和insert into行为限制一致)到目标存储中。
insert into on duplicate key update将数据使用insert into on duplicate key update的SQL语句写出到目标端。
  • 如果写出数据和目标存储已有数据发生数据约束(主键冲突、唯一键约束、外键约束等),数据库则使用来源数据update更新目标表已有数据行,在目标表存在多个数据约束的情况下,数据替换可能会失败并产生脏数据
  • 如果写出数据和目标存储已有数据没有发生数据约束,数据库则将来源数据插入(和insert into行为限制一致)至目标存储中。
insert ignore into将数据使用insert ignore into的SQL语句写出到目标端。
  • 如果写出数据和目标存储已有数据发生数据约束(主键冲突、唯一键约束、外键约束等),数据库会忽略来源数据不会写入到表中,数据写出动作为成功并且不会产生脏数据。
  • 如果写出数据和目标存储已有数据没有发生数据约束,数据库则将来源数据插入(和insert into行为限制一致)到目标存储中。
insert on conflict do nothing PostgreSQL协议族的数据库写出模式,类似于MySQL协议的insert ignore into。
  • 如果写出数据和目标存储已有数据发生数据约束(主键冲突、唯一键约束、外键约束等),数据库会忽略来源数据不会写入到表中,数据写出动作为成功并且不会产生脏数据。
  • 如果写出数据和目标存储已有数据没有发生数据约束,数据库则将来源数据插入(和insert into行为限制一致)到目标存储中。
insert on conflict do updatePostgreSQL协议族的数据库写出模式,类似于MySQL协议的 insert into on duplicate key update。
  • 如果写出数据和目标存储已有数据发生数据约束(主键冲突、唯一键约束、外键约束等),数据库则使用来源数据update更新目标表已有数据行,在目标表存在多个数据约束的情况下,数据替换可能会失败并产生脏数据。
  • 如果写出数据和目标存储已有数据没有发生数据约束,数据库则将来源数据插入(和insert into行为限制一致)到目标存储中。
copy on conflict do nothingPostgreSQL协议族的数据库写出模式,使用copy语法将数据写出到目标端,并且在遇到冲突时丢弃来源数据,数据冲突不会导致脏数据;如果写出数据和目标存储已有数据没有发生数据约束,数据库则将来源数据插入到目标存储中。
copy on conflict do updatePostgreSQL协议族的数据库写出模式,使用copy语法将数据写出到目标端,并且在遇到冲突时替换目标数据源已有数据,数据冲突不会导致脏数据;如果写出数据和目标存储已有数据没有发生数据约束,数据库则将来源数据插入到目标存储中。
merge into目前暂不支持。
脏数据 数据在写出至目标存储时失败,导致出现脏数据,进而目标数据源记录条数和源头数据不匹配。确认脏数据出现的原因,并解决脏数据问题,或者确认可否容忍忽略脏数据。
说明 若您任务不允许产生脏数据,您可以在任务配置 > 通道配置处,修改该阈值。配置任务脏数据阈值,详情请参见通过向导模式配置离线同步任务,关于脏数据认定,详情请参见基本概念
数据同步执行过程中就进行了数据查询部分Writer插件在数据同步完成前,会有同步完成才可见(比如Hive、MaxCompute(可配)等)、部分可见等行为。您需要在同步任务完成后再执行数据查询。
没有合理的节点依赖数据同步任务和数据分析任务没有配置合理的节点依赖,但是有数据依赖,比如下游使用max_pt找到MaxCompute的最大分区并读取分区的数据,但是最大分区对应的数据同步任务还未完成。上下游节点要建立节点依赖,避免使用max_pt这类的弱数据依赖,避免下游消费数据时数据不完整。
目标表、分区有多个同步任务同时在执行,并产生了干扰不合理的同步任务并发执行。
  • 如果是同节点多周期实例导致的冲突,建议配置任务调度自依赖,详情请参见依赖上一周期:本节点(自依赖)
  • 以MaxCompute、Hologres为例,2个任务写同一个分区数据(同步前清理分区数据 truncate),第一个任务写出的数据可能会被第2个同步任务清理掉。
  • 关系数据库配置了前置处理preSql、后置处理postSql等,第一个任务写出的数据可能会被第2个同步任务的前后置SQL干扰。
任务配置不能幂等执行一个任务重复运行多次最终的同步效果是一致等价的。如果任务配置不能幂等执行,而对任务又执行了多次重跑(包括成功后重跑,失败后重跑),可能会导致目标端数据又重复或者覆盖。不建议多次运行一个任务。
说明 若您配置了任务不可重跑,但是为保障任务产出的时效性,建议您为该任务设置监控报警,确保在任务异常时可以第一时间收到报警并及时处理异常,设置报警详情请参见:智能监控概述
错误的查询检查条件以MaxCompute为例,大多数情况下数据表都是分区表,分区值是DataWorks调度参数如$bizdate,常见的错误:
  • 调度参数没有合理的替换,即数据写出到$bizdate这个字面值分区中,而非实际的业务日期(如20230118中)。
  • 或者下游在查询使用数据时,分区表达式没有正确赋值,查询使用了错误的分区数据。
检查数据同步任务的调度变量表达式,即调度参数配置是否符合预期,调度时参数替换值是否符合预期。
数据类型、时区问题
  • 您的源头表数据类型、数据范围和目标表不一致,导致数据非预期的截断,或者数据写出脏数据失败。
  • 数据源头和目标端的时区不一致,导致两侧事件数据查询对比不一致。
  • 确认源头和目标类型、时区的差异。
  • 确认是否保持现状,或者修改目标数据类和时区参数。
目标端数据发生了变化目标数据源也在持续变化中,可能有其他系统程序在访问和更新目标数据源,导致目标数据源内容和源头不一致。一般符合业务预期,可以解释数据不一致原因即可。

读端数据一致性排查

数据集成的Reader插件用来连接具体的源头数据存储,抽取出待同步的数据并投递给同步写端。每一个存储类型都会有对应的Reader插件,Reader插件会根据用户配置的数据抽取模式(包括数据过滤条件、表、分区、列等),使用JDBC或者对应数据源SDK最终将数据抽取出来。
说明 数据实际读出效果和数据同步机制、源头数据是否变化、任务配置等有关。
如果数据同步任务执行完成后,对于数据同步质量(数据条数、数据内容)有相关疑问,在读取端您可以尝试从下列常见情况对照排查:
问题问题描述解决方案
源头数据在持续发生变化由于待读取范围的数据可能在持续变化中,因此实际同步到目标数据源的数据和源头最新数据可能不匹配。事务一致性以关系数据库为例,数据读取本质上是对源头数据源发起的数据查询SQL。任务配置并发读取时会切分出多个分片查询SQL,由于数据库事务一致性策略,每个查询SQL查询的都是当前提交时的数据快照,并且多个SQL并不在一个事务上下文内。因此在源头数据变化时会同步不到查询SQL之后的变化。这类原因导致的问题一般是符合预期的。这种情况一般多次运行同步任务每次同步的记录条数会有差异。
错误的查询检查条件
  • 以MySQL为例,可以配置数据抽取过滤where条件,在where条件中有调度参数变量,具体如gmt_modify >= ${bizdate},常见的错误是调度参数没有合理的替换,比如需要最近两天的数据却只过滤读取1天的数据。
  • 以MaxCompute为例,在读取分区表时往往会对分区参数配置变量表达式,比如pt=${bizdate},也容易出现分区参数未正确配置和替换的现象。
检查数据同步任务的调度变量表达式,即调度参数配置是否符合预期,调度时参数替换值是否符合预期。
脏数据数据在读取源头存储时失败,导致出现读端脏数据,进而目标数据源记录条数和源头对不上。
  • 确认脏数据出现的原因,并解决脏数据问题
  • 确认可否容忍忽略脏数据。
说明 读端脏数据一般比较少见,主要出现在半结构化类型的数据源中,比如OSS、FTP、HDFS等。

环境信息排查

问题解决方案
查询了错误或不完整的数据源、表、或者分区等。
  • DataWorks标准项目分为开发数据源、生产数据源,在开发环境运行任务使用开发数据源,在生产环境运行任务使用生产数据源,再对数据数量和内容比对时,需要确认下使用的数据源环境,避免开发、生产查询不一致。
  • 在实际生产业务当中,在线数据源往往有对应的预发或者测试环境,而实际同步任务使用的生产数据库和预发测试数据库不一致,需要进行数据检查对比是否有环境差异。
  • 在半结构化数据同步时往往涉及多个文件同步,您需要确认数据读取、写出的文件集合是否完整。
依赖产出未完成如果是周期产出的数据(周期的数据同步任务、周期的全增量数据融合Merge任务等),需要检查下对应的数据产出任务是否正常执行并完成。
说明 通用排查在您遇到数据质量方面的疑惑时,您可以尝试多次运行任务观察比对数据同步效果,也可以尝试切换源或者对目标数据源做对比测试,通过多次对比测试可以帮助您缩小问题排查范围。