Loading [MathJax]/jax/input/TeX/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >DBus数据库表结构变更处理方案

DBus数据库表结构变更处理方案

作者头像
宜信技术学院
修改于 2019-07-11 08:13:08
修改于 2019-07-11 08:13:08
1.8K0
举报
文章被收录于专栏:宜信技术实践宜信技术实践

导读:DBus是我们要介绍的在敏捷大数据(Agile BigData)背景下的第一个平台。企业中大量业务数据保存在各个业务系统数据库中,为同时解决数据同步的一致性和实时性问题,DBus(数据总线)平台应运而生。

DBus专注于数据的实时采集和实时分发,是一种基于日志的解决方案,同时能够提供消息订阅的方式给下游系统使用。本篇文章主要介绍在DBus的设计中,它是如何处理表结构变更及其带来的各种问题的。

数据库表结构变更在软件产品快速迭代过程中是普遍存在的现象,抽取数据库中的数据是DBus最重要的功能之一,那么对于数据库中表结构变更及其带来的各种问题,DBus是如何处理的呢? (本文仅讨论DBus for Oracle的实现方案)

贴源输出是DBus的基本设计原则之一,通过解析后的数据库日志获取数据转换成UMS输出到Kafka,当表结构发生变更时DBus必须能够及时的调整输出UMS的结构,以确保和数据库中表结构保持一致,这里有两个问题需要解决:

1)如何感知表结构变更?

2)表结构变更后,新的表结构要如何与OGG输出的二进制数据关联?

一、感知表结构变更

对于感知表结构变更,Oracle已经通过DDL trigger为我们提供了很好的支持,接下来我们要考虑的是如何让DBus感知到表结构变更? 我们讨论出以下两种方案:

1.1 RPC方案

在DDL trigger中调用DBus提供的REST服务,将表结构变更事件发送给DBus。

该方案思路简单容易实现,但也有一些明显的弊端,比如DBus需要提供高可用、低延时的REST服务,否则可能会使数据库中的DDL操作变得缓慢甚至执行出现错误; DBus 的REST服务器对有数据实时同步需求的所有数据库都必须开通防火墙策略,这将给DBus的部署带来很大的麻烦。

1.2 OGG实时同步方案

在DDL trigger中将表结构变更事件存储到一张Event表里,然后通过OGG实时的从日志中将数据同步到Kafka,从而感知表结构变更事件。

该方案实现相对复杂但具有很多优点,比如对数据库的侵入性相对较小,DDL执行时只是将数据写入到Event表中,相对网络通信来说,其延时更低、可靠性更高;更明显的优势是这种方案基于数据库日志实现,能够使用Event表的数据,严格的将表结构变更前后的数据区分开。

举例来说,对于表:test来说,依次执行insert → alter → insert 三个操作,因为OGG读取数据库日志存在延时,如果利用RPC方案,可能出现这样的一种情况:DBus REST服务接收到alter事件之后,第一个insert的记录才被OGG捕获并发送给DBus,此时DBus会认为这条数据中包含alter变化后的数据。这是一个很严重的问题,而OGG实时同步方案无论数据还是时间均通过OGG读取日志的方案实现,可以完美的避免这种问题的发生。

对比两种方案OGG实时同步方案优势明显,最终我们采用此方案。

然而,采用这种方案也并非一帆风顺,按照该方案的总体思路实现以后,我们遇到了一个很奇怪的问题:通过DDL trigger写到Event表中的数据无法被OGG读取,在经历多番尝试无解之后,我们试图到OGG的文档中寻找答案,而最终的结果却是:DML or DDL operations performed from within a DDL trigger are not captured.

这个答案让问题变得更棘手,但这是最佳方案,我们没有理由放弃。于是我们开始尝试在DDL trigger中调用存储过程,在存储过程中执行Event表的insert操作,但由于存储过程和DDL trigger仍然属于同一个事务,因此Event表的数据依然不能被OGG捕获,但通过这个尝试我们觉得只要在另外一个事务中写Event表就能解决我们面临的问题,于是我们又想到了RPC,但RPC缺点太过明显。那么有没有其他可以替代的方案呢?

实际上oracle数据库里可以使用多种语言来编写存储过程,Oracle 8i开始支持java编写存储过程,于是我们立即开始实现java存储过程,通过JDBC连接数据库实现Event表的写入并提交事务,最终通过实践验证了这种办法的可行性,OGG成功的获取到了DDL trigger调用java存储过程写入到Event表的数据。

然而,这种实现并不算完美。当我们在生产环境部署DDL trigger的时候,发现数据库服务器中并没有安装执行java所需要的组件,每次部署都需要DBA同学安装执行java存储过程所需要的组件,我们试图找到一个不使用java存储过程的方案。这里要感谢韩锋老师对我们的帮助,韩老师在听了我 们的实现原理之后,启发我们自治事务应该可以解决这个问题,我们即刻动手开始改造DDL trigger,使之支持自治事务,经过改造之后该方案才算完美,最终实现逻辑如图1所示:

