首页> 中国专利> MYSQL数据库的异构的基于日志的复制

MYSQL数据库的异构的基于日志的复制

摘要

一种用于在不同类型的系统之间传输数据的系统和方法,并且具体地,使用基于日志的复制来在例如MySQL数据库或系统与另一类型的数据库或系统之间传输数据。根据一个实施例,所述系统可以用于执行MySQL数据从源数据库系统到目标数据库系统的一次或初始拷贝,和/或在连续的基础上将从MySQL数据库的二进制日志捕获的进行中的事务复制到一个或额外的非MySQL数据库中,使得这两个系统针对关注的事务被同步。根据一个实施例,可以从MySQL二进制日志提取全部或部分数据改变,并可选地对所述改变进行转换、跳过或补充、输出或写入到文件(根据一个实施例,该文件可以被实现成轨迹文件或Oracle GoldenGate轨迹文件)中,并且随后将所述改变应用到一个或多个目标系统(例如,另一MySQL数据库或非MySQL数据库)中的任何一个上,从而使得源系统和目标系统同步。

著录项

  • 公开/公告号CN103221949A

    专利类型发明专利

  • 公开/公告日2013-07-24

    原文格式PDF

  • 申请/专利权人 甲骨文国际公司;

    申请/专利号CN201180036429.0

  • 申请日2011-05-13

  • 分类号

  • 代理机构中国国际贸易促进委员会专利商标事务所;

  • 代理人邹姗姗

  • 地址 美国加利福尼亚

  • 入库时间 2024-02-19 19:59:10

法律信息

  • 法律状态公告日

    法律状态信息

    法律状态

  • 2017-10-17

    授权

    授权

  • 2013-08-28

    实质审查的生效 IPC(主分类):G06F17/30 申请日:20110513

    实质审查的生效

  • 2013-07-24

    公开

    公开

说明书

版权声明

本专利文献的公开内容的一部分包含受到版权保护的资料。版权 所有者并不反对任何人如同在专利和商标局的专利文件或记录中出现 的那样对该专利文献或专利公开内容进行复制再现,但是在其它方面 版权所有者无论如何都保留全部版权权利。

技术领域

本发明一般涉及在不同类型的系统之间传输数据,并且具体地涉 及使用基于日志的复制来在MYSQL数据库或系统与另一类型的数 据库或系统之间传输数据的系统和方法。

背景技术

在世界各地,越来越多的组织使用诸如MySQL开源数据库之类 的数据库产品。估计每天有五万次下载,MySQL数据库是想要可靠 的、实惠的并易于使用的高性能数据库的数据库开发者、管理员 (DBA)和IT经理的普遍选择。对于一些组织而言,这样的数据库 可以成为主要的生产环境,并用于运行对于商业操作而言是核心的应 用。随着它们的商业增长,对于复杂数据管理的需求也随之增长。为 了可扩充性的原因,这些组织中的许多组织想要从例如他们的 MySQL数据库向其它商业数据库(例如,Oracle/DB2/SqlServer) 迁移数据。

除了数据迁移以外,将MySQL用作其原始数据库的一些组织可 能也想将其数据与其它操作系统和数据库整合。一个例子可以是与实 时数据仓库系统或在不同数据库系统上运行的其它金融应用整合。这 样的组织通常需要以下方案:在低时延的情况下提供异构复制以进行 零停机时间的迁移。

由于大量的用于报告的只读查询可能使得生产服务器的性能变 慢,所以有时也存在以下情况:一个组织不愿意因为频繁的报告查询 而增加生产服务器的负担。一些组织可能更愿意将与报告有关的查询 处理卸载到另一(可能较少执行的)非生产数据库。例如,一些组织 可能想要将第一类型的数据库服务器(例如在Linux或Windows OS 中运行的MySQL)用作其报告服务器;并且将第二类型的数据库服 务器(例如Oracle)用作高性能生产服务器。

为了使得MySQL数据库中存放的数据能够与其它非MySQL系 统进行整合,可以(经由网关或额外的产品)使用定制程序或软件组 件,例如ETL/EAI/EII。这些技术的问题在于它们在处理非批量数据 方面是低效的(ETL),需要应用程序修改来发布来自应用程序的数 据(EAI),或者需要应用程序访问MySQL系统和非MySQL系统 并根据需要整合数据。在大容量时,持续地运行ETL以整合改变的 数据在计算上是繁重的,EAI整合需要修改/访问应用程序从而影响 应用程序的响应时间,并且EII由于其涉及在不同(远程)网络上访 问多个系统而较慢。

相应地,迄今为止,除了处理这样的整合/同步的定期(夜间) ETL、EAI或EII方式以外,并不存在基于日志的改变数据捕获 (CDC)程序来执行例如MySQL事务数据从MySQL数据库向非 MySQL数据库的逻辑复制。这些就是本发明的实施例旨在解决的一 般问题。

发明内容

本文描述了一种用于在不同类型的系统之间传输数据的系统和方 法,并且具体地使用基于日志的复制来在例如MySQL数据库或系统 与另一类型的数据库或系统之间传输数据。根据一个实施例,所述系 统可以用于执行MySQL数据从源数据库系统向目标数据库系统的一 次或初始拷贝,和/或用于在连续的基础上将从MySQL数据库的二 进制日志捕获的进行中的事务复制到一个或额外的非MySQL数据库 中,使得这两个系统针对关注的事务被同步。根据一个实施例,可以 从MySQL二进制日志提取全部的或部分的数据改变,可选地对该全 部的或部分的数据改变进行变换、跳过或扩充、输出或写入到一文件 (根据一个实施例,该文件可以被实现成轨迹文件或Oracle  GoldenGate轨迹文件),并且随后将其应用在一个或多个目标系统 (例如,另一MySQL数据库或非MySQL数据库)中的任何一个 处,从而同步源系统和目标系统。

附图说明

图1示出了根据实施例的用于异构的基于日志的复制的系统的总 体架构。

图2示出了根据实施例使用日志索引文件来确定当前二进制日志 文件。

图3是根据实施例的用于异构的基于日志的复制的进程的流程 图。

图4示出了根据实施例的日志旋转的使用。

图5示出了根据实施例的在MySQL二进制日志中的事件顺序。

图6示出了根据实施例的事件头结构的例子。

图7示出了根据实施例的字段元数据的例子。

图8示出了根据实施例的表映射事件结构的例子。

图9示出了根据实施例的写行事件结构的例子。

图10示出了根据实施例的更新行事件结构的例子。

图11示出了根据实施例的事件顺序的例子。

图12示出了根据实施例的事件顺序的另一例子。

图13示出了根据实施例的用于VAM二进制日志读取器的类图 的例子。

图14示出了根据实施例的用于VAM二进制日志处理器的类图 的例子。

具体实施方式

本文描述了一种用于在不同类型的系统之间传输数据的系统和方 法,并且具体地使用基于日志的复制来在例如MySQL数据库或系统 与另一类型的数据库或系统之间传输数据。根据一个实施例,所述系 统可以用于执行MySQL数据从源数据库系统向目标数据库系统的一 次或初始拷贝,和/或用于在连续的基础上将从MySQL数据库的二 进制日志捕获的进行中的事务复制到一个或额外的非MySQL数据库 中,使得这两个系统针对关注的事务被同步。根据一个实施例,可以 从MySQL二进制日志提取全部的或部分的数据改变,可选地对该全 部的或部分的数据改变进行变换、跳过或扩充、输出或写入到一文件 (根据一个实施例,该文件可以被实现成轨迹文件或Oracle  GoldenGate轨迹文件),并且随后将其应用在一个或多个目标系统 (例如,另一MySQL数据库或非MySQL数据库)中的任何一个 处,从而同步源系统和目标系统。本发明的各个实施例的优点包括:

1、对于MySQL和非MySQL数据库系统之间的事务复制而 言,基于日志的复制允许非常低的时延。从事务被提交到MySQL系 统到复制到非MySQL系统的时间的一般预期是几秒或更少。

2、与现有方法相比,MySQL系统上的开销的量显著更少,这 是因为从日志而不是MySQL系统中的数据页面捕获改变。在网络上 传输的字节量也显著更少。

3、并不经由SQL或另一嵌入SQL的编程语言(或类SQL语 言)来查询应用程序表,从而使得复制是非侵入性的。

4、所述系统不需要使用第三方的网关产品,并且在网络或系统 发生故障的情况下,以及甚至对于影响整个数据站点的大部分故障而 言,允许有保证的事务传递。

5、可以使用操作报告应用程序来在实时的基础上从非MySQL 数据库获得数据,而无需访问MySQL数据库。

6、所述系统允许在MySQL数据库上运行的应用程序向非 MySQL数据库的接近零停机时间的迁移,并且还允许数据库机器使 用来自MySQL数据库的事务,以进行近实时(或活动)数据仓储。

7、所述系统能够实现基于日志的改变数据捕获(CDC),并且 允许可能寻求调整到另一系统但是不能接受应用程序中断的基于 MySQL的组织使得它们的两个系统维持在同步状态,执行全面的测 试,并且随后最终从它们的MySQL系统迁移到另一系统,而不会导 致停机时间。目前,来自MySQL数据库的实时操作通常并不在实时 的基础上与企业数据仓库进行整合。根据实施例,所述方法提供了供 企业获得来自MySQL系统的数据的方式。

根据实施例,所述系统使用MySQL的二进制日志特征来捕获数 据。MySQL二进制日志包含在例如DML操作中修改数据的语句数 据。语句是以“事件”的形式存储的,“事件”描述了对数据的修 改。根据实施例,二进制日志用于两个主要的目的:(1)复制,其 中,在主复制服务器上将二进制日志用作要被发送到从服务器的语句 的记录。主服务器向其从服务器发送包含在其二进制日志中的事件, 从服务器执行这些事件以进行在主服务器上进行的相同数据改变;以 及(2)数据恢复,其中,某些数据恢复操作需要使用二进制日志。 在已经恢复了备份文件之后,在进行备份之后被记录在二进制日志中 的事件被再次执行。这些事件使得数据库从备份点开始是最新的。

使得二进制日志能够存储事务数据并不是在安装MySQL时缺省 设置的。根据一个实施例,可以使用参数‘log-bin’来使得能够进行 二进制日志记录。这个参数是在MySQL初始化文件(对于 Windows平台其是my.ini;而在其它平台中是my.conf)中指定的。 在MySQL的之前版本中,二进制日志包含语句级别的信息,即其记 录全DDL和DML语句。为了使得数据能够以通用数据格式可用以 支持异构,基于纯文本SQL语句建立基于日志的捕获是困难的。 MySQL的后续版本引入了二进制日志记录支持,其可以用于解决上 述问题。MySQL版本5.1也引入了新的内部C++类来提供对二进制 数据的访问。

