一种溢出页异常的数据库修复方法、装置及存储介质与流程

文档序号:17160144发布日期:2019-03-20 00:34阅读:182来源:国知局
一种溢出页异常的数据库修复方法、装置及存储介质与流程

本发明涉及数据库技术领域,特别是一种溢出页异常的数据库修复方法、装置及存储介质。



背景技术:

sqlite,是一款轻型的数据库,是遵守acid的关系型数据库管理系统,它包含在一个相对小的c库中。它是d.richardhipp建立的公有领域项目。它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百k的内存就够了。它能够支持windows/linux/unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如tcl、c#、php、java等,还有odbc接口,同样比起mysql、postgresql这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。因此,sqlite数据库的使用越来越广泛,特别是在便携式设备中。

但是,由于便携式设备的稳定性相对较差,比如在进行数据写入时,突然断电,导致sqlite的数据异常,目前在sqlite数据库异常修复方面,目前国内外研究比较少,目前市场上的sqlite通用解析产品中会附带一些数据库修复工具,但是局限性很大,修复完的数据库中的数据一般会有所缺失,即数据库修复过程不完整,经常出现修复完的数据库记录差异很大的情况,从而影响了数据库的准确性和全面性。因此,如何准确的进行sqlite的数据异常的修复是现有技术中的一个技术难题。



技术实现要素:

本发明针对上述现有技术中的缺陷,提出了如下技术方案。

一种溢出页异常的数据库修复方法,该方法包括:

获取步骤,获取数据库溢出页单元的一个异常数据节点的异常信息;

修复步骤,根据修复模式和所述异常信息对所述数据库进行修复。

更进一步地,所述异常信息包括数据库溢出页单元的链表的第一个节点的页号start_pgno、单元起始地址start_offset、下一单元起始地址next_offset和数据库溢出页出现异常的节点的页号abnormal_pgno、节点序号abnormal_index,所述异常信息表示为:

[start_pgno,start_offset,next_offset,abnormal_pgno,abnormal_index],

其中,若第一个节点是所在sqlite页面的最后一个单元时,next_offset等于usable_size,usable_size为sqlite页面的可用大小。

更进一步地,所述数据库为sqlite数据库,所述数据库包括多个sqlite页面,所述sqlite页面采用b+tree进行管理,其中,在b+tree中存放数据的sqlite页面称为叶子页。

更进一步地,当修复模式为简单修复时,将所述异常数据节点所在数据记录全部修改为空。

更进一步地,当所述修复模式为标准修复时,对所述数据库进行修复包括:

截断异常数据节点,将截断前的最后一个数据节点的溢出页号标记为0,表示溢出页链表结束;对所述异常数据节点所在数据记录的头部数据进行修改;计算所述数据记录的头部数据所占空间是否缩小,若有缩小,将所述数据记录的头部数据后移,并相应修改所述数据记录对应的页面头部中的单元索引。

更进一步地,将截断前的最后一个数据节点记为[pre_pgno,pre_index],其中pre_pgno是异常数据节点之前的前一个数据节点的页号,pre_index=abnormal_index-1;将截断前的最后一个数据节点的溢出页号标记为0是指将pre_pgno页前4个字节的溢出页号填充为0。

更进一步地,对所述异常数据节点所在数据记录的头部数据进行修改的操作为:

读取数据记录的原始头部数据,所述原始头部数据包括数据记录总长度tl1、头部总长度hl1以及字段索引indexi,其中,0≤i<n,n为所述数据记录的字段数,为整数;

计算修改前后的数据域大小,其中数据库的页面可用大小记为usable_size,截断后数据总长度记为dl2,原始的数据总长度为dl1,则:

dl1=tl1-hl1;

dl2=pre_index*(usable_size-4)+(next_offset-start_offset-4)-hl1;

修改截断后的数据记录的头部数据,所述头部数据包括记录总长度tl2、头部总长度hl2以及字段索引new_indexi;

假定从字段m处被截断,f1(indexi)为字段i所占的长度,f2(indexi)为字段i索引本身所占的长度,则:

f1(indexi)=0,(i=m+1..n-1);

更进一步地,计算修改后的数据记录头部数据需要往后移动的字节数cnt,其中,

cnt=f2(tl1)+f1(hl1)-f2(tl2)+f1(hl2),

如果cnt为0,则数据记录头部数据无需移动,单元索引无需修改,如果cnt不为0,将修改后的数据记录头部数据往后移动cnt字节,以保持头部域和数据域的紧密衔接;并根据修改后的数据记录头部数据的偏移位置,修改数据记录对应的页面头部的单元索引,即单元索引值增加cnt字节。

