一种基于并行执行的数据同步的方法和装置
【技术领域】
本发明涉及数据库领域,特别是涉及一种基于并行执行的数据同步的方法和装置。
【背景技术】
传统的基于数据库自身的主备机制实现数据库数据的实时复制,是进行数据容灾备份,保障数据安全的重要的解决方案。但是,数据库主备机制要求备机数据库***和主机一致,对于异构数据库***环境,则不能利用数据库自身的主备机制实现有效的数据实时复制。为了实现异构数据库的数据实时复制,目前通常使用基于软件的异构数据库同步方法,该方法在源端捕获源数据库的增量数据,然后发送到目标端,在目标端通过通用的数据库访问接口将增量数据应用到目标数据库,实现数据复制。
在数据库同步的实时同步过程中,需要按照数据库日志文件中所记录的各个事务的操作顺序进行同步,否则会破坏源数据库和目标数据库之间的数据一致性。如果目标端的数据同步软件严格按照源端数据库日志文件中的事务顺序进行同步,虽然能够有效保证数据复制的一致性,但是会严重影响数据同步的并行度,同步效率将会非常低下。
鉴于此,如何克服该现有技术所存在的缺陷,解决异构数据库同步时数据一致性和并行执行相冲突的现象,是本技术领域待解决的问题。
【发明内容】
针对现有技术的以上缺陷或改进需求,本发明解决了数据库同步时为确保数据一致性而产生的并行冲突问题,在保证同步数据准确的基础上,实现了高效而简便的异构数据库并行同步。
本发明实施例采用如下技术方案:
第一方面,本发明提供了一种基于并行执行的数据同步的方法,具体为:获取需同步的事务;创建至少两个执行线程,每个执行线程中包括一个唤醒队列;按照提交顺序将事务逐一分配至不同的空闲的执行线程,被分配至每个线程中的事务为每个执行线程的当前事务;获取每个执行线程的当前事务中的每个操作,根据每个操作的唯一标识符对每个操作构造行锁;判断每个执行线程中的当前事务是否与提交顺序在其之前的事务存在行锁冲突,若存在行锁冲突,则将当前事务放入与其存在行锁冲突的事务所在的执行线程的唤醒队列中进行等待;执行线程并行执行不存在行锁冲突的当前事务;每个执行线程执行完当前事务后,唤醒执行线程的唤醒队列中的事务。
优选的,根据每个操作的唯一标识符对每个操作构造行锁,具体包括:在每个执行线程中创建一个行锁哈希表,以每个操作的唯一标识符为行锁哈希表的key,以每个操作为行锁哈希表的一个记录。
优选的,判断每个执行线程中的当前事务是否与提交顺序在其之前的事务存在行锁冲突,具体包括:获取第一执行线程的行锁哈希表为第一行锁哈希表;获取第二执行线程的行锁哈希表为第二行锁哈希表,其中,第二执行线程的当前事务提交顺序在第一线程之前;判断第一行锁哈希表和第二行锁哈希表中是否存在相同的key;若存在相同的key,表示第一线程的当前事务与第二线程的当前事务存在行锁冲突;若不存在相同的key,表示第一线程的当前事务与第二线程的当前事务不存在行锁冲突;对每一组第一线程和第二线程逐一比较,判断每两个线程间是否存在行锁冲突。
优选的,将当前事务放入与其存在行锁冲突的事务相应的唤醒队列中进行等待,具体包括:若当前事务和多个事务存在行锁冲突,查找所有存在行锁冲突的事务中提交顺序在当前事务之前且提交顺序与当前事务最接近的事务,将当前事务放入查找到的事务所在的执行线程的唤醒队列中。
优选的,方法还包括:若执行线程的当前事务执行完成,将执行线程的行锁哈希表中的行锁全部释放。
优选的,方法还包括执行事务列表,获取需同步的事务后,将需同步的事务按提交顺序放入执行事务列表中,以便于对需同步的事务进行查找和分配。
优选的,判断每个执行线程中的当前事务是否与提交顺序在其之前的事务存在行锁冲突时,具体包括:在执行事务列表中查找当前事务所在位置,由当前事务所在位置开始,依次逆序获取需执行的事务,判断当前事务与每个需执行的事务之间是否存在行锁冲突,找到第一个存在行锁冲突的需执行事务时停止判断。
优选的,还包括事务接收线程,事务接收线程对获取到的需同步的事务进行接收,将需同步的事务存放至执行事务列表中,并在执行线程空闲时将执行事务列表中的需执行的事务依次分配至执行线程中。
优选的,事务接收线程对获取到的需同步的事务进行接收后,根据需同步的事务ID对需同步的事务进行分类,仅将提交操作对应的事务存放至执行事务列表中。
另一方面,本发明提供了一种基于并行执行的数据同步的装置,具体为:包括至少一个处理器和存储器,至少一个处理器和存储器之间通过数据总线连接,存储器存储能被至少一个处理器执行的指令,指令在被处理器执行后,用于完成权利要求1-9任一的基于并行执行的数据同步的方法。
与现有技术相比,本发明实施例的有益效果在于:通过多线程并行同步提高同步效率,通过对可能造成同步数据错误的操作添加互斥锁以避免数据错误,通过唤醒队列简化事务执行顺序的控制复杂度,从而实现高效而简便的异构数据库并行同步。
进一步的,本发明提供的方案中的行锁哈希表在事务执行完成后整体释放资源,并通过数据读取线程对待同步的操作进行分类,进一步提高了异构数据库的同步效率。
【附图说明】
为了更清楚地说明本发明实施例的技术方案,下面将对本发明实施例中所需要使用的附图作简单地介绍。显而易见地,下面所描述的附图仅仅是本发明的一些实施例,对于本领域普通技术人员来讲,在不付出创造性劳动的前提下,还可以根据这些附图获得其他的附图。
图1为本发明实施例提供的一种基于并行执行的数据同步的方法流程图;
图2为本发明实施例提供的另一种基于并行执行的数据同步的方法时序图;
图3为本发明实施例提供的另一种基于并行执行的数据同步的方法流程图;
图4为本发明实施例提供的另一种基于并行执行的数据同步的方法流程图;
图5为本发明实施例提供的另一种基于并行执行的数据同步的方法流程图;
图6为本发明实施例提供的一种基于并行执行的数据同步的装置结构示意图;
其中,附图标记如下:
21:处理器;22:存储器。
【具体实施方式】
为了使本发明的目的、技术方案及优点更加清楚明白,以下结合附图及实施例,对本发明进行进一步详细说明。应当理解,此处所描述的具体实施例仅仅用以解释本发明,并不用于限定本发明。
本发明是一种特定功能***的体系结构,因此在具体实施例中主要说明各结构模组的功能逻辑关系,并不对具体软件和硬件实施方式做限定。
此外,下面所描述的本发明各个实施方式中所涉及到的技术特征只要彼此之间未构成冲突就可以相互组合。下面就参考附图和实施例结合来详细说明本发明。
实施例1:
在数据库***中,源端数据库中的所有事务中的操作都会记录至数据库日志中,若在目的数据库中获取并重复这些事务中的操作,即能够使目的数据库中的数据与源端数据库日志中的数据一致。在需要同步的事务数量较大时,单一线程顺序执行会导致数据同步的等待时间较长,实时性较差,但并行执行时,目的数据库中的操作执行顺序又可能会和源端数据库不一致,造成同步错误。因此,本发明实施例提供了一种能够在保证事务执行顺序一致的前提下并行执行事务的数据同步方法。
如图1所示,本发明实施例提供的基于并行执行的数据同步的方法具体步骤如下:
步骤101:获取需同步的事务。
进行数据同步时,需要将源端数据库中的数据同步至目的端数据库,因此首先需要获取源端的数据。在数据库领域中,由于需同步的数据量较大,为了减少同步的数据总量,可以采用增量同步的方式,即在前一次同步的基础上,对于未变化的数据不重复进行同步,仅同步发生变化的数据。源端数据库通过执行事务产生数据变化,每个事务中包含一个或多个数据库操作,每个操作会产生一个数据变化。操作包括读取数据、写数据、更新修改数据、删除数据等,在具体实施场景中,一个操作可以对应一个SQL语句。源端数据库中已被执行的事务会根据事务提交顺序编号并存放在数据库日志中,根据源端数据库的数据库日志中的事务提交顺序在目的端数据库中重复相同的事务,即可使目的端数据库的数据产生同样的变化,达到数据同步的目的。在非数据库领域,事务和操作表示与数据库的事务和操作相应的能产生数据变化的动作,如文档数据库、文件、分布式***等文件***中,操作可以为文件或数据块的新建、更改、删除等。
步骤102:创建至少两个执行线程,每个执行线程中包括一个唤醒队列。
为了提高目的端事务执行效率,进行数据同步时目的端对事务采用并行执行的方式,因此,需要创建多个能够并行执行的执行线程,将需要执行的事务分配至不同的执行线程进行执行。为了保证每个执行线程中执行顺序正确且不发生冲突,若两个事务中包含了针对同一数据的操作,提交顺序在后的事务需要等待提交顺序在前的事务执行完毕后再进行执行。因此,每个执行线程中还需要包括一个唤醒队列,用来存放提交顺序在执行线程的当前事务之后,并且包含了和当前事务相冲突的操作的事务,放入当前事务的唤醒队列中,等待当前事务执行完毕,操作不存在冲突后,对提交顺序在后的事务进行唤醒。
步骤103:按照提交顺序将事务逐一分配至不同的空闲的执行线程,被分配至每个线程中的事务为每个执行线程的当前事务。
每个执行线程同一时间只能执行一个事务,因此每个执行线程中每次仅能够被分配一个事务,该事务称为执行线程的当前事务。执行线程中没有被分配当前事务时的状态为空闲,空闲的执行线程可以接受按照事务提交顺序被分配的下一个事务。若同时存在多个空闲的执行线程,则向每个空闲的执行线程中分配一个事务。
步骤104:获取每个执行线程的当前事务中的每个操作,根据每个操作的唯一标识符,对每个操作构造行锁。
不同事务中针对同一个数据的不同操作会造成冲突,如针对数据库中同一行数据的两次更新,为了判断事务中是否存在互相冲突的操作,可以根据操作中数据的唯一标识符对操作构造行锁。具体的,可以使用唯一标识符的值作为行锁的值,若两个事务中存在行锁的值相同的操作,即表示两个事务之间存在行锁冲突。在数据库使用场景中,可以使用ROWID作为操作的唯一标识符,虽然不同的数据库在ROWID的结构上有不同的体现形式,有的采用物理地址构成,例如ORACLE,有的采用逻辑整数构成,例如SQL SERVER和DM7等,但是都遵循一个原则,就是在单个表上每行数据的ROWID值都是唯一的。同时,在数据库记录的日志操作中,每个操作的日志上都带有相应的ROWID信息用来标记日志操作对应的数据行,从数据库日志中获取需同步的事务即可同时获取事务中每个操作的ROWID作为唯一标识符。数据库的运行机制保证相同ROWID的数据不允许被多个事务并行的修改,那么数据同步在把这些带有ROWID信息的操作入库时,就可以通过互斥带有相同ROWID信息的事务,把相冲突的事务串行执行,而无冲突的事务并行执行,有效的增加事务入库的并行度,在不发生冲突的情况下部分忽略事务提交先后顺序,从而提升同步的性能。在非数据库领域,可以根据实际场景选择实际使用的唯一标识符,如文件ID;还可以使用多个特征值组作为数据的唯一标识符,如多个表同时同步时,使用表名+ROWID作为数据的唯一标识符。
步骤105:判断每个执行线程中的当前事务是否与提交顺序在其之前的事务存在行锁冲突,若存在行锁冲突,则将当前事务放入与其存在行锁冲突的事务所在的执行线程的唤醒队列中进行等待。
为了避免事务执行时出现冲突,可以根据行锁判断每个执行线程的当前事务是否存在行锁冲突,若两个线程的当前事务包含相同的行锁,表示两个事务之间存在行锁冲突,两个事务中提交顺序在后的事务需要等待提交顺序在前的事务执行完成后开始执行。因此,当两个事务之间存在行锁冲突时,需要将提交顺序在后的事务放入提交顺序在前的事务所在的执行线程中的唤醒队列,并将提交顺序在后的事务所在的执行线程挂起,以便于提交顺序在前的事务执行完成后对提交顺序在后的事务进行唤醒。使用唤醒队列,通过唤醒消息触发下一事务的执行,可以方便的管理互相冲突的事务间的执行顺序,不需要额外的执行状态监控和调度。
步骤106:执行线程并行执行不存在行锁冲突的当前事务。
对于不存在行锁冲突的事务进行并行执行,不会造成同步冲突,因此可以使用并行的方式执行事务,充分利用***资源,减少事务执行的总时间,提高数据同步效率。由于步骤103中将事务分配至执行线程时按照事务提交顺序进行分配,步骤104-步骤105中通过行锁和唤醒队列进一步限制了事务的执行顺序,因此并行执行不会导致事务的执行顺序与提交顺序不一致,可确保事务执行完成后数据正确。
步骤107:每个执行线程执行完当前事务后唤醒执行线程的唤醒队列中的事务。
每个执行线程执行完当前事务后,会对该执行线程中唤醒队列的事务进行唤醒,启动唤醒队列中的事务执行。通过加入唤醒队列和唤醒的方式,可以方便的完成事务的顺序调度,不需要使用额外的调度处理,减少了调度难度和调度所需的资源消耗,提高了调度效率和稳定性。若执行线程的唤醒队列中存在多个正在等待的事务,将正在等待的事务全部唤醒,激活被唤醒的事务所在的执行线程,即激活步骤105中被挂起的执行线程,并按照步骤106执行被唤醒的事务。循环执行加入唤醒队列和唤醒的步骤,直至需同步的事务执行完毕。另一方面,当某个事务存在于多个线程的唤醒队列中时,需要等待所有唤醒队列对其唤醒后,才能开始激活执行。
进一步的,执行线程执行完当前事务后,会按照事务提交顺序被分配下一个未被分配的事务,并对下一个事务重复步骤104-步骤106,直至所有需同步的事务执行完成。
如图2所示的时序图,以一个具体实施场景为实例,具体说明步骤101-步骤107。
源数据库和目标端数据库现都存在表T(ID INT PRIMARY KEY,C1 INT)。
源端应用对表T进行如下操作:
操作1:INSERT INTO T(ID,C1)VALUES(1,1);
操作2:INSERT INTO T(ID,C1)VALUES(2,2);
COMMIT;
操作3:UPDATE T SET C1=10WHERE ID=1;
COMMIT;
操作4:UPDATE T SET C1=20WHERE ID=2;
COMMIT;
上述串行执行的操作包含三个COMMIT操作,会在源端数据库的日志中生成三个事务,按照事务提交顺序分别为TRX1、TRX2和TRX3。其中,TRX1包括操作1、操作2和COMMIT操作,向T表中***了ID为1和ID为2的两行数据;TRX2包括操作3和COMMIT操作,更新了T表中ID为1的行;TRX3包括操作4和COMMIT操作,更新T表中ID为2的行。三个事务都会导致源端数据库的数据变化,因此按照步骤101获取TRX1、TRX2和TRX3为需同步的事务。
按照步骤102,在目的数据库中创建三个执行线程,分别为EXEC1、EXEC2和EXEC3。执行线程的数量具体由目的端的资源数确定,本实施例中创建三个执行线程不表示限制具体线程数的限定。
按照步骤103,当前执行线程EXEC1、EXEC2和EXEC3都为空闲状态,将事务TRX1、TRX2和TRX3按照事务提交顺序逐一分配至三个执行线程。分配后,TRX1为EXEC1的当前事务,TRX2为EXEC2的当前事务,TRX3为EXEC3的当前事务。
按照步骤104,由于事务中的操作除COMMIT操作外都是按行执行,选择行号ID,即ROWID,为操作的唯一标识符。根据操作的唯一标识符ROWID为每个操作构造行锁:操作1的行锁为ID=1,操作2的行锁为ID=2,操作3的行锁为ID=1,操作4的行锁为ID=2。
按照步骤105,判断每个事务是否与提交顺序在其之前的事务存在行锁冲突。TRX1最先提交,因此不存在与其行锁冲突的事务;TRX2中操作3的行锁ID=1与TRX1中操作1的行锁ID=1相同,TRX2与TRX1存在行锁冲突,将TRX2放入TRX1所在线程EXEC1的唤醒队列;TRX3中操作4的行锁ID=2与TRX1中操作2的行锁ID=2相同,TRX3与TRX1存在行锁冲突,将TRX3放入TRX1所在线程EXEC1的唤醒队列;TRX3中操作4的行锁ID=2与TRX2中操作3的行锁ID=1不同,因此不存在行锁冲突。
按照步骤106,EXEC1中的事务TRX1提交顺序最先,因此可以开始执行。EXEC2中的事务TRX2和EXEC3中的事务TRX3,由于事务提交顺序在TRX1之后,且和TRX1存在行锁冲突,因此被放入EXEC1的唤醒队列,需要等待TRX1执行完毕进行唤醒后,再开始执行。
按照步骤107,TRX1执行完成后,接受下一个被分配的事务,并对所在执行线程EXEC1唤醒队列中的TRX2和TRX3进行唤醒。由于TRX2和TRX3之间不存在行锁冲突,因此TRX2和TRX3可以并行执行。
在上述实例中,由于使用多线程并发执行,将原顺序执行TRX1+TRX2+TRX3串行执行的总时间,减少为TRX1+TRX2或TRX1+TRX3的执行时间,减少了事务执行的总时间,提高了同步效率。同时,通过行锁避免了TRX2中操作3和TRX1中操作1的冲突,以及TRX3中操作4与TRX1中操作2的冲突,保证了同步数据的正确。
为了便于对行锁进行对比,可以将行锁以哈希表的形式进行存储。步骤104中,根据每个操作的唯一标识符对每个操作构造行锁的具体实现方式可以为:在每个执行线程中创建一个行锁哈希表,将每个执行线程中当前事务的每个操作放入行锁哈希表中,其中,每个操作的唯一标识符作为行锁哈希表的key。在上述实例的实施场景中,行锁哈希表的key为操作的唯一标识符ID。EXEC1的行锁哈希表中保存两组以(key,value)为结构的值,其中key为哈希表的key值,分别为(ID=1,VALUE=操作1)和(ID=2,VALUE=操作2);EXEC2的行锁哈希表中保存一组(key,value)值,(ID=1,VALUE=操作3);EXEC3的行锁哈希表中保存一组(key,value)值,(ID=2,VALUE=操作4)。通过不同线程中行锁哈希表key值的比较,可以使用哈希表的特性快速简便的对是否存在行锁冲突进行判断。
进一步的,如图3所示,当执行线程使用行锁哈希表对行锁进行存储时,步骤105中可使用如下具体步骤判断每个执行线程中的当前事务是否与提交顺序在其之前的事务存在行锁冲突:
步骤201:获取第一执行线程的行锁哈希表为第一行锁哈希表。
步骤202:获取第二执行线程的行锁哈希表为第二行锁哈希表,第二执行线程的当前事务提交顺序在第一线程之前。
在上述实例中,根据事务提交顺序,需要比较三组行锁哈希表:EXEC1的行锁哈希表为第一行锁哈希表,EXEC2中的行锁哈希表为第二行锁哈希表;EXEC1的行锁哈希表为第一行锁哈希表,EXEC3中的行锁哈希表为第二行锁哈希表;EXEC2的行锁哈希表为第一行锁哈希表,EXEC2中的行锁哈希表为第二行锁哈希表。
步骤203:判断第一行锁哈希表和第二行锁哈希表中是否存在相同的key。
步骤204:若是,表示第一线程的当前事务与第二线程的当前事务存在行锁冲突。
步骤205:若否,表示第一线程的当前事务与第二线程的当前事务不存在行锁冲突。
在上述场景中,EXEC1的行锁哈希表和EXEC2的行锁哈希表中存在相同的key:ID=1,存在行锁冲突;EXEC1的行锁哈希表和EXEC3的行锁哈希表中存在相同的key,存在行锁冲突:ID=2;EXEC2的行锁哈希表和EXEC3的行锁哈希表中不存在相同的key,不存在行锁冲突。
步骤206:对每一组第一线程和第二线程逐一比较,判断每两个线程间是否存在行锁。
在进行行锁冲突判断时,需要使用如上述步骤202-步骤205中实例的对比方式对所有执行线程中的行锁哈希表逐一进行两两对比,以保证查找到所有的行锁冲突。
在进行同步时,需要按事务提交顺序执行,若当前事务和多个事务存在行锁冲突,则必须等待事务提交顺序最靠后的冲突事务执行完成后才能执行。因此,只需要查找所有存在行锁冲突的事务中提交顺序在当前事务之前,且提交顺序与当前事务最接近的事务,将当前事务放入查找到的事务所在的执行线程的唤醒队列中。在上述实例中,如图4所示的时序图,若TRX2中存在操作5:(UPDATE T SET C1=15WHERE ID=2;),则TRX3同时与TRX1和TRX2存在行锁冲突,按照事务提交顺序,在保证数据正确的基础上,TRX3需等待TRX1和TRX2执行完成后开始执行,TRX2需等待TRX1执行完成后开始执行。此时,TRX2即为所有和TRX3存在行锁冲突的事务中提交顺序在TRX3之前且提交顺序与当前事务最接近的事务,因此只需将TRX3放入TRX2所在执行线程EXEC2的唤醒队列中,在TRX2执行完成后唤醒TRX3,即可使事务执行顺序正确,并保证同步数据正确。仅将需等待的事务放入提交顺序与当前事务最接近的事务相应的唤醒队列中,在存在多组行锁冲突的情况下,不需要进行多次不必要的唤醒,节省了资源,减少执行线程调度的复杂度。
当执行线程的当前事务执行完成后,行锁对应的资源即可进行下一次的变化,此时,需要将执行线程的行锁哈希表中的行锁全部释放,即清空行锁哈希表中保存的所有(key,value),在下一个当前事务分配至执行线程后重新建立新的行锁哈希表。
为了便于管理需同步的事务,可以将需同步的事务使用执行事务列表进行组织。获取需同步的事务后,将需同步的事务按提交顺序放入执行事务列表中,以便于对需同步的事务按照事务提交顺序进行查找和分配。上述实例中,执行事务列表为:TRX1->TRX2->TRX3。步骤103中按照提交顺序将事务逐一分配至不同的空闲的执行线程,即可按照执行事务列表中保存的事务顺序,由表头开始向后逐个取出事务,依次分配至空闲的执行线程中。具体的,在数据库的使用场景中,日志中的数据库事务通过日志序号(Log sequencenumber,简写为:LSN)进行管理,LSN根据事务提交顺序由小到大进行编制。
进一步的,使用执行事务列表组织需同步的事务后,可以通过执行事务列表便捷的查找存在行锁冲突的事务。判断每个执行线程中的当前事务是否与提交顺序在其之前的事务存在行锁冲突时,在执行事务列表中查找当前事务所在位置,由当前事务所在位置开始,依次逆序获取需执行的事务判断是否存在行锁冲突,找到第一个存在行锁冲突的需执行事务时停止判断。在上述实例中,存在操作5的情况下,查找与TRX3存在行锁冲突的事务时,由TRX3开始,逆序获取需执行的事务,首先获取到的事务为TRX2,TRX3与TRX2存在行锁冲突,即可停止判断。使用执行事务列表逆序查找行锁冲突,可以方便快速的找到存在行锁冲突的最后一个事务,减少查找和比较的成本。
为了将需同步的事务接受和分配过程与事务执行过程分离,并方便对执行事务列表进行管理,还可以创建单独的事务接收线程。事务接收线程对获取到的需同步的事务进行接收,将需同步的事务存放至执行事务列表中,并在执行线程空闲时将执行事务列表中的需执行的事务依次分配至执行线程中。通过事务接受线程对事务的接受和分配过程进行管理,可以使事务的接受和分配过程与事务的执行过程并行进行,进一步提高数据同步过程的执行效率。
在进行数据同步时,由于只有含有COMMIT操作的事务,即提交操作对应的事务代表数据变化生效,因此只需执行含有COMMIT操作的事务。因此,事务接收线程对获取到的需同步的事务进行接收后,根据需同步的事务ID对需同步的事务进行分类,仅将提交操作对应的事务存放至执行事务列表中。在上述实例中,TRX1、TRX2和TRX3都含有COMMIT操作,都会产生数据变化,因此都需进行执行。具体的,在数据库的使用场景中,事务接受线程可以根据操作的事务ID判断操作类型,操作的事务ID代表操作的类型,因此可以用于确定事务中是否含有COMMIT操作。将事务存放至执行事务列表前先进行分类,可以对需同步的事务进行预先筛选,去掉不需要处理的事务,减少需处理的事务数量,避免对不需执行的事务进行处理,进一步提高数据同步的执行效率。
经过本实施例中提供的步骤后,通过创建多个执行线程,并通过行锁和唤醒队列配合使用,可以在保证数据正确的基础上对多个同步事务并行执行,提高数据同步效率。进一步的,还通过设置行锁哈希表、执行事务列表和事务接受线程,进一步优化冲突判断和事务分配的过程,进一步提高数据同步的效率。
实施例2:
基于实施例1提供的基于并行执行的数据同步的方法,在不同的具体应用场景中,还可以根据使用需求或实际场景的不同进行补充和调整。下述技术方案,在不存在冲突的情况下,可以选择一个或多个技术方案,与实施例1中的技术方案进行组合使用。
为了进一步提高执行线程并发执行的效率,在本实施例的具体实施场景中,步骤103中按照提交顺序将事务逐一分配至不同的空闲的执行线程时,还可以根据事务和线程的特征进行进一步的优化分配:预先判断有冲突的事务,将有冲突的事务组成队列,对不同队列中的事务预估事务的执行时间,根据时间选取合适的执行线程进行分配。在具体实施场景中,如图5所示,步骤101-步骤107可以变化为以下步骤:
步骤301:获取需同步的事务,每个事务中包含至少一个操作。
步骤302:创建至少两个执行线程,每个执行线程中包括一个唤醒队列。
步骤303:获取每个需同步的事务中的每个操作,根据每个操作的唯一标识符对每个操作构造行锁。
步骤304:判断每个执行线程中的当前事务是否与提交顺序在其之前的事务存在行锁冲突,将存在冲突的事务按照提交顺序放入同一个分配队列中,任两个分配队列中的事务之间都不存在事务冲突。
步骤305:预估每个分配队列中第一个事务的执行时间。
步骤306:当执行线程出现空闲时,优先将执行时间较长的事务分配至执行线程中,并将其所在分配队列的下一个事务放入线程的唤醒队列。
步骤307:执行线程按照事务提交顺序并行执行不存在行锁冲突的当前事务。
步骤308:每个执行线程执行完当前事务后,接受下一个被分配的事务,并唤醒执行线程的唤醒队列中的事务。
将事务分配至执行线程之前先进行行锁冲突判断,可以并发进行执行线程中的操作执行和行锁判断,节省行锁判断的时间;同时,预估事务的执行时间,将执行时间较长的事务分配至先出现空闲的线程,可以使各线程的执行时间较为均衡,充分利用线程资源。
使用行锁哈希表的情况下,为了便于对行锁哈希表进行释放,可以将每个行锁哈希表放在一块连续的内存中,进行行锁哈希表释放时,直接将整块内存进行释放,操作更简便,执行效率更高。进一步的,当事务执行完毕时,除了释放行锁哈希表的资源外,还需要释放事务所占用的其它资源。
在进行数据同步时,可能存在源端数据和目的端数据的数据格式不同,或仅需同步部分数据等情况。为了便于对格式不同的数据进行同步,在使用事务接收线程对需同步的事务进行管理时,可以先使用事务接收线程对事务中的操作进行清洗,将源端的操作转换为能提供相同数据变化的目的端的操作,或去掉不需要进行数据同步的部分。
实施例1和实施例2中所提供的数据同步的方法结合使用,可以充分利用***资源,进一步提升数据同步的效率。
实施例3:
在上述实施例1至实施例2提供的基于并行执行的数据同步的方法的基础上,本发明还提供了一种可用于实现上述方法的基于并行执行的数据同步的装置,如图6所示,是本发明实施例的装置架构示意图。本实施例的基于并行执行的数据同步的装置包括一个或多个处理器21以及存储器22。其中,图6中以一个处理器21为例。
处理器21和存储器22可以通过总线或者其他方式连接,图6中以通过总线连接为例。
存储器22作为一种基于并行执行的数据同步方法非易失性计算机可读存储介质,可用于存储非易失性软件程序、非易失性计算机可执行程序以及模块,如实施例1至实施例2中的基于并行执行的数据同步方法。处理器21通过运行存储在存储器22中的非易失性软件程序、指令以及模块,从而执行基于并行执行的数据同步的装置的各种功能应用以及数据处理,即实现实施例1至实施例2的基于并行执行的数据同步的方法。
存储器22可以包括高速随机存取存储器,还可以包括非易失性存储器,例如至少一个磁盘存储器件、闪存器件、或其他非易失性固态存储器件。在一些实施例中,存储器22可选包括相对于处理器21远程设置的存储器,这些远程存储器可以通过网络连接至处理器21。上述网络的实例包括但不限于互联网、企业内部网、局域网、移动通信网及其组合。
程序指令/模块存储在存储器22中,当被一个或者多个处理器21执行时,执行上述实施例1至实施例2中的基于并行执行的数据同步的方法,例如,执行以上描述的图1-图5所示的各个步骤。
本领域普通技术人员可以理解实施例的各种方法中的全部或部分步骤是可以通过程序来指令相关的硬件来完成,该程序可以存储于一计算机可读存储介质中,存储介质可以包括:只读存储器(ROM,Read Only Memory)、随机存取存储器(RAM,Random AccessMemory)、磁盘或光盘等。
以上所述仅为本发明的较佳实施例而已,并不用以限制本发明,凡在本发明的精神和原则之内所作的任何修改、等同替换和改进等,均应包含在本发明的保护范围之内。