根据一个实施例,与其它数据库(例如Ingress和Sybase)中发 现的环形日志记录风格相比,顺序地生成MySQL二进制日志并对其 编号。MySQL并不自动地对旧的日志文件进行存档,所以管理员必 须小心地保持/备份他们的较老的日志文件。

根据一个实施例,对非事务的表进行的更新在执行之后立即被存 储在二进制日志中。在未提交的事务内,对改变事务表(例如 InnoDB表)的所有更新(UPDATE(更新)、DELETE(删除)、 INSERT(插入))被高速缓存,直到服务器接收到COMMIT(提 交)语句为止。此时,服务器后台程序(mysqld)将整个事务写入 二进制日志。如果发布ROLLBACK(回滚)语句,则服务器后台程 序并不写入事务数据。对于二进制日志,回滚操作是无操作、非记录 操作。

图1示出了根据一个实施例的用于异构的基于日志的复制的系统 的总体架构。如图1中所示的,架构102包括MySQL或类似的数据 库104,使用上面描述的配置设置和参数将其配置成将数据记录在当 前二进制日志文件106(或多个二进制日志文件108)中。

根据一个实施例,所述系统可选地可以包括一个或多个MySQL 库110,其用于提供文件阅读器、文件CACHE和文件转换类。根据 另一个实施例,并不需要这种特别的组件。

数据捕获和复制系统或产品(例如,Oracle GoldenGate或类似 的复制产品)使用厂商访问模块(VAM)插件程序或应用程序接口 (API)111或类似组件来提供对二进制日志文件的访问。根据一个 实施例,VAM包括:多个MySQL VAM事件类112,其可以用于提 供对于来自MySQL二进制日志的事件的处理,例如打开当前二进制 日志、读取事件、将这些事件转换成VAM记录、处理日志旋转等; 多个MySQL VAM二进制日志类114,其可以用于环绕MySQL 库;以及多个VAM阅读器和处理器类116,其可以用于从二进制日 志类读取记录并处理记录,并将它们放到记录队列中。根据一个实施 例,这些类中的一些或全部可以具有它们自己的专用线程,并且不会 被提取调用阻塞。根据其它实施例,虽然上面的描述示出了使用 MySQL环境以及MySQL VAM,但是使用其它类型的数据库或系统 实现其它类型的VAM将是明显的。

表1

根据一个实施例,提供记录队列118来保持VAMRead()调用 后续使用的记录。多个VAM记录类120可以用于从记录队列读取数 据并发送所述数据,以便使用VAM API进行提取。对提取进程122 (例如,Oracal GoldenGate或类似的复制进程)进行编译,以捕获 来自VAM API的数据,并且将所述数据写入轨迹124或轨迹文件 (例如,GoldenGate轨迹文件),以便传输到目标系统126和/或目 标数据库128。

根据一个实施例,MySQL将数据作为事件项存储在二进制日志 中,支持基于SQL语句和操作的特性的各种事件,并且提供C++类 来读取事件数据。根据一个实施例,VAM通常被配置成识别这些二 进制日志事件的子集。例如,VAM可以被配置成识别表示事务、 DML语句数据、日志旋转等的那些二进制日志事件。根据一个实施 例,表1示出了MySQL事件的列表,其中,MySQL VAM可以被 配置为从二进制日志识别这些MySQL事件。将明显的是,根据其它 实施例,可以识别其它类型的事件。

根据一个实施例,可以使用C++来编写VAM实现,并且可以将 VAM模块的实现划分成两个主要的部分:第一部分,其使用内部开 发的事件C++类来读取二进制日志事件,并将这些二进制日志事件 处理成数据记录,使得这些记录处于现成格式(准备好发送),并将 其存储在有限大小的队列中;以及第二部分,每当其从API接收到 请求时,其就从队列取得记录并将记录发送到API。

日志索引文件

图2示出了使用日志索引文件来确定当前二进制日志文件。根据 一个实施例,MySQL使用日志索引文件来维持对当前二进制日志文 件以及旧的日志文件的进行标识的列表。这种日志索引文件位于与二 进制日志相同的目录位置处。所述系统可以从配置文件中进行读取, 以确定日志文件格式,例如,其是ROW(原始)格式、 STATEMENT(语句)格式还是MIXED(混合)格式的,并且如果 其不是ROW(原始)格式则异常中止。在初始化期间,VAM需要 获得活动二进制日志文件的名称。如图2中所示的,根据一个实施例 132,MySQL数据库104可以使用上面描述的配置设置和参数来向 当前二进制日志文件106(或多个二进制日志文件108)写入数据改 变。为了确定活动二进制日志,VAM111从环境变量或提供的VAM 参数获得MySQL安装主页;读取MySQL初始户文件(即, Windows平台中的my.ini或者其它平台中的my.confi文件);获得 ‘log-bin’参数的值,以获得日志目录位置以及日志索引文件名;打 开日志索引文件140,并读取内容142。根据该内容,VAM可以确 定列表中的最后一个日志文件,并使用该信息来打开144特定的日志 文件,并检查该日志文件是否仍然由服务器使用(例如,通过相对于 LOG_EVENT_BINLOG_IN_USE_F检查格式描述事件的标记值)。 如果是,则MySQL服务器当前正在使用该日志文件进行写,并且 VAM会把该日志文件看做活动日志文件。

图3是根据一个实施例的异构的基于日志的复制的进程的流程 图。如图3中所示的,在步骤160中,源系统(例如MySQL数据 库)被配置成向二进制日志写事务数据。在步骤162中,在运行时间 期间,创建一个或多个二进制日志,并在其中将事务或改变的数据存 储成与例如SQL或其它数据库语句相对应的事件项。在步骤164 中,VAM(在MYSQL数据库的情况下是MYSQL VAM)读取二进 制日志事件,并将它们处理到数据记录的队列中。在步骤166中,当 接收到对事务数据的请求时,VAM从队列取得数据记录,并将该数 据记录发送到VAM API。在步骤168中,提取进程(例如,Oracle  GoldenGate)从API进行读取并创建用于反映事务或改变的数据的 轨迹信息或轨迹文件(例如,Oracle GoldenGate轨迹文件)。在步 骤170中,将轨迹信息或轨迹文件传输或“泵送”到一个或多个目标 系统(例如目标数据库),以用于在这些目标数据库处对事务进行复 制(再次使用例如Oracle GoldenGate或另一产品)。

日志旋转

根据一个实施例,可以与二进制日志相关联的特定类型的事件是 旋转事件(RotateEvent),即,每当MySQL服务器关闭当前二进 制日志并打开新的二进制日志时,其被记录在二进制日志文件中用以 指示可能的日志旋转。日志旋转的可能原因包括:例如,如果日志文 件的大小超过‘max_binlog_size’参数,或者如果已经从MySQL命令 控制台发出了显式的‘flush logs’命令。在这些情况中,MySQL在当 前二进制日志中创建旋转事件,关闭当前二进制日志,并打开新的二 进制日志以进行进一步处理。旋转事件指示要创建的新的日志文件。 根据一个实施例,VAM可以使用该值来关闭现有的二进制日志文 件、打开新的二进制日志文件以及继续其读取。

根据一个实施例,由CrotateEvent C++类来表示旋转事件,该 C++类被定义为:

根据一个实施例,以下情形导致MySQL的日志旋转(即,关闭 现有的活动日志文件,并且打开新的日志文件):

1.当活动日志文件的大小超过‘max_binlog_size’的值(其是在 my.ini或my.conf文件中指定的)时。在该情形中:

a.MySQL在活动二进制日志中记录‘旋转事件’。旋转事件 数据部分包含新的活动二进制日志文件的位置和名称。

b.MySQL关闭活动二进制日志,并将格式描述事件标记 重设为NULL(空)。(该标记之前是用 LOG_EVENT_BINLOG_IN_USE_F值设置的)。

c.MySQL创建新的二进制日志,并将格式描述事件标记 设置成LOG_EVENT_BINLOG_IN_USE_F值。

2.当在MySQL SQL提示中发布了显式的‘flush logs’命令时。 在该情形中:

a.MySQL在活动二进制日志中记录‘旋转事件’。旋转事件 数据部分包含新的活动二进制日志文件的位置和名称。

b.MySQL关闭活动二进制日志,并将格式描述事件标记 重设为NULL。(该标记之前是用 LOG_EVENT_BINLOG_IN_USE_F值设置的)。

c.MySQL创建新的二进制日志,并将格式描述事件标记 设置成LOG_EVENT_BINLOG_IN_USE_F值。

3.在服务器停机期间。在这种情形下:

a.MySQL在活动二进制日志中记录‘停止事件’。

b.MySQL关闭二进制日志,并且还将格式描述事件的标记 重设为NULL值。(该标记之前是使用 LOG_EVENT_BINLOG_IN_USE_F值进行设置的)。

4.在服务器启动期间。在该情形下:

a.MySQL创建新的二进制日志,并且将格式描述事件标 记设置为LOG_EVENT_BINLOG_IN_USE_F值。

根据一个实施例,在上面提到的情形1和2期间,VAM使用旋 转事件来标识出现日志旋转,并且使用旋转事件的数据来获得下一二 进制日志名称。VAM随后打开下一二进制日志,并且继续其二进制 日志读取。在上面提到的情形3和4期间,当VAM遇到停止事件 时,其关闭其使用的二进制日志,并且在日志索引文件中检查下一二 进制日志的存在。如果VAM在索引文件中找到下一二进制日志,则 其打开该二进制日志,并继续其读取。如果VAM未能在索引文件中 找到任何新的日志文件名称(例如,服务器仍然处于停机模式,或者 在停机之后从未被启动),那么VAM通知extract(提取)异常中 止。

在服务器崩溃期间,格式描述事件的标记在服务器重启期间将不 被服务器重设或者MySQL服务器既不将旋转事件也不将停止事件记 录在活动二进制日志文件中的几率是很小的。在随后的启动期间,服 务器创建新的二进制文件,而不需要重设之前的二进制日志中的标 记。根据一个实施例,在这种情况下,两个二进制日志将设置 LOG_EVENT_BINLOG_IN_USE_F状态标记。在以下条件下VAM 可能遇到这种情形:(1)VAM当前正在处理活动二进制日志。在 读取时发生服务器崩溃。在这种情况下,建议停止提取,进行崩溃恢 复并在服务器启动之后重启VAM;以及(2)VAM被设定为读取旧 的日志文件。在从一个文件向另一个文件进行读取(即,日志旋转) 时,其遇到值为LOG_EVENT_BINLOG_IN_USE_F的日志文件标 记。还要注意到,这种日志文件并不是最近的日志文件(即,不是活 动二进制日志)。当EOF出现时,MySQL VAM可以在日志索引文 件中检查下一日志文件的存在。在这种情况下,VAM假定之前发生 了服务器崩溃,并关闭现有日志文件并打开下一日志文件,以及继续 日志读取。