本发明还提出了一种溢出页异常的数据库修复装置,该装置包括:

获取单元,用于获取数据库溢出页单元的一个异常数据节点的异常信息;

修复单元,用于根据修复模式和所述异常信息对所述数据库进行修复。

更进一步地,所述异常信息包括数据库溢出页单元的链表的第一个节点的页号start_pgno、单元起始地址start_offset、下一单元起始地址next_offset和数据库溢出页出现异常的节点的页号abnormal_pgno、节点序号abnormal_index,所述异常信息表示为:

[start_pgno,start_offset,next_offset,abnormal_pgno,abnormal_index],

其中,若第一个节点是所在sqlite页面的最后一个单元时,next_offset等于usable_size,usable_size为sqlite页面的可用大小。

更进一步地,所述数据库为sqlite数据库,所述数据库包括多个sqlite页面,所述sqlite页面采用b+tree进行管理,其中,在b+tree中存放数据的sqlite页面称为叶子页。

更进一步地,当修复模式为简单修复时,将所述异常数据节点所在数据记录全部修改为空。

更进一步地,当所述修复模式为标准修复时,对所述数据库进行修复包括:

截断异常数据节点,将截断前的最后一个数据节点的溢出页号标记为0,表示溢出页链表结束;对所述异常数据节点所在数据记录的头部数据进行修改;计算所述数据记录的头部数据所占空间是否缩小,若有缩小,将所述数据记录的头部数据后移,并相应修改所述数据记录对应的页面头部中的单元索引。

更进一步地,将截断前的最后一个数据节点记为[pre_pgno,pre_index],其中pre_pgno是异常数据节点之前的前一个数据节点的页号,pre_index=abnormal_index-1;将截断前的最后一个数据节点的溢出页号标记为0是指将pre_pgno页前4个字节的溢出页号填充为0。

更进一步地,对所述异常数据节点所在数据记录的头部数据进行修改的操作为:

读取数据记录的原始头部数据,所述原始头部数据包括数据记录总长度tli、头部总长度hl1以及字段索引indexi,其中,0≤i<n,n为所述数据记录的字段数,为整数;

计算修改前后的数据域大小,其中数据库的页面可用大小记为usable_size,截断后数据总长度记为dl2,原始的数据总长度为dl1,则:

dl1=tl1-hl1;

dl2=pre_index*(usable_size-4)+(next_offset-start_offset-4)-hl1;

修改截断后的数据记录的头部数据,所述头部数据包括记录总长度tl2、头部总长度hl2以及字段索引new_indexi;

假定从字段m处被截断,f1(indexi)为字段i所占的长度,f2(indexi)为字段i索引本身所占的长度,则:

f1(indexi)=0,(i=m+1..n-1);

更进一步地,计算修改后的数据记录头部数据需要往后移动的字节数cnt,其中,

cnt=f2(tl1)+f1(hl1)-f2(tl2)+f1(hl2),

如果cnt为0,则数据记录头部数据无需移动,单元索引无需修改,如果cnt不为0,将修改后的数据记录头部数据往后移动cnt字节,以保持头部域和数据域的紧密衔接;并根据修改后的数据记录头部数据的偏移位置,修改数据记录对应的页面头部的单元索引,即单元索引值增加cnt字节。

本发明还提出了一种计算机可读存储介质,所述存储介质上存储有计算机程序代码,当所述计算机程序代码被计算机执行时执行上述之任一的方法。

本发明的技术效果为:本发明通过获取数据库溢出页的一个异常数据节点的异常信息,根据修复模式和所述异常信息对所述数据库进行修复,在简单模式下进行修复可以实现异常数据的绕过修复,在标准修复模式下可自动修复异常点前的溢出页数据碎片,即将一条数据记录中异常节点前的数据修复出来,尽量多的恢复可用的数据,尽量提高了修复后数据的完整性,提高了用户体验。

附图说明

通过阅读参照以下附图所作的对非限制性实施例所作的详细描述,本申请的其它特征、目的和优点将会变得更明显。

图1是根据本发明的实施例的一种溢出页异常的数据库修复方法的流程图。

图2是根据本发明的实施例的sqlite数据记录的结构图。

图3是根据本发明的实施例的数据库溢出页的结构图。

图4是根据本发明的实施例的一种溢出页异常的数据库修复装置的结构图。

具体实施方式

下面结合附图和实施例对本申请作进一步的详细说明。可以理解的是,此处所描述的具体实施例仅仅用于解释相关发明,而非对该发明的限定。另外还需要说明的是,为了便于描述,附图中仅示出了与有关发明相关的部分。

