人大金仓KFS数据同步系统中extractEvent()方法中的关键逻辑介绍

extractor模块中extractEvent()方法的关键逻辑介绍

关键字:

Kingbase FlySync、extractor、extractEvent

关于extractEvent()方法

extractEvent()方法属于KFS数据同步系统中extractor模块中重要的一个方法。Extractor模块在数据抽取中的骨干逻辑包括configure、prepare、setLastEvent、extract和release五个部分,在KingbaseXLogicalExtractor类中分别对应五个方法,其中configure()方法负责完成对extractor的初始化配置,加载上下文相关信息;prepare()方法为抽取开始进行准备,通常的为初始化数据库连接、设置环境变量、获取元信息等;setLastEvent()方法负责设置开始抽取的断点位置,可以来源于用户的输入设置或者是KFS自身记录;extract()方法负责实现进行增量数据抽取的核心逻辑;release()方法负责释放相关资源,结束抽取。其中extractEvent()方法在extract()方法调用,返回值为DBMSEvent,数据抽取获得可以在流水线中流转的DBMSEvent主要在此方法中进行解析和封装。

extractEvent()方法执行流程

从代码逻辑上来看,extractEvent()方法执行流程如下,其中的关键流程在while循环中执行:

  • 通过一个tablePatternsUpdated标志判断是否是表样式的更新
  • 通过一个try-catch语句块判断流的状态
  • 准备参数执行以cancelled为判断的循环
  1. 在同步流中获取rowMsg,其中rowMsg可以看做是对WAL日志的进行映射的实体类,rowMsg中存储了抽取数据的相关信息。
  2. 判断rowMsg状态,获取rowMsg基础信息,包括lastRow,transactionId等。
  3. 执行一个以lastRow为判断的if语句,表示获取的信息是否是数据的最后一条,如果是表示事务已经完成,进行提交。
  4. 判断是否是分区表,分区表是将数据量大的表拆分若干个小表,当获取到的是分区表的子表时,需要获取其父表。
  5. 从表中解析DDL语句
  6. 解析数据的增删改语句
  7. 执行if (minRowsPerBlock > 0 && dataArray.size() >= minRowsPerBlock)判断是否对大事务进行分片拆分。

关键逻辑介绍

  • DBMSEvent封装逻辑

DBMSEvent是数据在工作流中流转的关键数据结构,在 Java源码中对应个实体类,其主要参数有:

String id;

LinkedList metadata;

ArrayList data;

boolean lastFrag;

Timestamp sourceTstamp;

LinkedList options;

其中id表示本地事务Id; metadata存储了关于此事务的一系列name/value键值对;data表示一系列关于数据更新的sql语句;lastFrag表示在分片中是否最后一个分片; sourceTstamp表示事务提交时间。这其中包含抽取数据的结构为又DBMSData组成的ArrayList。DBMSData一个重要的子类是RowChangeData,RowChangeData类中包含有一个枚举类,列举了数据操作的各种类型,包括增删改查,还包含一个由OneRowChange组成的ArrayList。OneRowChange是存储抽取数据的最小单元,其包含了两个重要的内部类columnSpec和columnVal,columnSpec表示对数据库表中列的规格参数说明,columnVal主要记录列值。OneRowChange的变量主要包括三类,第一类是抽取数据的基本信息,包括数更新类型和更新数据所属的模式名和表名;第二类是关于列参数规格说明的各种ArrayList,包括KeySpec、beforeImageSpec和columnSpec;第三类是关于列值的各种Array、List,包括keyValues、beforeImageValues和columnValuses。从WAL抽取的数据存储在OneRowChange中,经层层封装最终打包成DBMSEvent返回给调用者。

  • 大事务拆分逻辑

从WAL中抽取出来的数据更新信息通过DBMSEvent封装首先存储在内存中,当一个事务中数据量过大时,会对内存造成非常大的压力,甚至会使内存溢出,因此,需要对一个由非常多语句组成的大事务进行拆分,将一个大事务拆分成几个小的分片事务,每一个分片都有对应的seqno,和lastFrag标识,一个事务中的不同分片seqno相同,最有一个分片lastFrag标记为true,其余标记为fasle。当数据量达到参数minRowsPerBlock所设置的最小数据量时,if (minRowsPerBlock > 0 && dataArray.size() >= minRowsPerBlock)判断生效,执行新建DBMSEvent操作,并将lastFrag置为false,此时表示大事务分片开启,此分片属于同一个事务,将inTransaction置为true;当解析执行到lastRow时,表示当前事务执行到最后一条语句,此时执行新建DBMSEvent操作,将lastFrag置为true,此时表示当前分片数大事务最后一个分片,将inTransaction置为false,表示当前大事务分片结束。

  • DDL解析逻辑

由于kingbase复制槽获取增量数据,复制槽实际上是从WAL日志获取增量,由于WAL日志中没有记录DDL的信息,因此无法实时获取增量DDL。此时系统通过事件触发器的能力,获取到用户执行的DDL,然后将DDL插入到中间表中,当KFS获取到该中间表的数据时,就将该数据的特定字段当做DDL。Extractor模块通过prepar流程中的createTableAndFucForDDL()方法创建中间表、函数和触发器;其中记录DDL语句的中间表名称为trep_sync_ddl,默认存储在flysycn_servicename(源端服务名称)模式下。trep_sync_ddl表中一共包含exe_time、tg_tag、search_path和command四个字段,其中command存储的即为DDL操作的sql语句。在extractEvent()方法中,当解析的模式名和表名与系统名匹配成功后开始对ddl语句进行解析,解析首先排除delete语句,随后获取StatementData,StatementData类定义了必须被同步的sql语句,在StatementData中获取statementQuery,statementQuery系统需要执行的sql语句,随后进行判断,排除具有特殊标记的语句,排除tg_tag不匹配的语句,排除重复语句。最终将经过过滤的StatementData封装到dataArray,完成对DDL语句的解析。

参考资料

KFS项目源代码

你可能感兴趣的:(数据库,金仓数据库,人大金仓,python)