图4示出了根据一个实施例的日志旋转的使用182。如图4中所 示的,在步骤184中,VAM对日志索引文件进行解析,以获得二进 制日志文件列表。在步骤186中,读取序列ID以获得日志文件名称 和位置。在步骤188中,打开日志文件。在步骤190中,在该文件中 检查任意EOF,以及在步骤198中,如果没有到达EOF,则顺序地 从日志文件中读取事件。在步骤200到204中,VAM确定诸如查询 事件、行事件、旋转事件和/或停止事件之类的事件。在步骤208 中,可以从旋转事件信息获得下一日志文件。

VAM实现

如上面所描述的,根据一个实施例,所述系统和方法使得能够使 用基于日志的复制来在例如MySQL数据库或系统与另一类型的数据 库或系统之间传输数据,或者在诸如MySQL之类的数据库产品与诸 如Oracle GoldenGate之类的数据复制产品之间传输数据。以下的部 分对这样的实施例和相应的厂商访问模块(VAM)或应用程序接口 (API)的特定实现进行描述。

二进制日志支持

如上面描述的,根据一个实施例,VAM(MySQL VAM)使用 MySQL二进制日志来捕获数据。MySQL二进制日志包含修改数据 的语句数据,例如DML操作。语句是以描述修改的“事件”的形式 存储的。

二进制日志用于两个主要目的:复制,在复制中,在主复制服务 器上二进制日志用作要被发送到从服务器的语句的记录—主服务器向 其从服务器发送包含在其二进制日志中的事件,从服务器执行这些事 件以进行主服务器上进行的相同的数据修改;以及数据恢复,在数据 恢复中,某些数据恢复操作需要使用二进制日志。

在已经还原了备份文件之后,重新执行二进制日志中的、在进行 备份之后记录的事件。这些事件使得数据库从备份点开始是最新的。 对于完全备份而言,用户(例如,客户)可以使用‘MySQLDump’实 用程序,并且之后使用二进制日志来进行递增备份。

二进制日志配置

根据一个实施例,使得二进制日志能够存储事务数据并不是随着 安装MySQL而缺省地设置的。相反,应当使用参数‘log-bin’来使得 能够进行二进制日志记录。该参数是在windows平台的初始化文件 my.ini或其它平台中的my.conf中指定的。

在MySQL5.1版本之前,二进制日志包含语句级别的信息,即 其记录了完全的DLL和DML语句。为了具有可用于统一数据格式 的数据以便支持异构性,难以基于纯文本SQL语句来建立基于日志 的捕获。然而,MySQL5.1版本引入了二进制日志记录支持,其解 决了上述问题。并且,MySQL提供内部C++类来访问这种二进制数 据。

根据一个实施例,需要以下步骤来配置MySQL服务器以使得能 够进行二进制记录:打开MySQL服务器配置文件(windows的 my.ini或其它平台中的my.conf);使用参数‘log-bin’来使得能够进 行二进制日志记录,该选项的值指定日志文件的目录位置。例如:

log-bin=″C:/MySQL/MySQL Server5.1/log/test.bin"。

在上面的例子中,日志文件的名称是使用‘test.00001, test.00002…’等来创建的。将这些文件存储在“c:/MySQL/MySQL  Server5.1/log”目录中。在配置文件中,应当将日志记录格式配置成 仅‘ROW’模式。不支持‘MIXED’模式。该选项使得DML语句 能够以二进制格式记录数据。这可以使用参数‘binlog_format’来实 现。可以使用‘max_binlog_size’选项来指定二进制日志文件的大小 (字节)。最小值应当是4096。

与诸如Ingress和Sybase之类的其它厂商中发现的环形日志记录 风格相比,顺序地创建MySQL的二进制日志并且对其编号。 MySQL并不自动地对旧的日志文件进行存档,所以终端用户/客户应 当注意保持/备份他们的旧的日志文件。根据一个实施例,以下进程 创建新二进制日志文件,并且关闭现有日志文件:每当启动服务器后 台程序mysqld时;来自MySQL命令控制台程序(mysql)的显式刷 新命令,例如FLUSH LOGS或FLUSH MASTER—在当前日志的大 小达到max_binlog_size参数时,服务器也自动地创建新二进制日志 文件。

根据一个实施例,MySQL维持包含二进制日志文件列表的索引 文件,其包括活动地使用的二进制日志文件以及较旧的二进制日志文 件。该索引文件存在于与其它二进制日志相同的目录位置。MySQL 二进制日志并不支持关闭/开启对特定表/列的二进制记录。

事务和二进制日志

根据一个实施例,对非事务表的更新在执行之后立即被存储在二 进制日志中。在未提交的事务内,对改变事务表(例如InnoDB表) 的所有更新(UPDATE、DELETE、INSERT)进行高速缓存,直到 服务器接收到COMMIT语句为止。MySQL打开临时的文件来刷新 高速缓存以适应来自更新操作的更多数据。此时,mysqld(服务器 后台程序)向二进制日志写入整个事务。如果发布了ROLLBACK 语句,则服务器后台程序并不写入事务数据。就二进制日志而言,回 滚操作是无操作、非记录的操作。

当对与对事务表以及非事务表两者的更新混合的事务进行回滚 时,服务器后台程序将显式ROLLBACK语句记录到日志中。使用 SAVEPOINT(保存点)语句来用任意的名称来设置命名的事务保存 点。使用ROLLBACK TO SAVEPOINT(回滚到保存点)语句来针 对命名的保存点来回滚事务。MySQL并不支持嵌套的事务或事务命 名。如果启动新事务或者关闭服务器而并没有使用COMMIT或 ROLLBACK来结束前一事务,则MySQL在开始新事务之前或者在 服务器停机之前将自动地向磁盘提交之前事务的数据。MySQL并不 在多个二进制文件之间分割该事务。

根据一个实施例,如果事务数据的大小超过使用 max_binlog_size参数指定的值,则允许二进制日志文件的大小超过 该参数的值是可能的。并不向二进制日志写入无操作更新(更新导致 ‘零’列)。这也应用于空事务。当使用触发器来针对自身更新一列 时,MySQL记录触发器更新的结果而不是语句更新的结果。例如, 使用以下触发器,对20进行的寿命更新使得MySQL记录25(触发 器的结果)而不是20的值。

平台支持

根据各个实施例,所述系统可以支持Windows、Linux操作系 统、HPUX和Solaris OS。为了使得MySQL VAM捕获二进制日志 事件,需要为MySQL提取进程赋予以下许可(以下许可可应用于非 windows平台):对于配置文件(my.cnf)所处的目录以及用于生成 二进制日志的目录的读取和执行许可;对于配置文件(my.cnf)的读 取许可;(MySQL后台程序进程所使用的)读、写;对(定义的) tmp目录的执行许可。

版本支持

MySQL向前支持来自版本3.x的二进制日志。在版本5.1之 前,将经由DML操作对数据库表进行的修改作为SQL语句(文本 形式)记录在二进制日志中。从版本5.1向前,MySQL二进制日志 以二进制形式将DML操作存储成行数据。根据一个实施例,与处理 基于文本的SQL语句相比,MySQL VAM更容易读取这种二进制数 据并且将它们转换成例如GoldenGate统一格式。

数据类型支持

表2示出了根据一个实施例所支持的数据类型。

表2

存储引擎支持

根据一个实施例,MySQL VAM支持以下存储引擎: MyISAM—非事务存储引擎;以及InnoDB—事务存储引擎。

支持的数据库操作

根据一个实施例,MySQL VAM可以从二进制日志中捕获以下 数据库操作:启动事务;提交事务;回滚事务—MySQL并不发送被 回滚到二进制日志的事务,但是如果事务涉及参与相同事务的 InnoDB表以及myISAM类型,则MySQL记录“事务回滚操作”; 插入操作;更新操作;删除操作;截断操作。

最大行大小和列支持

根据一个实施例,所有例如GoldenGate应用支持MySQL的最 大数据库行大小(当前是64k)。对给定MySQL表的列的最大数量 (当前是3398)、MySQL的最大对象名称长度(shema.table)以及 MySQL的最大对象名称长度(shema.table)进行支持。具有 InnoDB存储引擎的MySQL包括列的数量不应当超过1000的限制。 压缩的更新和删除的支持

根据一个实施例,二进制日志存储不是DML操作的一部分的列 值。为了最小化MYSQL VAM和捕获模块之间的数据传输,支持压 缩的更新和删除。

AUTO_INCREMENT(自动递增)列

根据一个实施例,可以使用AUTO_INCREMENT列属性来生成 新行的唯一标识。由于在大部分情况中该列的值是系统生成的,所以 支持以下两个要求:AUTO_INCREMENT列的值向目标侧的传播— MySQL日志将该AUTO_INCREMENT列的值存储在二进制日志 中。在应用(即,目标)侧,复制进程将该自动递增列的值插入到显 式插入操作中—MySQL支持在插入操作期间将 AUTO_INCREMENT列强制为特定的值;以及Bi定向支持—在 INSERT操作期间,AUTO_INCREMENT列的值被插入下一较高的 值。

MySQL支持两个变量(经由它们的初始化文件my.ini配置) ‘auto_increment_increment’和‘auto_increment_offset’来解决任何 双向自动_递增列问题。这些服务器侧变量在源侧以及目标侧可以被 不同地设置,以解决双向设置冲突。

双向数据复制支持

根据一个实施例,为了支持双向环检测,MYSQL VAM模块基 于用户id、事务id来过滤记录。MySQL二进制日志并不将这些值 存储在它们的事件中。双向环检测应当通过目标侧上的轨迹表或检查 点表来支持(使用FILTERTABLE(过滤表)选项来配置)。 MySQL双向配置需要使用复制检查点表来标识复制事务,以从捕获 中排除。提取忽略以对检查点表进行的操作结束的事务。为了支持这 种功能,TRANLOGOPTIONS提供新的FILTERTABLE<table>选 项,其指定检查点表的名称。复制数据库用户可以使用‘sql_log_bin’ 变量来关闭会话级别的二进制日志记录。所以在应用侧上,复制用户 应当将该值是设置成0,以关闭二进制日志记录。

通过LSN和时间戳进行的定位

根据一个实施例,MySQL VAM支持通过时间戳以及LSN进行 的定位。使用ADD/ALTER提取命令来设置时间戳位置,例如;

ADD/ALTER EXTRACT extract_name,MYSQL VAM,begin timestamp_value

其中,合法的时间戳值是:

NOW(或现在)—提取在其被添加或改变时采用当前时间戳 值。

MySQLMYSQL VAM读取时间戳值等于或大于该时间戳值的事 务记录。

过去时间戳值—MySQL VAM搜索日志文件,并读取时间戳值 等于或大于该时间戳值的事务记录。

未来时间戳值—MySQL VAM等待,并读取时间戳值等于或大 于该时间戳值的事务记录。

使用ADD/ALTER提取命令来设置LSN值的位置,例如:

ADD/ALTER EXTRACT extract_name,MYSQL VAM,lognum log_num,logpos log_pos

其中,log_num是日志文件号。例如,如果日志文件名称是 test.000034,那么该值将是34。MySQLMYSQL VAM搜索该日志文 件并打开它以进行进一步读取;并且log_pos是日志文件中的偏移 值。该位置之后可用的事务记录将被MySQL VAM读取。

存档日志支持

如上面所描述的,根据一个实施例,与在其它厂商(例如 Ingress和Sybase)中发现的环形日志记录风格相比,创建MySQL 的二进制日志并对其进行顺序编号。MySQL并不自动地对其旧的日 志文件进行存档。在初始化文件中指定的日志记录中保持日志文件。 这样,客户应当注意保持/备份它们的较旧的日志文件。根据一个实 施例,可以提供通过使用MySQL VAM来支持对较旧的二进制日志 文件进行定位以及读取。如果要求MySQL VAM定位被管理员或其 它备份工具移动到其它位置的较旧的日志文件,那么MySQL VAM 将返回错误或异常中止。

DDL复制

根据一个实施例,二进制日志将DDL语句存储成基于文本的 SQL语句,并且MySQL VAM支持这一特征。

FetchCols和FetchModCols支持

根据一个实施例,当在事务日志记录中不存在列值时,可以使用 FETCHCOLS和FETCHCOLSEXCEPT来从数据库取得列值。如果 数据库使用压缩的更新(其中,除非列值改变否则不记录列值),则 可以使用这一选项。FETCHCOLS和FETCHCOLSEXCEPT确保 FILTER操作所需要的列值是可用的:

FETCHCOLS取得指定的列。

FETCHCOLSEXCEPT取得除了指定列以外的所有列。对于具 有大量列的表而言,与用FETCHCOLS列出每一个列相比, FETCHCOLSEXCEPT可以更加高效。

即使在事务日志中存在列,也可以使用FETCHCOLS和 FETCHCOLSEXCEPT来强制从数据库取得列值。事务日志中可以 存在的值是那些在追加日志记录中修改或包括的列:

FETCHMODCOLS取得指定的列。

FETCHMODCOLSEXCEPT取得除了指定列之外存在于事务日 志中的所有列。对于具有大量列的表而言,FETCHMODCOL。

根据一个实施例,在捕获侧支持这一特征。

初始加载支持

根据一个实施例,MYSQL VAM包括初始加载支持。随着开源 数据库和开源操作系统的流行,越来越多的客户开始将MySQL用作 其企业的一部分。随着他们的公司的成长,组织可能喜欢通常通过以 下步骤来从MySQL移动到Oracle/DB2/SQL服务器:

步骤1,将现有MySQL的数据迁移到客户所选的数据库。捕获 侧初始加载支持可以用于解决这一问题;

步骤2,在成功迁移之后,使能实时复制(或改变数据捕获)。 MySQL VAM可以用于解决这一问题。

支持以下的初始加载方法:使用复制来加载数据-提取进程从表 中直接提取数据。该方法本质上是较慢的,这是因为在应用侧每次应 用一个记录;使用批量加载实用程序来加载数据-提取进程输出 ASCII格式的记录,这些记录稍后可以由SQLLOADER或BCP使 用;以及使用GoldenGate直接加载来加载数据-提取进程直接从表中 提取数据,并调用复制进程。将数据直接加载到SQL*Loader。

其它要求

根据一个实施例,MySQL VAM模块并不通过添加额外的截断 点(在Sybase情况中)改变二进制日志内容。所以,支持多于一个 提取进程对同一二进制日志进行读取是可能的。根据一个实施例, MySQL VAM应当与配置有复制选项的MySQL数据库共存。应当 注意避免在提取中添加新的参数或者使用MySQL特定参数文件。

大小写敏感性

根据一个实施例,MySQL将数据库名称映射成目录名称,并且 将表名称映射成文件名称(.frm文件保存关于表的元数据)。对大 小写敏感的表名称取决于MySQL所运行于的底层操作系统。 MySQL在windows平台中并不区分具有混合的大小写字母的表名 称,并且在UNIX平台的大部分变形中是大小写敏感的。

字符集支持

根据一个实施例,对于CHAR、VARCHAR、TEXT和ENUM 列类型,MySQL支持UICODE字符集。MySQL支持其字符串列的 UTF8以及UTF16(ucs2)编码。对于UNICODE字符集而言,需要 在轨迹文件中将数据存储成UTF16值。在字符串列的UTF8编码的 情况下,MYSQL VAM模块、初始加载模块以及应用侧模块使用内 部转换库来将其数据转换成UTF16值(或者从UTF16值转换其数 据)。MySQL支持NCHAR、NVARCHAR列类型。它们在内部被 映射成具有UTF8字符集的列。MySQL捕获支持每一个第一版本中 的UTF8和UCS2字符集。根据一个实施例,使用UNICODE字符 集来证实MySQL捕获和应用模块。

其它配置要求

根据一个实施例,MySQL VAM要求正确地设置环境变量 ‘MYSQL_HOME’。该变量必须指向MySQL数据库的安装位置。 MySQL VAM使用该变量来查找MYSQL配置文件(在为windows 平台中是my.ini并且在非windows平台中是my.conf)。并且,必 须在MySQL配置文件内部(my.ini或my.conf)设置以下参数:使 用‘log-bin’参数使能二进制日志记录,该选项的值指定日志文件的目 录位置;使用‘binlog_format’参数来指定日志记录格式,其应当被配 置成仅‘ROW’模式。不支持‘MIXED’和‘STATEMENT’模式。例 如:

[mysqld]

log-bin=″C:/MySQL/MySQL Server5.1/log/test.bin″

binlog_format=ROW

在这个例子中,使用‘test.00001,test.00002’等来创建日志文件名 称。这些文件存储在目录“c:/MySQL/MySQL Server5.1/log”中。

MySQL C++类的直接使用

MySQL并不具有可用于外部世界的已定义好的日志API,但是 它具有已定义好的文件访问IO_CACHE类以及事件类(用C++公开 的),其镜像二进制日志的内容。MYSQL已经分开了对日志事件的 读取以及处理。内部IO_CACHE类按照需要以数据块的形式读取二 进制日志数据。(为了避免盘IO开销,最小为64k大小)。这些类 提供从该块进行读取的API。在处理侧,MYSQL具有事件类,其可 以用于将该数据投掷到特定于事件的C++类。这些公共可用的 MySQL类具有以下缺点:IO_CACHE类单次地将二进制日志事件 数据(如果大小大于64k)读取到存储器中。对于包含更大数据(例 如,大小为2GB的LOB数据)而言,这可能存在问题; IO_CACHE类自己重新实现特定于线程的功能。在MySQL VAM与 提取模块链接时,这产生了链接器错误集(重定义)。

根据一个实施例,MySQL VAM可以重新实现IO_CACHE类以 及事件处理器类。这对于MySQL VAM访问二进制日志给出了完整 的控制。并且这缓解了链接器错误、更大LOB数据取得以及对特定 于MySQL的源代码文件或头文件的依赖的问题。

根据一个实施例,MySQL VAM可以重新实现用于处理事件的 C++类,并且使用IO_CACHE类进行缓冲的IO读取。该方法将对 MySQL源代码的依赖性减小到了例如GoldenGate建立环境中。并 且该方法给出了MySQL VAM如何处理事件数据的完整控制。还可 以重复利用频繁使用的事件实例。

根据一个实施例,MySQL VAM可以使用特定于MySQL的事 件类和IO_CACHE类来访问二进制日志。MySQL VAM类需要继承 事件类以提供特定于MySQL VAM的所需特征。

有符号或无符号整数

MySQL支持被定义成有符号或无符号(缺省为有符号)的整数 列。例如,两字节的有符号整数列可以支持从-32k到+32k的值,并 且无符号整数支持0到+64k。二进制日志并不返回关于数字列的符 号的元数据,即,二进制日志的列支持有符号或无符号模式,那么。 存在两种可能的设计方法:总是返回有符号的值—在目标侧上,复制 将基于列类型进行转换;或者从提取获得MySQL列的元数据,并将 正确的值返回给提取。根据一个实施例,MySQL VAM向MySQL  VAM API返回作为有符号值的数值。

通过序列Id进行的定位

根据一个实施例,在二进制日志内部,MySQL事件在其头部分 中具有位置值。该值的生命周期特定于二进制文件,即,位置值在给 定的二进制文件中而不是在二进制文件外部是唯一的。两个不同的二 进制文件中的两个不同的事件可能具有相同的值。为了通过位置唯一 地识别事务记录,MySQL VAM将该事件位置值与日志文件名称组 合起来。例如,对于‘binlog.00054:123’,‘binlog.00054’是二进制日 志的名称,‘123’是事务记录的位置。MySQL VAM使用 GG_ATTR_DS_SEQID将该值作为ASCII字符串属性进行发送。

根据一个实施例,在重启情形中,在MySQL VAMInitalize() 调用期间,extract(提取)向MySQL VAM发送该最后接收到的序 列Id。MySQL VAM使用该值来设置正确的读取位置。MySQL  VAM对来自extract的该序列ID进行解析,并获得日志文件名称以 及事件位置。随后,其打开相应的日志文件,并开始扫描事件。如果 事件的位置与序列Id中指定的位置匹配,那么MySQL VAM将该位 置设置成当前读取位置,并从该位置开始读取二进制日志。

事务ID

对于表示DML操作的事件而言,MySQL并不具有作为事件数 据的一部分的事务id。这样,MySQL VAM需要用于向MySQL  VAM API发送这种(唯一的)事务id的方法。根据一个实施例,为 了解决这一问题,MYSQL VAM API将‘START Transaction’ (开始事务)语句中的‘Sequence Id’(序列Id)看做事务id。由 于这种‘Sequence Id’是日志文件名称+该文件中的事件偏移的组 合,所以在多个日志文件当中,保证了事务的唯一性。并且, MYSQL VAM将在内部保持这种伪随机事务id,并且将该值发送到 MYSQL VAM API以用于特定事务中的所有DML语句。MYSQL  VAM一旦遇到‘Commit’或‘Rollback’语句就清除该值。

访问LOB数据

在MySQL二进制日志中,LOB列值是与其它非LOB列值是内 联地存储的。这与其它数据库是不同的,这是因为这些值并不是使用 定位符或关联符(coupon)内联地存储以及访问的,其中,可以根 据需要取得数据。对于MySQL数据库(具有存储引擎MyISAM以 及InnoDB)并不是这样的。对于从二进制日志读取LOB列值而 言,MySQL内部IO_CACHE类将这种LOB列值的整个值从日志文 件取到存储器中,即,该类一次为这种LOB列完全地分配存储器。