需要说明的是,在不冲突的情况下,本申请中的实施例及实施例中的特征可以相互组合。下面将参考附图并结合实施例来详细说明本申请。

图1示出了本发明的一种溢出页异常的数据库修复方法,该方法包括:

获取步骤s101,获取数据库溢出页单元的一个异常数据节点的异常信息;

修复步骤s102,根据修复模式和所述异常信息对所述数据库进行修复。

在本方法的一个实施例中,本发明采用的数据库为sqlite数据库,所述数据库包括多个sqlite页面,所述sqlite页面采用b+tree进行管理,其中,在b+tree中存放数据的sqlite页面称为叶子页。并且该方法不局限于某一个数据库,对所有sqlite数据库的溢出页异常修复分析都适用,也适用于其他类似sqlite的数据库的溢出页异常修复。

sqlite数据库文件是由一系列的数据表组成的,而每张数据表是由一系列的页面组成的,并且这些页面组织由一棵b+tree来管理,每个b+tree节点对应一个sqlite页面,页面的大小page_size是2的n次方,常见的有1024、2048、4096字节等,page_size扣掉页面尾部预留部分就是页面的可用大小usable_size(一般情况下page_size和usable_size相等)。其中存放数据的叶子节点称为叶子页,而存放索引的内部节点称为内部页。

sqlite数据记录的结构如图2所示,其中记录总长度(记为tl)和rowid(rowid是唯一标志记录物理位置的一个id)是变长整数,占用的空间大小为1-9字节,头部索引长度是n个索引(记为index)和头部索引长度本身占用的空间大小,而n个数据(记为data)域与n个索引域一一对应,indexi记录了datai占用的空间大小。

b+tree叶子页内部以单元(cell)为单位来组织数据,一个单元包含一个(或部分,当使用溢出页时)payload(也称为b+tree记录数据)。单元(cell)具有可变的大小,而页的大小是固定的,这就有可能一个单元比一个完整的页还大,这样的单元就会溢出到由溢出页组成的链表上,如图3所示。在图3中,b+tree页的最后一个单元超大,需要使用溢出页。此时,单元的最后4个字节为溢出页链表中第1个溢出页的页号。对于每个溢出页,其头4个字节为下一溢出页的页号,该值为0时表示此页为溢出页链表的表尾页。除最后一个溢出页外,每个溢出页全部填充数据(除了最开始的4个字节),而且最后一个溢出页可能数据很少,甚至只有一个字节的数据,但一个溢出页不会存储来自两个单元的数据。

为了进行溢出页异常的修复,需要获取异常信息,所述异常信息包括数据库溢出页单元的链表的第一个节点的页号start_pgno、单元起始地址start_offset、下一单元起始地址next_offset和数据库溢出页出现异常的节点的页号abnormal_pgno、节点序号abnormal_index,所述异常信息表示为:

[start_pgno,start_offset,next_offset,abnormal_pgno,abnormal_index],其中,若第一个节点是所在sqlite页面的最后一个单元时,next_offset等于usable_size,usable_size为sqlite页面的可用大小。一种获取异常信息方法是通过对b+tree以及图3所示的链表进行遍历获取,当然,本领域技术人员也可以通过其他的方法获取。

在本方法的一个实施例中,当修复模式为简单修复时,将所述异常数据节点所在数据记录全部修改为空,这种修复模式也称为绕过模式,即将该数据记录全部初始化为空,即该条数据记录可以访问,但没有任何数据,这样,可以防止在数据库操作(如查询)时报错,导致中断数据的查询,这是本发明的一个发明点。

本发明更重要的一个发明点是对数据记录中的可用数据尽量的恢复,即尽可能多的恢复可用的数据,提高恢复后数据的完整度,以提高用户的体验,当所述修复模式为标准修复时,标准修复模式也可以称为‘微创式’修复,即对数据节点的内部进行修复,对所述数据库进行修复包括:截断异常数据节点,将截断前的最后一个数据节点的溢出页号标记为0,表示溢出页链表结束;对所述异常数据节点所在数据记录的头部数据进行修改;计算所述数据记录的头部数据所占空间是否缩小,若有缩小,将所述数据记录的头部数据后移,并相应修改所述数据记录对应的页面头部中的单元索引。

在一个实施例中,将截断前的最后一个数据节点记为[pre_pgno,pre_index],其中pre_pgno是异常数据节点之前的前一个数据节点的页号,pre_index=abnormal_index-1;将截断前的最后一个数据节点的溢出页号标记为0是指将pre_pgno页前4个字节的溢出页号填充为0。