二、处理表结构变更事件

DBus已经具备通过事件方式感知表结构变更的能力,接下来详细说明一下表结构变更事件该如何处理。

下图描述了Event的完整处理流程:

Event中描述了发生结构变更的表名、该表所属的schema以及元数据版本号,DBus接受并解析Event之后,根据表名、schema以及版本号调用元数据抓取模块获取该表的元数据(包括表的字段类型、长度以及注释等)信息,实际上DDL trigger和alter语句在一个事务中执行,这样在trigger执行过程中无法从oracle的数据字典里获取到修改之后表结构元数据,我们写入到meta_history表中的元数据只是执行alter语句之前的元数据信息(因此我们给这个表取名为table_meta_his),要得到完整的元数据信息需要联合table_meta_his和数据字典进行查询,示意SQL如下:

这个SQL的结果有两种可能:

1)只包含all_tab_cols视图中的数据

2)既包含all_tab_cols视图中的数据又包含table_meta_his表的数据(is_current字段的作用是区别该字段的来源)

结果A表明在table_meta_his表中没有找到数据,这说明在生成表结构变更Event至元数据抓取程序成功获取元数据期间没有再次发生表结构变更,结果B则说明在此期间又发生过一次或多次表结构变更。

为什么要使用union all?

单独使用上图中的两个SQL可能导致元数据获取程序获取到错误的结果,例如:接到表结构变更Event 1后,我们调用SQL 1 查询table_meta_his结果集为空,在调用SQL 2之前表结构再次发生变更(命名为Event 2),这种情况下我们通过SQL 2 查询到的结果实际上是再次变更后的结果,使用这个结果产生的元数据去解析Event 1和Event 2之间的数据,如果两次表结构变更是不兼容的,那么必然会导致解析失败。

感知表结构变更以及处理表结构变更事件的最终目的是能够生成正确的输出结果,其中的更多细节以及实现可以参考:

https://github.com/BriData/DBus

作者:张玉峰