根据一个实施例,MYSQL VAM API提供列出更大大小的LOB 数据应当以数据块的形式发送到MYSQL VAM API的概要的规范。 但是在MySQL情况中,数据已经被MySQL内部类完全地取得 (即,IO_CACHE对象完全分配了存储器),可以在一个调用以及 多个调用中以大小为32k字节的数据块向MYSQL VAM API发送 LOB数据。根据一个实施例,如上面描述的,MySQL的 IO_CACHE类一次取得lob数据的整个值以及其它行数据。如果 LOB的大小为2GB,那么这是有问题的。一个方法是重写 IO_CACHE类的实现,使得MYSQL VAM可以从文件中以数据块 的形式读取数据。可以使用来自GoldenGate(如果存在的话)的现 有文件管理器库。根据一个实施例,系统使用IO_CACHE类,并以 数据块的形式向MYSQL VAM API发送日志数据。

根据一个实施例,MySQL VAM实现可以利用IO_CACHE类来 读取二进制日志文件。除了LOB数据限制以外,IO_CACHE类也很 好地处理其它MySQL数据的读取。并且,处理大小为2GB的LOB 数据在实际情况中是很少见的(或不常见的)。不管LOB列值的内 部存储机制如何,MYSQL VAM应当以数据块的形式向MYSQL  VAM API返回LOB数据,使得如果需要的话MYSQL VAM API可 以进行页调出。

OG处理和MYSQL VAM API通信

根据一个实施例,MySQL VAM实现可以被划分成两个部分: 第一部分从二进制日志读取LOG数据,并准备数据,使得数据准备 好以用于MYSQL VAM API—这将在不同的线程中执行;第二部分 根据请求向API发送准备好的数据(记录)。传统设计中的主要缺 点是:只有在MYSQL VAM API请求时每个事情(完整的进程)才 开始发生,并且显然MySQL VAM模块需要一些执行时间来完成该 进程。在该时间期间,MYSQL VAM API是空闲的,并且这将降低 MYSQL VAM的性能。通过将设计划分成两个部分,这移除了 MYSQL VAM API的空闲时间。由于第一部分独立地读取二进制日 志,所以系统可以准备要发送给API的数据,并将其存储到有限大 小的队列中。然后,第二部分从队列中取得准备好的记录,并且在请 求来自MYSQL VAM API侧时立即向MYSQL VAM API发送准备 好的记录。

架构设计

如上面所描述的,根据一个实施例,MySQL VAM模块的总体 架构包括:

MySQL库—提供文件读取器、文件CACHE、数据转换类的 库。

MySQL VAM事件类—MySQL VAM的处理来自MySQL二进 制日志的事件的内部实现。

MySQL VAM二进制日志类—环绕MySQL库、MySQL VAM 事件类的库。打开当前二进制日志、读取事件、将事件转换成 MYSQL VAM记录、处理日志旋转等。

MYSQL VAM读取器、处理器类—读取以及处理来自二进制日 志类的记录并将其放入记录队列中的类。这些列具有其自己的专用线 程并且不是不被提取阻塞。

记录队列—保持供MYSQL VAMRead()调用后续使用的记录的 队列。

MYSQL VAM记录类—使用MySQL VAM API从记录队列读取 数据并将其发送到提取的类。

提取(extract)进程—标准的GoldenGate提取进程,被编译成 从MYSQL VAM API捕获数据。

二进制日志结构和日志事件

图5示出了根据一个实施例的MySQL二进制日志中的事件顺 序。根据一个实施例,MySQL在二进制日志内部将数据存储成事件 项。MySQL支持各种基于SQL语句和操作的特性的事件。MySQL 提供用于读取事件数据的C++类。通常,二进制日志结构包含以下 事件项:

1.以4字节的魔数数字开始,该数字被定义成值为 "\xfe\x62\x69\x6e"的常数BINLOG_MAGIC。

2.下一项是格式描述事件。在给定二进制日志文件上,该项是 全局的。MySQL针对每个二进制日志只写入该事件一次。该事件跟 踪当前二进制日志是否在使用或者是否被适当地关闭。

3.在图5中表示了后面接着事件序列的其余项。

根据一个实施例,MySQL VAM对二进制日志事件的子集感兴 趣。例如,MySQL VAM对表示事务、DML语句数据、日志旋转等 的二进制日志事件感兴趣。表3示出了根据一个实施例MySQL  VAM感兴趣的MySQL事件的列表。

表3

事件结构

图6示出了根据一个实施例的事件头结构。所有的事件具有通用 的头部分,之后是数据部分。一些事件具有可选的数据头部分。事件 结构通常被表示成:

1.事件头—该结构的大小是19字节。该部分包含在所有事件上 通用的以下特定于事件的数据。

4字节—事件时间戳。从1970年开始以来的秒数。

1字节—事件类型代码。类型代码的关注值和意义是: QUERY_EVENT=2;STOP_EVENT=3;ROTATE_EVENT=4; FORMAT_DESCRIPTION_EVENT=15;XID_EVENT=16; TABLE_MAP_EVENT=19;WRITE_ROWS_EVENT=23; UPDATE_ROWS_EVENT=24;DELETE_ROWS_EVENT=25。

4字节—服务器ID。在服务器的复制对端当中唯一地标识该服 务器。MySQL VAM忽略该值。

4字节—整个事件长度,以字节为单位,包括头。

4字节—日志中的事件偏移,以字节为单位。该值类似于LSN 或序列号。

2字节-事件标记。MySQL VAM忽略该值。

这种事件头由ClogEvent C++类来表示。所有的特定于与二进制 日志有关的事件的C++类都继承该类。该类的结构被表示成:

2.数据头—该结构的大小是8字节。包含变量数据的事件(例 如,表映射事件、写行事件等)包含该部分。该部分包含:

6字节—包含table_id。这可以被看做表版本。MYSQL VAM使 用该值来检查底层表元数据是否被改变。

2字节—数据头标记。MySQL VAM忽略该值。

3.数据部分—保存特定于事件的数据。例如,针对写行事件的 列值序列、针对表映射事件的列元数据。对于更多细节请参见下一部 分。

事件数据部分

根据一个实施例,事件数据部分保存特定于事件的数据。该数据 部分的大小是动态的,即值可以不同并且特定于事件类型,并且保存 数据变量列表。以下部分针对MySQL VAM感兴趣的事件类型来解 释事件数据部分的结构。

查询事件

根据一个实施例,该事件表示SQL查询。该事件由MySQL内 部C++类‘CqueryEvent’来表示。该事件的数据部分包含数据库名 称、查询字符串值和其它信息。MYSQL VAM使用CqueryEvent通 过使用以下成员变量来获取这些值:

MySQL的‘BEGIN事务’和‘ROLLBACK事务’以及 ‘Truncate’语句由该CqueryEvent类来表示。对于这些语句而 言,成员‘query’包含像“BEGIN”或“ROLLBACK”或 “TRUNCATE table_name”的值。可以使用标准字符串比较例程来 从日志中过滤这些语句。

XID_Event

根据一个实施例,该事件表示事务的提交。该事件由MySQL内 部C++类‘CxidEvent’来表示。该事件的数据部分包含两阶段提交 事务的事务id,MySQL VAM忽略该id(MySQL复制也忽略该 值)。MySQL VAM可以使用该事件项来假定提交了事务并释放任 何特定于事务的对象。

表映射事件

根据一个实施例,该事件表示(通过DML语句)参与事务的表 的元数据。该事件在表示DML操作的任何事件(例如,写、更新和 删除行事件)之前。例如,简单的插入操作产生二进制日志中的两个 项。第一项是包含表元数据的‘表映射事件’,并且下一项是包含作 为INSERT操作的一部分被添加的行数据的‘写行事件’。除了通 用头结构之外,该事件包含额外的数据头部分加数据部分。数据头 (8字节)部分包含以下数据:table_id(6字节长度)—跟踪表元数 据的修改;以及标记(MySQL VAM可以忽略该标记)。

如果底层表结构保持相同,那么针对给定表的大部分时间表映射 事件保持不变。虽然二进制日志包含同一表映射事件的多个项,但是 一次处理它们并且稍后重用它们是更好的。这加速了读取二进制日志 的执行。使用哈希表来存储Table_map_log_event日志类的实例并稍 后使用表名称来获取它们以进一步处理是更好的。

当(使用‘alter table……’语句)修改表结构时,MySQL创建 相同表的新表id。MySQL并不存储表id的历史。在读取二进制日 志的同时改变表元数据的情况中,MySQL可以以以下方式进行处 理。1)ABEND(异常中止)进程。2)MySQL VAM使用改变的 (最新的)表定义进行进一步处理。根据一个实施例,MySQL VAM 可以针对给定的表名称检查现有表id,如果是不同的,那么这可以 被鉴定为是表元数据的改变,并且MYSQL VAM可以通知提取异常 中止。

表映射事件的数据部分包含以下表元数据信息:

1字节—数据库名称的长度

n字节—数据库名称+之后的以null结束的字符。

1字节—表名称的长度

n字节—表名称+之后的以null结束的字符。

n字节—列的数量。如果列的数量小于或等于255则为1字节, 否则为2字节。

n字节—存储表中的每一列的类型,从左到右列出。每个字节被 映射到MYSQL内部列类型。

n字节—字段元数据的大小。对于更多的细节,请参见字段元数 据部分(下一部分)。

n字节—字段元数据值。对于更多的细节,请参见字段元数据部 分(下一部分)。

n字节—null列比特,被舍入到最近的字节。对于每个列,指示 该列中的数据是否为NULL的比特。其所需要的字节数量是 int((column_count+7)/8)。左边的第一列的标记位于第一字节的最低 有效位,第二列的标记位于第一字节的第二最低有效位,第九列的标 记位于第二字节的最低有效位,以此类推。

字段元数据

图7示出了根据一个实施例的字段元数据。字段元数据通常表示 与列元数据的大小有关的额外信息。这可以被看做是封装长度,即封 装特定列值所需要的总字节。这些值稍后用于读取适当的字节以获得 实际值。对于固定长度的类型(例如整数、日期等),该字段元数据 通常是零。例如,对于VARCHAR列类型,该字段元数据表示 VARCHAR列的最大大小。表4示出了针对不同列类型的字段元数 据部分的内容。

表4

假定具有类型为‘MEDIUM BLOB’的blob列的表。Blob列的 最大大小可以是16777216字节(16MB)。该大小通常需要3字 节。对该表进行简单的插入操作。该插入操作在二进制日志中创建了 ‘表映射事件’以及‘写行事件’。二进制日志将BLOB列的长度 以及实际的BLOB数据存储在‘写行事件’部分中。为了获取该 BLOB数据,MySQL VAM需要进行以下步骤:

1.MySQL VAM需要知道计算该BLOB列的长度所需要的字节 存储(在该例子中,其是存储16777216的长度所需要的3字节)。 该值是从‘表映射事件’的‘字段元数据’部分中获取的。

