一种基于日志解析同步的事务合并执行方法及装置
【技术领域】
本发明涉及计算机技术领域,尤其涉及一种基于日志解析同步的事务合并执行方法及装置。
【背景技术】
传统的基于数据库自身的主备机制实现数据库数据的实时复制,是进行数据容灾备份、保障数据安全的重要解决方案。目前如ORACLE公司的DataGuard、达梦数据库的DM7主备产品等都是实现这种解决方案的成熟商业化产品。数据库主备机制下,一般备机作为备份节点,只提供只读访问,可以在备机上做一些报表分析、数据挖掘等只读访问的应用,而不能像主机一样提供读写访问。另外,数据库主备机制要求备机数据库系统和主机一致,对于异构数据库系统环境,则不能利用数据库自身的主备机制实现有效的数据实时复制。
针对数据库主备机制实现数据复制的不足,目前基于软件的异构数据库复制技术应用广泛。这种技术在源端捕获出数据库的增量数据,然后发送到目标端,在目标端通过通用的数据库访问接口将增量数据应用到目标数据库,实现数据复制。这种技术因为使用到通用数据库接口,因此支持异构数据库系统复制,支持异构操作系统环境,并且目标端备机数据库系统可读写,是一种“双活”系统。
目前,有多种技术方式实现获取源端数据库的增量数据,其中,基于数据库日志捕获分析的数据实时同步技术,因其对源数据库侵入性小、捕获分析性能高,得到较大发展及研究。这种技术通过分析源数据库归档或联机日志,捕获出数据库的INSERT、UPDATE、DELETE操作日志,然后发送到目标端;目标端对日志信息进行逆向生成,恢复成SQL语句方式,然后使用数据库通用接口应用到目标数据库,实现数据复制。因此,在数据库实时复制过程中,目标端的执行效率是影响数据同步性能的重要因素。
通常,源端数据库上并发执行的各个事务中可能存在大量小事务,数据库系统都会根据并发控制机制去执行,把相冲突的事务操作互斥执行,并且在日志文件中顺序的记录下各个事务的操作日志;数据同步时应该针对小事务采用事务合并执行的策略,把源端多次执行的操作合并以后批量执行,以便提升同步性能。然而,现有的数据同步系统往往是以事务为单位进行同步的,在确定事务提交以后才会被分配到执行线程执行;在这种机制下,事务合并的方法往往采取事务追加的方式进行合并,这种合并策略虽然可以解决部分的应用场景下同步效率的问题,但是在某些特殊的应用场景下事务合并以后事务之间操作合并率并不高,目标端的执行效率仍较低,无法有效提升同步性能。因此,在如何保证数据复制一致性的前提下来合并事务和事务之间的操作,提高目标端数据复制的执行效率,就成为业界亟待解决的重要技术问题。
鉴于此,克服上述现有技术所存在的缺陷是本技术领域亟待解决的问题。
【发明内容】
本发明需要解决的技术问题是:
现有的数据同步系统往往是以事务为单位进行同步,采取简单的叠加进行事务合并,但事务合并以后事务之间的操作合并率并不高,目标端的执行效率仍较低,无法有效提升同步性能;因此,如何在保证数据复制一致性的前提下提高事务合并以后事务之间操作的合并率,提高目标端数据复制的执行效率,成为业界亟待解决的重要技术问题。
本发明通过如下技术方案解决上述技术问题:
第一方面,本发明提供了一种基于日志解析同步的事务合并执行方法,包括:
选择拥有相同表操作的多个事务,并添加到待合并事务链表;
按顺序依次从待合并事务链表取出各事务进行合并,且每合并一个事务,将该事务的提交LSN添加到已合并事务链表,将合并后生成的操作存放至操作容器;其中,当从待合并事务链表中取出第i个事务时,利用已合并事务链表中的i-1个提交LSN作为分割界限,在操作容器中划出i-1个操作区间;按顺序依次从所述第i个事务中取出操作,通过当前操作的LSN在操作容器中定位到相应的操作区间,并在相应的操作区间内找到与当前操作相同表相同操作类型的操作位置,将当前操作插入至该位置;
完成各事务的合并后,从操作容器中按顺序提取操作执行;其中,夹在两个操作中间的提交操作忽略执行,相同的操作合并后批量执行;
其中,各操作按LSN的大小顺序发送至目的端,所述待合并事务链表与所述已合并事务链表中的对象按事务的提交LSN的大小顺序存放。
优选的,在所述选择拥有相同表操作的多个事务之前,所述方法还包括:
源端数据库同步系统从源端数据库读取日志后,按捕获日志的顺序进行日志解析,并将解析以后的操作按顺序发送到目的端数据库同步系统;
目的端数据库同步系统接收到源端的操作后,按操作的事务ID进行分类管理,在接收到事务提交操作后将对应的事务添加到待执行事务链表;
其中,所述待执行事务链表中的事务按事务提交LSN的大小顺序存放。
优选的,所述选择拥有相同表操作的多个事务,并添加到待合并事务链表,具体为:
执行线程从所述待执行链表中取出一个事务添加到所述待合并链表,根据该事务涉及的表信息从所述待执行链表中选择有相同表操作的事务,并将选出的有相同表操作的事务也添加到所述待合并链表中。
优选的,对于待合并事务链表中的任一事务A,合并过程具体包括:
从所述待合并事务链表中取出事务A,从所述已合并事务链表中取一个提交LSN,并将该提交LSN作为当前的分割LSN;
从事务A中取出一个操作,判断当前操作的操作类型是否是提交操作;如果是提交操作,则将该提交操作追加到操作容器,将对应的提交LSN添加到所述已合并事务链表,并按顺序继续从所述待合并事务链表中取出下一个事务;如果不是提交操作,则判断当前操作的LSN是否小于分割LSN。
优选的,合并过程中采用操作链表来存放需要批量合并的操作,如果当前操作的LSN小于分割LSN,则判断当前操作是否与操作链表中的操作涉及的表和操作类型一致;如果一致,则将当前操作添加到所述操作链表中,并按顺序继续从事务A中提取下一个操作。
优选的,如果当前操作与操作链表中的操作涉及的表或操作类型不一致,则使用分割LSN在所述操作容器中定位,并从定位处向前搜索是否存在和操作链表中的操作相同表并且相同操作类型的操作,一直搜索到上一次合并操作的位置或上个事务的提交操作为止;
如果搜索到与操作链表中的操作相同表并且相同操作类型的操作,则将操作链表中的操作合并至搜索到的位置;如果搜索不到,则将操作链表中的操作合并至搜索停止的位置;
合并完成后清空操作链表,将当前操作添加到操作链表中,并按顺序继续从事务A中提取下一个操作。
优选的,合并过程中采用操作链表来存放需要批量合并的操作,如果当前操作的LSN大于分割LSN,则判断当前所述操作链表中是否存在操作;
如果存在,则使用分割LSN在所述操作容器中定位,并从定位处向前搜索是否存在和操作链表中的操作相同表并且相同类型的操作,一直搜索到上一次合并操作的位置或上个事务的提交操作为止。
优选的,如果搜索到与操作链表中的操作相同表并且相同操作类型的操作,则将操作链表中的操作合并至搜索到的位置;如果搜索不到,则将操作链表中的操作合并至搜索停止的位置;
合并完成后清空操作链表,按顺序继续从所述已合并事务链表中取下一个提交LSN,并将该提交LSN作为新的分割LSN,继续判断当前操作的LSN是否小于新的分割LSN;
其中,在取提交LSN时如果已经到达所述已合并事务链表的末尾,则将事务A中剩余的操作追加到操作容器中,并按顺序继续从所述待合并事务链表中取出下一个事务。
优选的,在从所述已合并事务链表中取提交LSN时,如果所述已合并事务链表为空,或者事务A已经遍历完所述已合并事务链表中的提交LSN,则将事务A中剩余的操作按顺序追加到所述操作容器中;追加完成后,按顺序继续从所述待合并事务链表中取出下一个事务。
第二方面,本发明提供了一种基于日志解析同步的事务合并执行装置,包括至少一个处理器和存储器,所述至少一个处理器和存储器之间通过数据总线连接,所述存储器存储有可被所述至少一个处理器执行的指令,所述指令在被所述处理器执行后,用于完成第一方面所述的基于日志解析同步的事务合并执行方法。
与现有技术相比,本发明的有益效果是:
本发明提供的一种基于日志解析同步的事务合并执行方法中,选择拥有相同表操作的多个事务来进行合并,合并时以先提交事务的提交LSN作为分割界限,将后提交事务在源端数据库中并行执行的部分操作上移来找到相同的操作,使得后提交事务与先提交事务中相同的操作合并到一起,以便在执行的时候可以批量执行,提高了事务合并以后事务之间操作的合并率,可有效提高目标端数据复制的执行效率,提升同步性能。
【附图说明】
为了更清楚地说明本发明实施例的技术方案,下面将对本发明实施例中所需要使用的附图作简单地介绍。显而易见地,下面所描述的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
图1为本发明实施例提供的一种基于日志解析同步的事务合并执行方法的流程图;
图2为本发明实施例提供的一种事务合并方法的具体流程图;
图3为本发明实施例提供的一种基于日志解析同步的事务合并执行装置的架构图。
【具体实施方式】
为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本发明进行进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。
此外,下面所描述的本发明各个实施方式中所涉及到的技术特征只要彼此之间未构成冲突就可以相互组合。下面就参考附图和实施例结合来详细说明本发明。
实施例1:
数据同步在目标端数据库同步事务时,应该本着尽量减少和数据库交互的次数来执行操作,因为每次和数据库交互都会带来额外的开销,批量一千行执行一次插入的操作所花费时间远比执行一千次每次只插入一行花费的时间少,因此操作合并是数据同步中一项非常重要的技术。而基于日志解析同步又是以事务为单位,所以把多个小事务合并成一个大事务,然后针对该大事务中的操作合并后执行可以有效地提升同步性能。
数据库日志在把数据库中的操作写入日志时采用的是串行方式,也就是说,数据库内部并行执行的事务操作产生的日志会交替地写入到日志文件中。鉴于上述原因,假如只有一个活动事务对某个表做DML操作,那么数据库日志中将会连续地记录这个表的DML操作日志;假如有两个活动事务分别针对同一个表做DML操作,那么数据库日志中将会交替地记录这个表上两个事务的DML日志。数据同步在目标端数据库同步这两个事务时,采取事务合并的方式同步这两个事务,如果采用简单的叠加方式,在两个事务操作都是同一个操作的情况下,针对这种最理想的状态两个事务的操作可以合并成一次批量执行;但是如果这两个事务的操作是各种DML操作交替执行,那么就算事务合并了,这种采用简单叠加方式合并后事务操作之间的合并率也会比较低。
基于上述问题,本发明实施例提供了一种基于日志解析同步的事务合并执行方法,如图1所示,主要包括以下步骤:
步骤201,选择拥有相同表操作的多个事务,并添加到待合并事务链表。
其中,每个事务涉及一张或多张表的操作,每个操作对应拥有一个日志序列号(Log Sequence Number,简写为LSN),以表征该操作的执行顺序,源端解析出的各操作会按顺序(即按LSN从小到大的顺序)发送至目的端。在该步骤中,以某一事务涉及的表信息为基准选择拥有相同表操作的多个事务,所述多个事务后续将合并成一个大事务来提交;需要说明的是,“拥有相同表操作”是指涉及对同一个表的同一类型的操作。为了方便操作,可预先初始化一个待合并事务链表,选择完成后将选择出的需要合并的事务添加到所述待合并事务链表。其中,所述待合并事务链表中的事务按事务的提交LSN(即事务中包含的提交操作的LSN)的大小顺序存放,也就是按事务的提交先后顺序存放。
步骤202,按顺序依次从待合并事务链表取出各事务进行合并,且每合并一个事务,将该事务的提交LSN添加到已合并事务链表,将合并后生成的操作存放至操作容器。
在进行事务合并中,可按照各事务的提交LSN由小到大的顺序,依次从所述待合并事务链表取出每个待合并的事务进行合并。为了方便操作,可预先初始化一个已合并事务链表和一个操作容器,每完成一个事务的合并后,将该事务的提交LSN添加到已合并事务链表备用,将合并后生成的操作存放至操作容器。如此一来,当按顺序从所述待合并事务链表中取至第i个事务时,也就已经完成待合并事务链表中前i-1个事务的合并,此时操作容器中已经存放有前i-1个事务合并后生成的事务操作,已合并事务链表中已经存放有前i-1个事务的提交LSN。
进一步地,当从待合并事务链表中取出第i个事务时,利用已合并事务链表中的i-1个提交LSN作为分割界限,在操作容器中划出i-1个操作区间;然后按顺序依次从所述第i个事务中取出每个操作,对于每个操作,通过当前操作的LSN在操作容器中定位到相应的操作区间,并在相应的操作区间内找到与当前操作相同表相同操作类型的操作位置,将当前操作插入至该位置,从而将相同的操作归到一起,方便后续合并与批量执行。具体的合并过程将在实施例2中展开详细介绍,在此不做赘述。
步骤203,完成各事务的合并后,从操作容器中按顺序提取操作执行;其中,夹在两个操作中间的提交操作忽略执行,相同的操作合并后批量执行。
当执行线程遍历完所述待合并事务链表,即所述待合并事务链表中的所有事务都取出并完成事务合并之后,所述待合并事务链表中的多个事务被合并成一个大事务,此时所有待合并事务涉及的操作都已经按设定规则插入至所述操作容器中,且相同操作已归在一起,便可从操作容器中按顺序提取操作执行。需要说明的是,相同的操作需合并后批量执行,夹在两个操作中间的提交操作需忽略执行,即只执行操作容器尾部的提交操作(即提交LSN最大的提交操作);直到操作容器中的所有操作都执行后,提交合并后的该大事务,完成入库。
本发明实施例提供的上述事务合并执行方法中,选择拥有相同表操作的多个事务来进行合并,合并时以先提交事务的提交LSN作为分割界限,将后提交事务在源端数据库中并行执行的部分操作上移来找到相同的操作,尽量将相同的操作归到一起,以便在执行的时候可以批量执行,提高了事务合并以后事务之间操作的合并率,可有效提高目标端数据复制的执行效率,提升同步性能。这主要是基于源端数据库生成的操作在两个提交日志之间是无数据冲突的原则来调整操作的顺序,以提交日志为界,把范围内的操作按表和操作的类型归类,这样就可以有效的提升事务合并以后操作的合并率,实现批量执行以提升入库性能。
实施例2:
上述实施例1中介绍了一种基于日志解析同步的事务合并执行方法的主要步骤,在此基础上,本发明实施例进一步对实施例1中事务合并执行方法的完整步骤展开详细介绍。
结合图2,本发明实施例提供的一种基于日志解析同步的事务合并执行方法,具体包括以下步骤:
步骤101,在源端数据库及目的端数据库部署同步系统。其中,源端数据库同步系统用于从源端数据库读取日志,而目的端数据库同步系统则负责把源端发过来的同步操作应用到目的端数据库。
为了方便后续操作,在所述目的端数据库同步系统启动后,可在目的端初始化一条待执行事务链表、一条待合并事务链表和一条已合并事务链表。其中,待执行事务链表用来存放待执行入库的事务,待合并事务链表用来存放需要合并操作的事务(即待合并的事务),已合并事务链表用来存放已经合并事务的提交LSN,并且三个链表中的事务顺序都按事务的提交LSN的大小顺序存放,也就是按照事务的提交先后顺序存放。
步骤102,源端数据库同步系统从源端数据库读取日志后,按捕获日志的顺序进行日志解析,并将解析以后的操作按顺序发送到目的端数据库同步系统。
步骤103,目的端数据库同步系统接收到源端的操作后,按操作的事务ID进行分类管理,在接收到事务提交操作后将对应的事务添加到待执行事务链表。
具体来讲,目的端数据库同步系统在接收到源端的操作后,会先提取每个操作涉及的表信息;其中,所述表信息包括事务ID、表ID、操作LSN和操作类型等等。然后按照操作的事务ID对事务进行分类管理,并将提取到的表信息添加到对应的事务分类中,也就是将相同事务ID的操作归类为一个小事务;当接收到提交操作时,将该提交操作对应的事务(即前面归类的小事务)添加到所述待执行链表中等待执行。
步骤104,负责事务入库的执行线程先从待执行链表中取出一个事务添加到待合并链表,然后根据该事务涉及的表信息从待执行链表中选择有相同表操作的事务,并将选出的有相同表操作的事务也添加到待合并链表中。
该步骤对应于实施例1中的步骤201,目的是选出合并的事务。其中,选中的事务要从待执行链表中移出,这样下次再选择合并的事务时,上次未能合并的事务就可以继续这个动作。在选择合并的事务个数时,可根据预先设定的合并事务的规模值来决定。假如设定合并以后的操作个数为N,那么在选择事务时就可以统计合并事务的操作数;当操作数达到或超过N时,停止选择。在这里,N如果设置得过小会影响操作合并的效果,而如果设置得过大则会影响执行线程之间的并行度,因此需要根据同步环境来决定N值,在此不做具体限定。
其中,“拥有相同表操作”是指涉及对同一个表的同一类型的操作,即涉及的表ID和操作类型都相同。在进行选择时,可以以提取出的第一个事务涉及的表信息为基准,选择拥有相同表操作的事务来合并。需要说明的是,由于提取的第一个事务中可能涉及多张表的操作,那么在后续选择合并的事务时,第二个事务中涉及的表可能和第一个事务涉及的表不一致(例如,第一个事务中的操作针对表T1和T2,而第二个事务的操作针对表是T1和T3);在这种情况下,应该把这前两个事务涉及的表信息合并到一起作为条件选择第三个事务;依此类推,直到选择出的事务的操作数量规模达到设定值,即待合并链表中事务的操作数量达到N。
步骤105,初始化一个操作容器。执行线程在选择出合并的事务以后,需要继续进行事务之间操作上的合并,为方便操作,此处初始化一个操作容器,准备用来存放合并生成的事务操作。
步骤106,从所述待合并事务链表中取出一个事务A,准备将该事务中的操作合并入所述操作容器中。
其中,这里的事务A可以是指待合并事务链表中的任一事务,且在提取时优先按照各事务的提交LSN从小到大的顺序依次提取。由于每个事务都可能涉及多个操作,为了后续批量合并操作方便,此处可初始化一个操作链表用来存放需要批量合并的操作。如果所有事务都已经合并完成,即所述待合并事务链表中的事务已经全部取完,则直接跳到最后一个步骤113,从操作容器中按顺序提取操作执行。
步骤107,从所述已合并事务链表中取一个提交LSN,并将该提交LSN作为当前的分割LSN。
对于任一事务A,在进行合并时都需要遍历取出所述已合并事务链表中的每个提交LSN,即依次将每个提交LSN作为分割LSN,且取提交LSN时优先按照提交LSN从小到大的顺序依次提取。其中,提取时如果所述已合并事务链表为空,或者事务A已经遍历完所述已合并事务链表中的提交LSN,则将事务A中剩余的操作按顺序追加到所述操作容器中,追加完成后,按顺序继续从所述待合并事务链表中取出下一个事务,即跳到步骤106继续执行;否则将继续向下执行步骤108,进行操作合并。
其中,在合并第一个事务的操作到操作容器中时(即事务A为待合并事务链表中的第一个事务),已合并事务链表为空链表,所以直接采用操作追加的形式按顺序把操作塞入操作容器中,然后把第一个事务的提交LSN添加到已合并事务链表中;在事务A遍历完已合并事务链表时,代表事务A后续的操作LSN比已合并事务链表中最后一个提交LSN都要大,那么这些操作将不能再跟前面的事务的操作合并,所以直接采用操作追加的形式按顺序把这些操作塞入操作容器中。
步骤108,从事务A中取出一个操作,判断当前操作的操作类型是否是提交操作;如果是提交操作,则将该提交操作追加到操作容器,将对应的提交LSN添加到所述已合并事务链表,并按顺序继续从所述待合并事务链表中取出下一个事务,即跳到步骤106;如果不是提交操作,则继续向下执行步骤109。
步骤109,如果不是提交操作,则判断当前操作的LSN是否小于分割LSN。如果当前操作的LSN小于分割LSN,则继续向下执行步骤110;如果当前操作的LSN大于分割LSN,则跳到步骤112继续执行。
步骤110,如果当前操作的LSN小于分割LSN,则判断当前操作是否与操作链表中的操作涉及的表和操作类型一致;如果一致,则将当前操作添加到所述操作链表中,并按顺序继续从事务A中提取下一个操作,即跳到步骤108继续执行;如果不一致,则继续向下执行步骤111。
其中,源端数据库在事务并行执行时,某些事务中批量执行的操作在日志流中可能会被其它事务的操作分隔开,而使用操作链表来缓存同一个事务中连续相同的操作,可以把那些在日志流中不连续但是在本事务中却连续的批量操作进行合并。
步骤111,如果当前操作与操作链表中的操作涉及的表或操作类型不一致,则使用分割LSN在所述操作容器中定位,并从定位处向前搜索是否存在和操作链表中的操作(即当前待合并操作)相同表并且相同操作类型的操作,一直搜索到上一次合并操作的位置或上个事务的提交操作为止。
如果搜索到与操作链表中的操作相同表并且相同操作类型的操作,则将操作链表中的操作合并至搜索到的位置;如果搜索不到,则将操作链表中的操作合并至搜索停止的位置;此处还需记录下合并的位置,下次再合并向前搜索时应该止于此位置。合并完成后清空操作链表,将当前操作添加到操作链表中,并按顺序继续从事务A中提取下一个操作,即跳到步骤108继续执行。
需要说明的是,事务A的第一个操作在操作容器中搜索指定的位置时,从定位开始向前,一直到上一个事务的提交操作为止,这段区间内的操作和事务A的第一个操作在逻辑上是没有冲突的,可以合并到这段区间的任意位置;一旦操作合并以后,后续的操作再次合并时向前搜索的位置就不能越过上次合并的位置,不然就破坏了当前操作在事务A中的操作顺序。
步骤112,如果当前操作的LSN大于分割LSN,则判断当前所述操作链表中是否存在操作;如果存在,则使用分割LSN在所述操作容器中定位,并从定位处向前搜索是否存在和操作链表中的操作相同表并且相同类型的操作,一直搜索到上一次合并操作的位置或上个事务的提交操作为止。
如果搜索到与操作链表中的操作相同表并且相同操作类型的操作,则将操作链表中的操作合并至搜索到的位置;如果搜索不到,则将操作链表中的操作合并至搜索停止的位置;此处还需记录下合并的位置,下次再合并向前搜索时应该止于此位置;合并完成后清空操作链表,按顺序继续从所述已合并事务链表中取下一个提交LSN,并将该提交LSN作为新的分割LSN,继续判断当前操作的LSN是否小于新的分割LSN。其中,在取提交LSN时如果已经到达所述已合并事务链表的末尾,则将事务A中剩余的操作追加到操作容器中,并按顺序继续从所述待合并事务链表中取出下一个事务,即跳到步骤106继续执行。
步骤113,执行线程完成事务合并后,从操作容器中按顺序提取操作执行;该步骤对应于实施例1中的步骤203。
执行到步骤112时,所述待合并事务链表中的所有事务已经完成合并(即所述待合并事务链表中的所有事务合并成一个大事务),各事务涉及的操作也都已经存放至操作容器,且相同的操作被归到一起。那么,在从操作容器中按顺序提取操作执行时,可采用操作链表把操作相同的操作缓存到链表以后批量执行,并忽略夹在两个操作中间的提交操作;直到操作容器中的所有操作都被取出并执行以后,提交合并后的大事务,完成入库。
本发明实施例提供的上述事务合并执行方法,其原理主要是通过利用每个待合并事务的提交LSN做为分割界限,在操作容器中划出一连串的操作区间;在合并操作时,通过操作的LSN定位到相应的操作区间,然后把该操作在它所属的区间内找到相同表相同操作类型的操作位置,把相同的操作合并到一起。这样在事务合并完成以后执行时,比采用事务叠加合并的方式合并率更高,执行次数就更少,从而提升同步性能。
下面对上述事务合并执行方法的基本步骤作如下解释:
首先,数据库的日志流中记录的操作先后顺序可以直接反映出各个事务的操作在数据库内部执行的先后顺序,而以日志流中的提交操作作为分界线则反映出各个事务操作在数据库内部执行的并行度,两个事务的操作在日志流中以第一个提交操作为界,前面重合的那部分操作可以表示在源数据库中是并行执行的,而后面单个事务的操作在源数据库运行时可能会访问到前面一个事务的数据。那么这两个事务在合并时,如果采用简单叠加的方式,那只有当先提交事务的最后一个操作和后提交事务的第一个操作都相同的情况下才能合并执行。而本发明采用以先提交事务在日志流中的提交操作为界限,后提交的事务在该界限之前的操作在先提交的事务操作中间寻找合适的位置,把后提交事务界限之前的操作按一定规则插入进去,使得这些操作和先提交的事务操作合并执行,来提升事务合并以后操作的合并率。
其次,这种以事务为单位的合并方式不会破坏事务的原子性。由于在执行合并后的操作时忽略掉了操作中间夹杂的提交操作,只有在所有操作执行完成以后才整体提交,当合并的事务执行发生异常时,目的端数据库会回滚掉整个大事务,目的端数据同步系统只需要重新执行合并后的操作即可,这样即可以保证执行时事务逻辑的一致性,又可以提升执行性能。
实施例3:
在上述实施例1和实施例2的基础上,本发明实施例提供了一种基于日志解析同步的事务合并执行方法的具体实例,以便更好地理解整个事务合并执行过程。
在该具体的实施例中,假设源端数据库和目的端数据库现都有表T1(ID VARCHAR)和T2(ID VARCHAR)。
源端应用有三个事务,对表T1和T2进行如下操作:
TRX1:INSERT INTO T1(ID)VALUES('TRX1_T1_1');
TRX2:INSERT INTO T1(ID)VALUES('TRX2_T1_10');
TRX1:INSERT INTO T1(ID)VALUES('TRX1_T1_2');
TRX1:UPDATE T1SET ID='TRX1_T1_2'WHERE ID='TRX1_T1_2';
TRX3:INSERT INTO T2(ID)VALUES('TRX3_T2_300');
TRX3:INSERT INTO T1(ID)VALUES('TRX3_T1_30');
TRX1:COMMIT;
TRX2:INSERT INTO T1(ID)VALUES('TRX2_T1_20');
TRX3:UPDATE T1SET ID='TRX3_T1_30'WHERE ID='TRX3_T1_30';
TRX2:UPDATE T1SET ID='TRX2_T1_20'WHERE ID='TRX2_T1_20';
TRX2:COMMIT;
TRX3:UPDATE T1SET ID='TRX3_T1_10'WHERE ID='TRX3_T1_10';
TRX3:COMMIT;
上述各操作的顺序在日志接收线程接收到之后,会形成如表1所示的情况。
表1:
事务ID |
操作 |
LSN |
TRX1 |
INSERT INTO T1(ID)VALUES('TRX1_T1_1') |
1 |
TRX2 |
INSERT INTO T1(ID)VALUES('TRX2_T1_10') |
2 |
TRX1 |
INSERT INTO T1(ID)VALUES('TRX1_T1_2') |
3 |
TRX1 |
UPDATE T1 SET ID='TRX1_T1_2'WHERE ID='TRX1_T1_2' |
4 |
TRX3 |
INSERT INTO T2(ID)VALUES('TRX3_T2_300') |
5 |
TRX3 |
INSERT INTO T1(ID)VALUES('TRX3_T1_30') |
6 |
TRX2 |
INSERT INTO T1(ID)VALUES('TRX2_T1_20') |
7 |
TRX1 |
COMMIT; |
8 |
TRX3 |
UPDATE T1 SETID='TRX3_T1_30'WHERE ID='TRX3_T1_30' |
9 |
TRX2 |
UPDATE T1 SET ID='TRX2_T1_20'WHERE ID='TRX2_T1_20' |
10 |
TRX2 |
COMMIT; |
11 |
TRX3 |
UPDATE T1 SETID='TRX3_T1_10'WHERE ID='TRX3_T1_10'; |
12 |
TRX3 |
COMMIT; |
13 |
结合图2给出的执行步骤,本发明实施例中的事务合并过程具体如下:
步骤301,选择拥有相同表操作的事务作为合并的事务,并添加到待合并事务链表。按照上述选择规则,生成的待合并链表中的事务详细情况为{TRX1,TRX2,TRX3},即待合并链表中有TRX1、TRX2、TRX3三个事务。
步骤302,构造一个操作容器。为了陈述方便,此处以表格做为容器来解释操作合并的过程,所述操作容器如表2所示。
表2:
步骤303,从待合并链表中取出第一个事务TRX1,其操作信息如表3。
表3:
事务ID |
操作 |
LSN |
TRX1 |
INSERT INTO T1(ID)VALUES('TRX1_T1_1') |
1 |
TRX1 |
INSERT INTO T1(ID)VALUES('TRX1_T1_2') |
3 |
TRX1 |
UPDATE T1 SET ID='TRX1_T1_2'WHERE ID='TRX1_T1_2' |
4 |
TRX1 |
COMMIT; |
8 |
此时,由于已合并事务链表为空,那么第一个事务TRX1的操作顺序追加到操作容器中,形成如表4所示的操作面局。
表4:
然后把提交LSN添加到已合并事务链表中,形成{TRX1(LSN=8)}。
步骤304,从待合并链表中取出第二个事务TRX2,其操作信息如表5。
表5:
事务ID |
操作 |
LSN |
TRX2 |
INSERT INTO T1(ID)VALUES('TRX2_T1_10') |
2 |
TRX2 |
INSERT INTO T1(ID)VALUES('TRX2_T1_20') |
7 |
TRX2 |
UPDATE T1 SET ID='TRX2_T1_20'WHERE ID='TRX2_T1_20' |
10 |
TRX2 |
COMMIT; |
11 |
步骤305,从已合并事务链表中取出第一个事务TRX1的提交LSN(LSN=8),把它作为第一分割LSN去分割事务TRX2中的操作。
步骤306,从事务TRX2中提取到第一个INSERT操作,它的LSN(LSN=2)比第一分割LSN要小,所以将该操作添加到操作链表。
步骤307,从事务TRX2中提取到第二个INSERT操作,它的LSN(LSN=7)比第一分割LSN要小,所以将该操作添加到操作链表。
步骤308,从事务TRX2中提取到第三个UPDATE操作,它的LSN(LSN=10)比第一分割LSN要大,所以需要对操作链表进行清空;即,使用第一分割LSN(LSN=8)在操作容器中定位,并从定位处向前搜索到相同操作的位置,把操作链表中的操作(即事务TRX2的前两个INSERT操作,LSN=2,LSN=7)插入操作容器,形成如表6所示的操作面布局。
表6:
通过表6可以发现,前两个INSERT操作被归类到了操作容器中第一分割LSN之前的INSERT操作一起。插入操作容器完成以后,取已合并链表中下一个提交LSN;由于已到达已合并链表末尾,则事务TRX2后续的操作(即后两个操作,LSN=10,LSN=11)直接追加到操作容器中,形成如表7所示的操作面布局。
表7:
然后将事务TRX2的提交LSN添加到已合并事务链表中,形成:{TRX1(LSN=8),TRX2(LSN=11)}。其中,后续使用时,LSN=8仍作为第一分割LSN,而LSN=11将作为第二分割LSN。
步骤309,从待合并链表中取出第三个事务TRX3,其操作信息如表8。
表8:
事务ID |
操作 |
LSN |
TRX3 |
INSERT INTO T2(ID)VALUES('TRX3_T2_300') |
5 |
TRX3 |
INSERT INTO T1(ID)VALUES('TRX3_T1_30') |
6 |
TRX3 |
UPDATE T1 SET ID='TRX3_T1_30'WHERE ID='TRX3_T1_30' |
9 |
TRX3 |
UPDATE T1 SET ID='TRX3_T1_10'WHERE ID='TRX3_T1_10'; |
12 |
TRX3 |
COMMIT; |
13 |
步骤310,从已合并事务链表中取出第一个事务TRX1的提交LSN(即8),把它作为第一分割LSN去分割事务TRX3中的操作。
步骤311,从事务TRX3中提取到第一个INSERT操作,它的LSN(LSN=5)比第一分割LSN要小,所以将该操作添加到操作链表。
步骤312,从事务TRX3中提取到第二个INSERT操作,它的LSN(LSN=6)比第一分割LSN要小,但是该操作和操作链表中的INSERT操作不相同(即操作的表不一样),所以需要清空操作链表;然后使用第一分割LSN(LSN=8)在操作容器中定位,并从定位处向前搜索到相同操作的位置,把操作链表中的操作(即事务TRX3的第一个INSERT操作,LSN=5)插入操作容器,形成如表9所示的操作面布局。
表9:
LSN |
操作 |
备注 |
5 |
INSERT INTO T2(ID)VALUES('TRX3_T2_300') |
TRX3 |
1 |
INSERT INTO T1(ID)VALUES('TRX1_T1_1') |
TRX1 |
3 |
INSERT INTO T1(ID)VALUES('TRX1_T1_2') |
TRX1 |
2 |
INSERT INTO T1(ID)VALUES('TRX2_T1_10') |
TRX2 |
7 |
INSERT INTO T1(ID)VALUES('TRX2_T1_20') |
TRX2 |
4 |
UPDATE T1 SETID='TRX1_T1_2'WHERE ID='TRX1_T1_2' |
TRX1 |
8 |
COMMIT; |
TRX1 |
10 |
UPDATE T1 SET ID='TRX2_T1_20'WHERE ID='TRX2_T1_20' |
TRX2 |
11 |
COMMIT; |
TRX2 |
然后把当前操作(即事务TRX3的第二个INSERT操作,LSN=6)添加到操作链表。
步骤313,从事务TRX3中提取后续操作,此时需将当前操作的LSN与第二分割LSN(LSN=11)比较,具体可参照事务TRX2的合并规则,在此不做赘述。合并以后,形成如表10所示的操作布局。
表10:
步骤314,在待合并事务链表中的三个事务都合并完成后,执行整个大的事务时,就可以合并相同的操作,形成如表11所示的执行方式。
表11:
从表11所示的合并以后的操作布局可以看出,事务TRX2和事务TRX3中本来独立的INSERT操作都将被批量执行,可以和采用叠加方式来合并后的操作布局进行对比,就可能看出合并率的明显提升。其中,采用叠加方式合并后的操作布局如表12所示。
表12:
通过比较表11和表12中的两个操作布局可以看出,采用本发明实施例的方案合并以后执行次数为3次,而采用叠加合并的方案则需要执行7次,本发明提供的方法明显优于传统方案。
需要说明的是,本发明实施例是以涉及三个事务TRX1、TRX2、TRX3和两个表T1、T2为例进行说明,但并不用以限制本发明。当涉及的事务数量和表数量出现变化时,具体的事务合并执行过程仍可参考上述实施例中的步骤,在此不做赘述。
实施例4:
在上述实施例1-实施例3提供的基于日志解析同步的事务合并执行方法的基础上,本发明还提供了一种可用于实现上述方法的基于日志解析同步的事务合并执行装置,如图3所示,是本发明实施例的装置架构示意图。本实施例的基于日志解析同步的事务合并执行装置包括一个或多个处理器21以及存储器22。其中,图3中以一个处理器21为例。
所述处理器21和所述存储器22可以通过总线或者其他方式连接,图3中以通过总线连接为例。
所述存储器22作为一种基于日志解析同步的事务合并执行方法非易失性计算机可读存储介质,可用于存储非易失性软件程序、非易失性计算机可执行程序以及模块,如实施例1-实施例3中的基于日志解析同步的事务合并执行方法。所述处理器21通过运行存储在所述存储器22中的非易失性软件程序、指令以及模块,从而执行基于日志解析同步的事务合并执行装置的各种功能应用以及数据处理,即实现实施例1-实施例3的基于日志解析同步的事务合并执行方法。
所述存储器22可以包括高速随机存取存储器,还可以包括非易失性存储器,例如至少一个磁盘存储器件、闪存器件、或其他非易失性固态存储器件。在一些实施例中,所述存储器22可选包括相对于所述处理器21远程设置的存储器,这些远程存储器可以通过网络连接至所述处理器21。上述网络的实例包括但不限于互联网、企业内部网、局域网、移动通信网及其组合。
所述程序指令/模块存储在所述存储器22中,当被所述一个或者多个处理器21执行时,执行上述实施例1-实施例3中的基于日志解析同步的事务合并执行方法,例如,执行以上描述的图1和图2所示的各个步骤。
本领域普通技术人员可以理解实施例的各种方法中的全部或部分步骤是可以通过程序来指令相关的硬件来完成,该程序可以存储于一计算机可读存储介质中,存储介质可以包括:只读存储器(ROM,Read Only Memory)、随机存取存储器(RAM,Random AccessMemory)、磁盘或光盘等。
以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。