来源:宜信技术学院

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
史上最全的OGG基础知识整理
GoldenGate软件是一种基于日志的结构化数据复制软件。GoldenGate 能够实现大量交易数据的实时捕捉、变换和投递,实现源数据库与目标数据库的数据同步,保持亚秒级的数据延迟。
JiekeXu之路
2019/06/19
10.5K0
史上最全的OGG基础知识整理
​第十击 | 数据库理论20题
平时使用 char 类型定义字段时,往往会指定其长度 M,即 char(M)。其实 M 指的是字符数,即这个字段最多存储多少个字符,M 可不指定,默认为 1,范围是[0,255],单个字母、数字、中文等都是占用一个字符。utf8 字符集下一个中文字符占用3个字节。这个怎么去测试呢。举个例子
我是程序员小贱
2021/10/09
6680
​第十击 | 数据库理论20题
跨数据库同步方案汇总怎么做_国内外数据库同步方案
Datax 一般比较适合于全量数据同步,对全量数据同步效率很高(任务可以拆分,并发同步,所以效率高),对于增量数据同步支持的不太好(可以依靠时间戳+定时调度来实现,但是不能做到实时,延迟较大)。
全栈程序员站长
2022/11/07
3.4K0
跨数据库同步方案汇总怎么做_国内外数据库同步方案
innodb锁机制探究(一)---元数据锁
元数据锁(metadata lock,简称MDL)是用来保证并发访问数据库对象场景下的一致性而设定的。简单理解,它是为了管理数据库元数据而产生的一种锁。关于元数据锁,有以下的知识点需要注意:
AsiaYe
2019/11/20
1.1K0
数据库结构同步之通过DDL触发器记录数据库结构的变更
1.FOR DROP_TABLE, ALTER_TABLE ,CREATE_TABLE   这里只记录了这几个事件
liulun
2022/05/09
7740
MySQL数据库备份命令mysqldump参数详解
MySQLdump对于MySQL数据库备份是有一个很好用的命令,并且是MySQL自带的。 -d:只备份表结构,备份文件是SQL语句形式;只备份创建表的语句,插入的数据不备份。
星哥玩云
2022/08/16
7.5K0
数据库表结构设计方法及原则「建议收藏」
http://www.cnblogs.com/RunForLove/p/5693986.html
全栈程序员站长
2022/09/30
2.8K0
数据库表结构设计方法及原则「建议收藏」
这样做,免费从Oracle同步数据
刘伟,云和恩墨软件开发部研究院研究员;前微博DBA,主要研究方向为开源数据库,分布式数据库,擅长自动化运维以及数据库内核研究。
数据和云
2019/05/13
2.2K0
这样做,免费从Oracle同步数据
mysql databus_DataBus概述
Databus是一个低延迟、可靠的、支持事务的、保持一致性的数据变更抓取系统。由LinkedIn于2013年开源。Databus通过挖掘数据库日志的方式,将数据库变更实时、可靠的从数据库拉取出来,业务可以通过定制化client实时获取变更并进行其他业务逻辑。
全栈程序员站长
2022/11/02
7910
如何设计实时数据平台(技术篇)
导读:实时数据平台(RTDP,Real-time Data Platform)是一个重要且常见的大数据基础设施平台。在上篇(设计篇)中,我们从现代数仓架构角度和典型数据处理角度介绍了RTDP,并探讨了RTDP的整体设计架构。本文作为下篇(技术篇),则是从技术角度入手,介绍RTDP的技术选型和相关组件,探讨适用不同应用场景的相关模式。RTDP的敏捷之路就此展开~
宜信技术学院
2019/06/28
2.2K0
大数据总线平台DBus设计思路与工作原理
企业中大量业务数据保存在各个业务系统数据库中,过去通常的同步数据的方法有很多种,比如:
宜信技术学院
2019/07/18
4.1K0
大数据总线平台DBus设计思路与工作原理
三歪连MySQL大表怎么DDL变更都不懂
随着业务的发展,用户对系统需求变得越来越多,这就要求系统能够快速更新迭代以满足业务需求,通常系统版本发布时,都要先执行数据库的DDL变更,包括创建表、添加字段、添加索引、修改字段属性等。
敖丙
2020/12/09
2.5K0
三歪连MySQL大表怎么DDL变更都不懂
单表超 100000000 条记录的数据库结构变更,你能做到在线平滑变更吗?
Percona-Toolkit 源自 Maatkit 和 Aspersa 工具,这两个工具是管理 MySQL 的最有名的工具,但 Maatkit 已经不维护了,全部归并到 Percona-Toolkit。Percona Toolkit 是一组高级的命令行工具,用来管理 MySQL 和系统任务,主要包括以下功能:
iMike
2019/10/14
3.5K0
拒绝停服,随时回退:MS SQL 到 PostgreSQL 的无缝数据库双向迁移方案
本项目旨在将关键业务应用从 MS SQL 数据库平滑迁移至 PostgreSQL。
Tapdata
2025/06/09
1810
拒绝停服,随时回退:MS SQL 到 PostgreSQL 的无缝数据库双向迁移方案
MySQL在线DDL修改表结构的简单经验分享
摘 要 在线DDL修改生产环境的大表一直是运维、DBA一个很头痛的问题,本文分享一些相关经验,希望对还在头痛的同学能有所帮助,当然更希望路过的大神,如果有更靠谱的方案能够指点一二,不吝赐教。 一、故障背景 内部故障群反馈:XX 系统卡住不可用了,请帮忙看看; 排查发现是有一个 alter 修改数据库的表结构的变更,出现了大量的 MDL 锁,导致服务不可用,最后通过 kill 掉这个 alter 恢复了服务。当然, 这个 alter 需求也就暂时搁置了。 业务需求的变更肯定还是要继续执行的,因此就有了各种
张戈
2018/03/26
3.5K0
MySQL在线DDL修改表结构的简单经验分享
MySQL数据库基础
关系型数据库:MySQL、Oracle、mariadb、Microsoft SQL 等。
Alone-林
2022/08/20
3880
MySQL数据库基础
MetaData Lock 之二
一 简介 上一篇文章 《MetaData Lock 之一》 简单的介绍了MySQL 引入MDL 的前因后果,本文深入了解MDL的实现原理和运行机制。
用户1278550
2018/08/09
7350
MySQL进阶知识(最全)(精美版)
脏读:读取到了没有提交的数据, 事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的 数据是脏数据。 不可重复读:同⼀条命令返回不同的结果集(更新).事务 A 多次读取同⼀数据,事务 B 在事务A 多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同⼀数据时,结果 不⼀致。 幻读:重复查询的过程中,数据就发⽣了量的变化(insert, delete)。
编程张无忌
2021/01/26
2.7K0
MySQL进阶知识(最全)(精美版)
数据库(七)
视图是由一张表或多张表的查询结果构成的一张虚拟表,建立一张视图后会在数据库中保留一个以 frm 后缀结尾的文件,只保留了数据结果,所有的数据都来自 sql 语句。
py3study
2020/01/20
9050
MySQL 数据库中的锁
MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTWRL)。当你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。
星尘的一个朋友
2021/03/20
5.5K0
相关推荐
史上最全的OGG基础知识整理
更多 >
交个朋友
加入架构与运维趋势交流群
技术趋势前瞻 架构演进方向
加入架构与运维学习入门群
系统架构设计入门 运维体系构建指南
加入架构与运维工作实战群
高并发系统设计 运维自动化实践
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档