在一个实施例中,对所述异常数据节点所在数据记录的头部数据进行修改的操作为:读取数据记录的原始头部数据,所述原始头部数据包括数据记录总长度tl1、头部总长度hl1以及字段索引indexi,其中,0≤i<n,n为所述数据记录的字段数,为整数;

计算修改前后的数据域大小,其中数据库的页面可用大小记为usable_size,其中数据库的页面可用大小记为usable_size,大部分情况下usable_size和页面大小page_size相等,截断后数据总长度记为dl2,原始的数据总长度为dl1,则:

dl1=tl1-hl1;

dl2=pre_index*(usable_size-4)+(next_offset-start_offset-4)-hl1;

修改截断后的数据记录的头部数据,所述头部数据包括记录总长度tl2、头部总长度hl2以及字段索引new_indexi;

假定从字段m处被截断,f1(indexi)为字段i所占的长度,f2(indexi)为字段i索引本身所占的长度,则:

f1(indexi)=0,(i=m+1..n-1);

在一个实施例中,计算修改后的数据记录头部数据需要往后移动的字节数cnt,其中,

cnt=f2(tl1)+f1(hl1)-f2(tl2)+f1(hl2),

如果cnt为0,则数据记录头部数据无需移动,单元索引无需修改,如果cnt不为0,将修改后的数据记录头部数据往后移动cnt字节,以保持头部域和数据域的紧密衔接;并根据修改后的数据记录头部数据的偏移位置,修改数据记录对应的页面头部的单元索引,即单元索引值增加cnt字节。

进一步参考图4,作为对上述图1所示方法的实现,本申请提供了一种数据库溢出页异常的检测装置的一个实施例,该装置实施例与图1所示的方法实施例相对应,该装置具体可以包含于各种电子设备中。

图4示出了本发明的一种溢出页异常的数据库修复装置,该装置包括:

获取单元401,用于获取数据库溢出页单元的一个异常数据节点的异常信息;

修复单元402,用于根据修复模式和所述异常信息对所述数据库进行修复。

在本装置的一个实施例中,本发明采用的数据库为sqlite数据库,所述数据库包括多个sqlite页面,所述sqlite页面采用b+tree进行管理,其中,在b+tree中存放数据的sqlite页面称为叶子页。并且该装置不局限于某一个数据库,对所有sqlite数据库的溢出页异常修复分析都适用,也适用于其他类似sqlite的数据库的溢出页异常修复。

sqlite数据库文件是由一系列的数据表组成的,而每张数据表是由一系列的页面组成的,并且这些页面组织由一棵b+tree来管理,每个b+tree节点对应一个sqlite页面,页面的大小page_size是2的n次方,常见的有1024、2048、4096字节等,page_size扣掉页面尾部预留部分就是页面的可用大小usable_size(一般情况下page_size和usable_size相等)。其中存放数据的叶子节点称为叶子页,而存放索引的内部节点称为内部页。

sqlite数据记录的结构如图2所示,其中记录总长度(记为tl)和rowid(rowid是唯一标志记录物理位置的一个id)是变长整数,占用的空间大小为1-9字节,头部索引长度是n个索引(记为index)和头部索引长度本身占用的空间大小,而n个数据(记为data)域与n个索引域一一对应,indexi记录了datai占用的空间大小。

b+tree叶子页内部以单元(cell)为单位来组织数据,一个单元包含一个(或部分,当使用溢出页时)payload(也称为b+tree记录数据)。单元(cell)具有可变的大小,而页的大小是固定的,这就有可能一个单元比一个完整的页还大,这样的单元就会溢出到由溢出页组成的链表上,如图3所示。在图3中,b+tree页的最后一个单元超大,需要使用溢出页。此时,单元的最后4个字节为溢出页链表中第1个溢出页的页号。对于每个溢出页,其头4个字节为下一溢出页的页号,该值为0时表示此页为溢出页链表的表尾页。除最后一个溢出页外,每个溢出页全部填充数据(除了最开始的4个字节),而且最后一个溢出页可能数据很少,甚至只有一个字节的数据,但一个溢出页不会存储来自两个单元的数据。

为了进行溢出页异常的修复,需要获取异常信息,所述异常信息包括数据库溢出页单元的链表的第一个节点的页号start_pgno、单元起始地址start_offset、下一单元起始地址next_offset和数据库溢出页出现异常的节点的页号abnormal_pgno、节点序号abnormal_index,所述异常信息表示为:

[start_pgno,start_offset,next_offset,abnormal_pgno,abnormal_index],其中,若第一个节点是所在sqlite页面的最后一个单元时,next_offset等于usable_size,usable_size为sqlite页面的可用大小。一种获取异常信息装置是通过对b+tree以及图3所示的链表进行遍历获取,当然,本领域技术人员也可以通过其他的装置获取。

在本装置的一个实施例中,当修复模式为简单修复时,将所述异常数据节点所在数据记录全部修改为空,这种修复模式也称为绕过模式,即将该数据记录全部初始化为空,即该条数据记录可以访问,但没有任何数据,这样,可以防止在数据库操作(如查询)时报错,导致中断数据的查询,这是本发明的一个发明点。

本发明更重要的一个发明点是对数据记录中的可用数据尽量的恢复,即尽可能多的恢复可用的数据,提高恢复后数据的完整度,以提高用户的体验,当所述修复模式为标准修复时,标准修复模式也可以称为‘微创式’修复,即对数据节点的内部进行修复,对所述数据库进行修复包括:截断异常数据节点,将截断前的最后一个数据节点的溢出页号标记为0,表示溢出页链表结束;对所述异常数据节点所在数据记录的头部数据进行修改;计算所述数据记录的头部数据所占空间是否缩小,若有缩小,将所述数据记录的头部数据后移,并相应修改所述数据记录对应的页面头部中的单元索引。

在一个实施例中,将截断前的最后一个数据节点记为[pre_pgno,pre_index],其中pre_pgno是异常数据节点之前的前一个数据节点的页号,pre_index=abnormal_index-1;将截断前的最后一个数据节点的溢出页号标记为0是指将pre_pgno页前4个字节的溢出页号填充为0。

在一个实施例中,对所述异常数据节点所在数据记录的头部数据进行修改的操作为:读取数据记录的原始头部数据,所述原始头部数据包括数据记录总长度tl1、头部总长度hl1以及字段索引indexi,其中,0≤i<n,n为所述数据记录的字段数,为整数;

计算修改前后的数据域大小,其中数据库的页面可用大小记为usable_size,其中数据库的页面可用大小记为usable_size,大部分情况下usable_size和页面大小page_size相等,截断后数据总长度记为dl2,原始的数据总长度为dl1,则:

dl1=tl1-hl1;

dl2=pre_index*(usable_size-4)+(next_offset-start_offset-4)-hl1;

修改截断后的数据记录的头部数据,所述头部数据包括记录总长度tl2、头部总长度hl2以及字段索引new_indexi;

假定从字段m处被截断,f1(indexi)为字段i所占的长度,f2(indexi)为字段i索引本身所占的长度,则:

f1(indexi)=0,(i=m+1..n-1);

在一个实施例中,计算修改后的数据记录头部数据需要往后移动的字节数cnt,其中,

cnt=f2(tl1)+f1(hl1)-f2(tl2)+f1(hl2),

如果cnt为0,则数据记录头部数据无需移动,单元索引无需修改,如果cnt不为0,将修改后的数据记录头部数据往后移动cnt字节,以保持头部域和数据域的紧密衔接;并根据修改后的数据记录头部数据的偏移位置,修改数据记录对应的页面头部的单元索引,即单元索引值增加cnt字节。

本发明的技术效果为,在简单模式下进行修复可以实现异常数据的绕过修复,在标准修复模式下可自动修复异常点前的溢出页数据碎片,即将一条数据记录中异常节点前的数据修复出来,尽量多的恢复可用的数据,尽量提高了修复后数据的完整性,提高了用户体验。

为了描述的方便,描述以上装置时以功能分为各种单元分别描述。当然,在实施本申请时可以把各单元的功能在同一个或多个软件和/或硬件中实现。

通过以上的实施方式的描述可知,本领域的技术人员可以清楚地了解到本申请可借助软件加必需的通用硬件平台的方式来实现。基于这样的理解,本申请的技术方案本质上或者说对现有技术做出贡献的部分可以以软件产品的形式体现出来,该计算机软件产品可以存储在存储介质中,如rom/ram、磁碟、光盘等,包括若干指令用以使得一台计算机设备(可以是个人计算机,服务器,或者网络设备等)执行本申请各个实施例或者实施例的某些部分所述的方法。

最后所应说明的是:以上实施例仅以说明而非限制本发明的技术方案,尽管参照上述实施例对本发明进行了详细说明,本领域的普通技术人员应当理解:依然可以对本发明进行修改或者等同替换,而不脱离本发明的精神和范围的任何修改或局部替换,其均应涵盖在本发明的权利要求范围当中。

当前第1页1 2 
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1