2.基于上述值,为了找到实际数据长度,MySQL VAM从‘写 行事件’读取实际行数据值的前一个或前两个或前三个或前四个字 节。在这种情况中,MySQL VAM需要读取前三个字节来获得 BLOB数据的实际长度值。

3.MySQL VAM基于实际长度分配足够的存储器,并从二进制 日志拷贝数据。

从‘表映射事件’获得该BLOB列所需要的最大列字节存储。 这应该返回3。

column_max_datasize=uint2korr(m_field_metadata);

上述值可以用于从‘Write Rows Event’获得实际数据。

以下例子示出了针对表‘t1’的表映射事件的字节序列顺序,数 据库‘test’描述为:

key int not null,

created date not null,

name char(30),

desc varchar(145)not null,

表8示出了根据一个实施例的表映射事件结构。表映射事件是由 C++类‘CtableMaPEvent’表示的,并且其类结构如下:

写行事件

图9示出了根据一个实施例的写行事件结构。该事件表示 MySQL INSERT(插入)操作。该事件之前是表映射事件。除了通 用头部分以外,该事件包含额外的数据头部分加数据部分。数据头 (8字节)部分包含以下数据,其与之前的表映射事件类似。

table_id:6字节长度。其可以与之前的表映射事件的table_id进行比较。但是并不是很 用用。MySQL VAM忽略该值。

标记:MySQL VAM可以忽略该标记。

写行事件的数据部分包含基于列顺序布置的列值。写行事件由 CwriteRowsEvent类来表示。数据部分包含以下信息:

1或2字节—存储列号。MySQL中支持的最大列是3398。

n字节—列位映射。其是MySQL复制所使用的内部数据结构。 MySQL VAM通常忽略该值。大小为((no_of_cols+7)/8)。

n字节—以(小端字节顺序)指示null列值。总大小通常是 ((no_of_cols+7)/8)。左边的第一列的标记位于第一字节的最低有效 位,第二列的标记位于第一字节的第二最低有效位,第九列的标记位 于第二字节的最低有效位,以此类推。

n字节—插入值的字节序列。可变的列值(例如VARCHAR、 LOB、CHAR类型)之前是其长度。

以下例子示出了对于表t2的写行事件的字节序列顺序。

更新行事件

图10示出了根据一个实施例的更新行事件的结构。该事件表示 MySQL UPDATE(更新)操作。该事件之前是表映射事件。除了通 用的头部分之外,该事件包含额外的数据头部分加数据部分。数据头 (8字节)部分包含以下数据,这与之前的表映射事件类似。

table_id:6字节长度。其可以与之前的表映射事件的table_id进行比较。标记:MySQL  VAM可以忽略该标记。

写行事件的数据部分包含基于列顺序布置的列值。写行事件数据 部分包括像前及像后数据值。与其它日志记录系统不同,MySQL二 进制日志存储列值的整个副本(像前值以及像后值两者),而不是仅 仅存储主键或更新的列。例如,对包含100个列的表上的一个列进行 的更新创建了100个列值的像前副本以及相同的100个列的像后副 本。对于MySQL VAM而言重要的是在向MYSQL API(extract) 发送数据之前压缩(或过滤)数据。写行事件由CupdateRowsEvent 类来表示。数据部分包含以下信息:

1或2字节—存储列号。在MySQL中支持的最大列是3398。

n字节—列位映射。其是MySQL复制所使用的内部数据结构。 MySQL VAM通常忽略该值。大小是((no_of_cols+7)/8)。

n字节—像后列位映射。其是MySQL复制所使用的内部数据结 构。MySQL VAM通常忽略该值。大小是((no_of_cols+7)/8)。

n字节—针对像前数据,以(小端字节顺序)指示null列值。总 大小通常是((no_of_cols+7)/8)。

n字节—像前数据的值的字节序列。可变的列值(例如 VARCHAR、LOB、CHAR类型)之前是其长度。

n字节—针对像后数据,以(小端字节顺序)指示null列值。总 大小通常是((no_of_cols+7)/8)。

n字节—像后数据的值的字节序列。可变的列值(例如 VARCHAR、LOB、CHAR类型)之前是其长度。

删除行事件

该事件表示MySQL DELETE(删除)操作。该事件之前是表映 射事件。除了通用头部分之外,该事件包含额外的数据头部分加数据 部分。数据头(8字节)部分包含以下数据,这与之前的表映射事件 类似。写行事件由CdeleteRowsEvent类来表示。

table_id:6字节长度。其可以与之前的表映射事件的table_id进行比较。标记:MySQL  VAM可以忽略该标记。

写行事件的数据部分包含基于列顺序布置的列值。数据部分与写 行事件的数据部分类似。

CRowsLogEvent C++类

CwriteRowsEvent、CupdateRowsEVent和 CdeleteRowsEvent C++类从CRowsLogEvent C++类继承。

该类包含特定于获取日志数据以用于INSERT、UPDATE 和DELETE操作的大部分公用操作。

旋转事件

在二进制日志中记录旋转事件,从而指示可能的日志旋转,即, MySQL服务器关闭当前二进制日志,并打开新的二进制日志。日志 旋转的可能情形是:

1.日志文件的大小超过了‘max_binlog_size’参数。

2.已经从MySQL命令控制台发出显式‘flush logs’命令。

在这些情况中的任何一种情况下,MySQL在当前二进制日志中 创建旋转事件,关闭当前二进制日志,随后其打开新的二进制日志以 进行进一步处理。旋转事件包含要被创建的新日志文件。MySQL  VAM使用该值来关闭现有二进制日志文件,并打开新的二进制日志 文件,并且继续其读取。旋转事件由CrotateEvent C++类来表示, 被定义为如下:

停止事件

在MySQL服务器显式停机时,MySQL服务器在二进制类中记 录停止事件。MySQL服务器的后续启动创建新的二进制日志文件。 停止事件并不包含新的二进制日志文件的任何项。

事件顺序

图11示出了根据一个实施例的事件顺序。该部分针对不同情形 示出了二进制日志中的事件顺序。参见标题为“事件顺序”的部分来 获得各种事务情形。举例来说,以下语句可以存储在二进制日志文件 中:

start transaction;

insert into t2values(10,’Sample10’);

insert into t3values(20,’Sample20’,NOW());

commit;

图12示出了根据一个实施例的另一事件顺序列子。举另一例子 来说,以下语句存储在二进制日志文件中:

starttransaction;

update t1set a=50where a=10;

savepoint Sv1;

insert into t1values(30,’Sample30’);

rollback to Sv1;

commit;

数据类型

该部分描述二进制日志中的各种支持的数据类型和存储要求。 MySQL支持若干类别的多种数据类型:数值类型、日期和时间类型 以及字符串(字符)类型。在日志记录中,每个类型被存储成一组字 节。所使用的字节的数量取决于数据类型(而不管列是否是可空的) 以及字段的长度。可变长度的字符字段(例如VARCHAR、 VARBINARY、CHAR、TEXT和BLOB等)之前是其长度。

数据类型CHAR、VARCHAR和TEXT可以以ucs2(每个字符 最多2个字节)格式或utf8格式(每个字符2或3字节)存储。例 如,VARCHAR(255)列可以保存最大长度为255个字符的字符 串。假定列使用latin1字符集(一个字符一个字节),所需要的实际 存储是字符串的长度加上用于记录该字符串的长度的一个字节。对于 字符串‘abcd’,L是4,并且存储要求是5个字节。如果相同的列 被改为声称使用ucs2双字节字符集,那么存储要求是10个字节: ‘abcd’的长度是8字节,并且列需要两个字节来存储长度,这是因 为最大长度大于255(多达510个字节)。

根据一个实施例,内联地存储LOB字段。LOB字段之前是其长 度。在表5中描述支持的数据类型以及它们的日志大小。

表5

处理NULL值

根据一个实施例,二进制日志行事件(即,写行事件、更新行事 件和删除行事件)并不与其它非NULL列值一起存储NULL列值。 NULL列值作为一组NULL字节存储在数据部分之前。NULL字节 的总数通常是(列的数量+7)/8。请参考写行事件(待办事项)获得 更多信息。

NULL列按照小端字节顺序存储在这些NULL字节部分中。左 边的第一列的标记位于第一字节的最低有效位,第二列的标记位于第 一字节的第二最低有效位,第九列的标记位于第二字节的最低有效 位,以此类推。可以对NULL字节中的每个比特进行屏蔽,以找到 该列是否保存NULL值。以下代码片段检查列是否为NULL。

空字符串作为零长度的值存储在二进制日志中。

数据类型转换

根据一个实施例,CHAR、BINARY、VARCHAR和 VARBINARY类型—字符串数据类型在长度上是可变的。实际数据 值之前是数据长度。并且,长度的值可能需要1个字节(如果长度小 于255)或2个字节(如果长度大于255)。

如上面所描述的,字符串列的‘fieldmetadata’(应用于 CHAR、VARCHAR、BINARY和VARBINARY类型)有助于找到 长度的最大值。基于该值,可以获取实际长度,如下:

uint2korr()函数是MySQL提供的宏,其定义在config_win.h 中。该函数读取给定指针的前两个字节,并返回相应的整数值。

ENUM类型

根据一个实施例,ENUM列在日志文件中被存储成索引值。例 如,对于被定义成ENUM(‘red’、‘orange’、‘blue’)的列而 言,可以具有索引值0、1和2。所以存储ENUM值‘orange’将在 二进制日志文件中产生索引值2。所支持的最大枚举索引值为65535 个字节。

ENUM列类型的‘fieldmetadata’包含ENUM索引值所需要的 最大字节。基于该值,可以获取实际的长度,如下:

集合类型

根据一个实施例,SET列是字符串列,其可以具有零个或多个 值,每个值必须是从在创建表时指定的允许值的列表中选择的。例 如,被指定为SET('one','two')的列可以具有这些值中的任何一 个:'one'、'two';'one,two'。SET可以具有64个不同成员中的最大 值。在日志文件中,Set列被存储成二进制值。例如,被指定成 SET('a','b','c','d')的列,成员具有以下十进制和二进制值:

SET成员 十进制值 二进制值 ′a′ 1 0001 ′b′ 2 0010 ′c′ 4 0100 ′d′ 8 1000

表6

所以存储SET(‘a’,’b’)可以产生十进制值3(即,二进制值 0011)。由于SET列可以具有64个不同成员中的最大值,所以存储 这些值所需要的最大字节可能达8个字节之多。SET列类型的 ‘fieldmetadata’包含SET十进制值所需要的最大字节。基于该值,可 以获取实际长度,如下:

整数类型

根据一个实施例,在二进制日志中,整数值被存储成有符号的以 及无符号的整数。整数将作为有符号整数被MySQL VAM读取,并 被发送到extract。整数的C类型取决于整数列的大小,其可以由长 度来确定。对于MySQL,具有基于大小的被定义用于所有整数变形 的C类型以及用于将存储器位置拷贝到独立于平台的整数值的相关 联的宏。表7示出了用于每个长度的类型和相关联的宏:

MYSQL类型 字节长度 C类型 TINYINT 1 int8 直接赋值:i1val=data_ptr SMALLINT 2 int16 sint2korr(data_ptr) MEDIUMINT 3 int24 sint3korr(data_ptr) INT,INTEGER 4 int32 sint4korr(data_ptr)

BIGINT 8 int64 sint8korr(data_ptr)

表7

可以将整数值作为指定大小的整数返回给GoldenGate MYSQL VAM,所以数据转换仅仅需要使用适当的宏,并作为整数数据返回 转换的整数和长度。

Float(浮点)、Double(双精度)和Decimal(十进制)类型

根据一个实施例,对于浮点数据类型而言,MySQL将四个字节 用于单精度的值,并且将八个字节用于双精度的值。MySQL允许非 标准的语法:FLOAT(M,D)或DOUBLE(M,D)。这里,“(M,D)”表 示总共可以用多达M个的数字来存储值,这M个数字中的D个数 字可以在小数点之后。对于MYSQL,具有用于float和double列类 型的宏,以用于将存储器位置拷贝到独立于平台的float或double 值。表8示出了用于每个长度的类型以及相关联的宏:

表8

可以将float和double值作为指定大小的浮点数返回给 GoldenGate MYSQL VAM,所以数据转换只需要使用适当的宏,并 作为浮点数数据返回转换的浮点数和长度。

DECIMAL(或NUMERIC)数据类型用于存储精确的数字数据 值。这些类型用于存储对于保留精确的精度而言重要的值,例如强制 数据。在MySQL的版本之前(比5.0.3更早),以字符串格式存储 DECIMAL和NUMERIC值。

使用将9个十进制(基数为10)数字封装成4个字节的二进制 格式来表示DECIMAL列的值。单独地确定每个值的整数部分和小 数部分的存储。9个数字的每个倍数需要4个字节,并且“残余 (leftover)”数字需要4个字节的某个部分。过剩数字所需要的存 储在表9中给出:

残余数字 字节数 0 0 1 1 2 1 3 2 4 2 5 3 6 3 7 4 8 4

表9

对于MySQL,具有用于十进制列类型的函数,用于拷贝包含十 进制值的存储器位置,并将它们转换成字符串值。MySQL VAM使 用‘bin2decimal’函数来读取存储器位置,并将该值填入‘decimal_t’结 构。另一个函数‘decimal_bin_size’简单地转换该‘decimal_t’结构,并 作为字符串返回值。在以下的代码行中对其进行了解释。

十进制值可以作为字符串返回给GoldenGate MySQL VAM,所 以数据转换仅仅需要使用适当的宏,并且返回转换的十进制值。

比特类型

根据一个实施例,BIT(比特)类型列针对每个值存储多达64 个比特。所需要的最大存储是(M+7)/8个字节,其中‘M’指示每个 值的比特数量。MYSQL VAM使用以下代码从二进制日志获取BIT 列值。

DATE(日期)、TIME(时间)、YEAR(年)、DATETIME(日 期时间)和TIMESTAMP(时间戳)类型

日期和时间类型转换是所有数据转换中最复杂的。与其它数据类 型相比,MySQL并不公开用于处理日期和时间类型的MACRO或公 共函数。对MySQL内部实现进行调试,以找到处理这些调用的适当 方法。MySQL VAM已经基于MySQL内部实现重写了其自己的代 码版本。MYSQL VAM从日志获取二进制数据,并将它们转换成共 同的结构MySQL_TIME(该结构由MySQL定义和使用)。之后, 这些结构可以在移交到extract之前被转换成字符串。

DATE类型以封装的三字节整数形式存储成DD+MM×32+ YYYY×16×32。所支持的范围是'1000-01-01'到'9999-12-31'。使用以 下代码从二进制日志中获取DATE列。

TIME类型以封装的三字节整数形式存储成DD×24×3600+ HH×3600+MM×60+SS。使用以下代码从二进制日志获取TIME 列:

YEAR类型以1字节的整数形式进行存储。值可以是‘YYYY’ (值的范围为1901到2155)或‘YY’(值的范围70(1970)到69 (2069)格式。使用以下代码从二进制日志中获取YEAR列值:

当需要包含日期和时间信息两者的值时,使用DATETIME类 型。所支持的范围是'1000-01-0100:00:00'到'9999-12-3123:59:59'。 DATETIME类型被存储成8字节的整数,其包含:被封装成 YYYY×10000+MM×100+DD的四字节整数;被封装成HH×10000 +MM×100+SS的四字节整数。使用以下代码从二进制日志中获取 DATETIME列值:

TIMESTAMP类型是四字节整数,其表示从新纪元以来的秒数 UTC(范围为从'1970-01-0100:00:01'UTC到'2038-01-0903:14:07' UTC)。使用以下代码从二进制日志中获取TIMESTAMP类值:

LOB数据类型

根据一个实施例,MySQL LOBMySQL将LOB记录(大对象— 即TINYBLOB,BLOB,MEDIUM BLOB,LONG BLOB和TEXT类 型)与其它列值一致地存储起来。以与VARBINARY或VARCHAR 字段类似的方式存储BLOB或TEXT列数据,即前几个字节存储长 度,之后是原始的LOB值。对于LOB列,表映射事件的‘field  metadata’包含给定LOB字段所需要的最大字节存储。当分配获取 LOB值所需要的存储器时,该值很容易获得。TINYTEXT和 TINYBLOB列的最大大小是255。这与处理CHAR和BINARY列类 似。

TEXT和BLOB列的最大大小是64k。这与处理VARCHAR和 VARBINARY列类似。可以一次将存储在TINYTEXT、TEXT、 TINYBLOB和BLOB列中的值发送到extract。对于其它LOB类 型,一次可以以64k的数据块读取数据,并将其发送到extract。以 下的代码行解释了处理MYSQL LOB列。

对于其它LOB类型,例如MEDIUM BLOB和LONG BLOB (其可以保存多于64k字节的数据),可以以32k大小的数据块读 取数据,并在多次调用中发送到extract。如上面所描述的,LOB列 值是与其它非LOB列值一致地存储的。这与其它数据库不同,因为 值并不是使用定位符或关联符(coupon)内联地存储以及访问的, 其中可以根据需要取得数据。对于MySQL数据库(具有存储引擎 MyISAM以及InnoDB)并不是这样的。为了从二进制日志读取 LOB列值,MySQL内部IO_CACHE类将该LOB列的整个值从日 志文件中取到存储器中,即该类一次就为该LOB列完全地分配存储 器。

根据一个实施例,MYSQL VAM API规范描述了应当以数据块 将较大大小的LOB数据发送到MYSQL VAM API。但是在MySQL 情况中,MySQL内部类已经在存储器中完全地取得了数据(即, IO_CACHE对象完全地分配了存储器),可以在一个调用以及多个 调用中以32k字节大小的数据块向MySQL VAM API发送LOB数 据。

使用二进制日志工作

如上面所描述的,根据一个实施例,MySQL使用二进制日志索 引文件来维持包含当前二进制日志文件以及较旧的日志文件的列表。 该索引文件存在于与二进制日志相同的目录位置中。这允许系统从配 置文件中进行读取,以找到日志文件格式,例如ROW、 STATEMENT或MIXED格式,并且如果其不是ROW则异常中 止。

当MySQL服务器(在启动期间或通过显式‘flush logs’命令)创 建新的二进制日志文件时,其写BINLOG_MAGIC值(4字节)和 ‘格式描述事件’。对于给定的二进制日志而言,该格式描述只被写一 次。

该格式描述事件的‘flag’属性跟踪当前二进制日志是否被服务 器使用。MySQL服务器在启动期间将该状态设置成 LOG_EVENT_BINLOG_IN_USE_F值,并且在停机或日志旋转期间 清除该值。这可以被看做是用于检查二进制日志是否被适当地关闭的 可靠指示符。

在初始化期间,MySQL VAM需要获得活动二进制日志文件的 名称。MySQL VAM使用以下步骤来获得活动二进制日志的名称。 MySQL服务器使用相同的过程来获得当前二进制日志:

1.从环境变量或所提供的MYSQL VAM参数获得MySQL安装 主页。

2.读取MySQL初始化文件—windows平台中的my.ini或其它 平台中的my.conf。

3.获得‘log-bin’参数的值。从该值找到日志目录位置以及日志索 引文件名称。

4.打开日志索引文件名称,并读取内容。从该内容找到列表中 的最后一个日志文件。

5.打开该日志文件,并检查该日志文件是否仍然被服务器使用 (针对LOG_EVENT_BINLOG_IN_USE_F检查格式描述事件的标 记值)。如果是,则MySQL服务器当前正在使用该日志文件进行 写。MySQL VAM将该日志文件看做是活动日志文件。

定位二进制日志

根据一个实施例,MYSQL VAM API可以请求MySQL VAM通 过时间戳值或序列号进行定位。在extract过程中,可以在GGSCI 中通过ADD或ALTER命令请求定位。在MYSQL VAM中除了支 持通过时间戳或序列号进行定位之外,系统还支持定位到活动二进制 日志的结尾以及开始。

通过序列号进行定位

根据一个实施例,当向extract发送事务记录时,MySQL VAM 还向extract发送序列号值。在重启情形期间,extract在MYSQL  VAMIntialize()调用期间向MySQL VAM发送最后接收到的序列号 值。MySQL使用该值来设置正确的读取位置。

MySQL VAM使用GG_ATTR_DS_SEQID将该序列号值作为 ASCII字符串进行发送。MySQL VAM在向extract发送该ASCII字 符串之前将该值创建成当前日志文件和当前事件位置的组合(即, log.000001:10045)。

在MYSQL VAMInitilize()调用期间为了通过序列号进行定位, MySQL VAM对来自extract的序列号值进行解析,并获得日志文件 名称作为事件位置。随后其打开相应的日志文件,并开始扫描事件。 如果事件的位置与序列号中指定的位置匹配,则MySQL VAM将该 位置设置成当前读取位置,并从该位置开始读取二进制日志内容。

通过时间戳值进行定位

为了通过时间戳进行定位,系统必须在活动二进制日志中找到时 间戳等于或大于所需时间戳值的开始事务记录(即,包含 ‘BEGIN’字符串的QueryEvent)。如果时间戳值是未来的时间, 那么系统可以在日志的末尾继续读取,直到其看见时间戳等于或大于 所述时间戳位置的开始事务记录为止。在二进制日志中或者对于二进 制日志可能出现两种情形:

情形1:在活动二进制日志中存在开始/结束事务记录,并且第一 这样的记录的时间戳小于所需时间戳位置。

在这种情形中,MySQL VAM将扫描活动二进制日志文件以找 到时间戳值大于或等于所需时间戳位置的开始事务记录。如果 MySQL VAM未能找到所需记录,那么它将被定位在日志的末尾。

情形2:活动二进制日志中的第一开始/结束事务记录的时间戳值 大于或等于所需时间戳位置。

这种情形变得比较复杂。在这种情形中,可能的是,较旧的二进 制日志可能也具有时间戳等于所需时间戳值的开始事务记录。

根据一个实施例,MySQL VAM扫描二进制日志,以最新的开 始一直到最旧的。(较旧的维持在日志索引文件中)。如果MySQL  VAM没有找到时间戳等于所需时间戳的开始/结束事务记录,那么 MySQL VAM返回错误或者定位在最旧的日志文件的开始处。通过 时间戳进行定位可能是耗时的过程,这是因为MySQL VAM可能需 要打开较旧的日志文件并搜索与该时间戳匹配的事件项。

定位到日志的末尾

根据一个实施例,为了定位到活动二进制日志的末尾,MySQL  VAM将使用my_b_seek()函数来请求IO_CACHE类寻找日志的末 尾。

定位到日志的开始

根据一个实施例,为了定位到事务日志的开始,MySQL VAM 将调用my_b_seek()函数来定位日志的开始,其中日志的开始位于 BINLOG_MAGIC加全局格式描述事件数据之后的位置处。

读取二进制日志

根据一个实施例,MySQL VAM使用MySQL的IO_CACHE  C++类和文件实用函数来打开并读取MySQL二进制日志。MySQL  IO_CACHE C++类(mysql_client.lib的一部分)以64k大小的数据 块读取二进制日志的内容。这种缓冲的读取有助于减小IO使用。

为了找到读取二进制日志文件的正确序列,对MySQL的各种内 部模块(例如,‘mysqlbinlog’实用程序和‘replication slave  thread’模块进行调试。以下代码行对IO_CACHE类进行初始化, 并打开以及读取二进制日志文件。

日志旋转

根据一个实施例,以下情形导致MySQL的日志旋转(即,关闭 现有活动日志文件并打开新的日志文件)。

1.当活动日志文件的大小超过‘max_binlog_size’的值(在 my.ini或my.conf中指定的)时

a.MySQL在活动二进制日志中记录‘Rotate Event(旋转事 件)’。旋转事件数据部分包含新的活动二进制日志文件的位置和名 称。

b.MySQL关闭活动制日志,并将格式描述事件标记重设成 NULL。(该标记之前是用LOG_EVENT_BINLOG_IN_USE_F值来 设置的)。

c.MySQL创建新的二进制日志,并将格式描述事件标记设置 成LOG_EVENT_BINLOG_IN_USE_F值。

2.当在MySQL SQL提示中发布显式‘flush logs’命令时:

a.MySQL在活动二进制日志中记录‘Rotate Event(旋转事 件)’。旋转事件数据部分包含新的活动二进制日志文件的位置和名 称。

b.MySQL关闭活动二进制日志,并将格式描述事件标记重设 成NULL。(该标记之前是用LOG_EVENT_BINLOG_IN_USE_F 值来设置的)。

c.MySQL创建新的二进制日志,并将格式描述事件标记设置 成LOG_EVENT_BINLOG_IN_USE_F值。

3.在服务器停机期间

a.MySQL在活动二进制日志中记录‘Stop Event(停止事 件)’

b.MySQL关闭该二进制日志。并且将格式描述事件标记重设 成NULL。(该标记之前是用LOG_EVENT_BINLOG_IN_USE_F 值来设置的)。

4.在服务器启动期间

a.MySQL创建新的二进制日志,并将格式描述事件标记设置 成LOG_EVENT_BINLOG_IN_USE_F值。

如上面所描述的,根据一个实施例,MySQL VAM使用旋转事 件来标识日志旋转的发生,并使用旋转事件的数据来获得下一二进制 日志名称。MySQL VAM打开下一二进制日志,并继续其二进制日 志读取。为了处理情形3和4,当MySQL VAM遇到停止事件时, 其关闭其使用的二进制日志,并在日志索引文件中检查下一二进制日 志的存在。如果MySQL VAM在索引文件中找到下一二进制日志, 则其打开该二进制日志,并继续其读取。如果MySQL VAM未能在 索引文件中找到任何新的日志文件名称(服务器仍然处于停机模式, 在停机之后从未启动),那么MySQL VAM通知extract异常中止。

存在一个要考虑的有趣的情形。在服务器崩溃期间,格式描述事 件的标记在服务器重启期间将不被服务器重设的几率比较小。并且 MySQL服务器在活动二进制日志文件中既不记录旋转事件也不记录 停止事件。所以对于后续的启动,服务器创建新的二进制日志文件而 不重设之前的二进制日志中的标记。因此在这种独特的情形中,设置 了两个具有LOG_EVENT_BINLOG_IN_USE_F状态标记的二进制 日志。MySQL VAM在以下条件下可能遇到这种情形:

1.MySQL VAM当前正在处理活动二进制日志。在读取时发生 服务器崩溃。建议是停止extract,进行崩溃恢复以及在服务器启动 之后重启MySQL VAM。

2.MySQL VAM被设置成读取较旧的日志文件。当从一个文件 到另一个文件进行读取(即,日志旋转)时,其遇到具有 LOG_EVENT_BINLOG_IN_USE_F值的日志文件标记。还注意到, 该日志文件不是最新的日志文件(即,不是活动二进制日志)。当 EOF出现时,MySQL VAM可以在日志索引文件中检查下一日志文 件的存在。在这种情况下,MySQL VAM假定之前发生了服务器崩 溃,并且关闭现有日志文件并打开下一日志文件,以及继续日志读 取。

MYSQL VAM类设计

如上面描述的,根据一个实施例,使用C++来编写MySQL VAM实现;其中,MYSQL VAM模块的实现被划分成两个主要部 分。第一部分使用内部开发的事件C++类来读取二进制日志事件, 将这些事件处理成数据记录,使得记录处于准备好的格式(准备好发 送),并将其存储到有限大小的队列中。第二部分每当其从API获 得请求时就从队列中取得记录并将其发送到API。

二进制日志读取器

图13示出了根据一个实施例的用于VAM二进制日志读取器的 类图。CMySQLBinLOGManager类是主要的控制类,其管理整个过 程并将任务委托给不同的类。其主要负责从二进制日志读取数据、处 理二进制日志数据(将MySQL事件转换成数据记录)以及将(准备 好的)记录放入有限大小的队列中。其是从CLOGManager类派生 的,CLOGManager具有全部“纯虚”函数。

设计具有CMySQLBinLogReader类,其负责从二进制日志取 得数据,其使用各种C++事件类和MySQL的IO_CACHE类来管理 二进制日志以及事件实例的生命周期。其还使用CFilterBinLog来过 滤事件。

CLogProcessor类将处理二进制日志数据,并且其用制备的准 备好的对象来填充有限大小的队列(CRecordQueue)。之后,某个 其它类将取得这些对象,并将其发送到API。

CRecordQueue类负责存储准备好的记录(Crecord)。

从头开始,该过程将从CMySQLBinLogManager类的scanLog 函数开始,其是独立地运行的单独的执行实体(线程),并且其负责 整个过程的执行。其首先向CMySQLBinLogReader请求二进制日志 读取,并且其从二进制日志获得原始事件实例。其将该记录传递到 ClogProcessor以便对该记录进行进一步处理并将该记录放入到有限 大小的队列中。

二进制日志处理器

图14示出了根据一个实施例用于二进制日志处理器的类图。

CMySQL VAM模块是整个MYSQL VAM模块的主要控制类; 其是在MYSQL VAM模块的整个生命周期中仅具有1个对象的单态 类。其在其内部具有全部核心业务逻辑,并且其在各个类上委托任 务。

MySQL VAM模块向API公开了4个函数,它们是MYSQL  VAMInitialize、MYSQL VAMRead,MYSQL VAMMesage和 MYSQL VAMControl。这些函数的业务逻辑位于CMySQL  VAMModule类中。其从CRecordQueue取得(由设计的第一部分准 备好的并放入到队列中的)CRecord,并通过CMySQL  VAMCommunicator类将该CRecord发送到API。

CMySQL VAMCommunicator类将负责如何向API发送数据以 及如何从API获得数据;其将使用CMySQL VAMApi类来使用来自 API的公开函数。CMySQL VAMApi类是API的公开函数的包装 器。

CErrorContainer类将在其内部存储错误对象,并且将用于处 理易错情形。

每当从API调用MYSQL VAM公开的函数(即,MYSQL  VAMInitialize)时,流程将定向到CMySQL VAMModule类,并且 其将把流程重定向到某个其它类,并且将向API返回数据。例如, 如果已经从API调用了MYSQL VAMRead,那么CMySQL  VAMModule的MYSQL VAMRead将被调用,并且其将从 CrecordQueue取得数据,并通过CMySQL VAMCommunicator类 将该数据发送到API。

在常规上,可以使用一个或多个常规的通用或专用数字计算 机、计算设备、机器或微处理器(包括一个或多个处理器、存储器和 /或根据本公开内容的教导编程的计算机可读存储介质)来实现本发 明。熟练的编程人员基于本公开内容的教导可以轻易地制备适当的软 件编码,这对于软件领域的技术人员将是显而易见的。

在一些实现中,本发明包括计算机程序产品,所述计算机程序 产品是在其上存储有指令的非瞬时性存储介质或计算机可读介质(媒 体),所述指令可以用于对计算机进行编程以执行本发明的任意过 程。存储介质可以包括但不限于任意类型的盘,包括软盘、光盘、 DVD、CD-ROM、微驱动器以及磁光盘、ROM、RAM、EPROM、 EEPROM、DRAM、VRAM、闪存设备、磁卡或光卡、纳米系统 (包括分子存储IC)或者任意类型的适合于存储指令和/或数据的介 质或设备。

为了解释和描述的目的,已经提供了本发明的以上描述。并不 旨在是穷举的或者将本发明限于所公开的精确形式。许多修改和变形 对于本领域技术人员都将是显而易见的。具体地,虽然所描述的实施 例示出了MySQL环境和MySQL VAM的使用,但是明显的是,可 以用其它类型的数据库或系统来实现其它类型的VAM。选择并描述 了实施例,以便最好地解释本发明的原理及其实际应用,从而使得本 领域其它技术人员能够理解用于各个实施例的以及具有各种适合于预 期特定用途的修改的本发明。本发明的范围旨在由以下权利要求及其 等同形式来限定。

去获取专利,查看全文>

相似文献

  • 专利
  • 中文文献
  • 外文文献
获取专利

客服邮箱:kefu@zhangqiaokeyan.com

京公网安备:11010802029741号 ICP备案号:京ICP备15016152号-6 六维联合信息科技 (北京) 有限公司©版权所有
  • 客服微信

  • 服务号