说明性实施例的详细描述
这里所描述的阴影分页提供了一种用于例如在数据库中对存储进行访问和控制,同时减轻诸如电源故障、盘崩溃和/或处理器故障等意外故障的有害影响的技术。该技术能够相对简单地实现并使用很少的软件代码,这样使其尤其适合于具有有限存储器的电子设备,如手持式设备和/或移动数据库产品(如SQL-CE)。数据库产品的重要特点包括实现原子事务和耐久事务的能力。原子事务是从不部分提交的事务-即,该事务或者完全完成,或者完全不完成。耐久事务是其中数据库状态的变化是永久性的事务,在这一意义上,即使在事务完成之后立即出现***崩溃,所得到的数据库事务后状态也能够继续存在。阴影分页提供了一种用于实现原子事务和耐久事务的机制。
图1是能够实现阴影分页的示例数据库组织的说明。在示例实施例中,在具有图1所示结构的数据库被修改时可以利用阴影分页,并且这里本发明是在这类数据库的背景下描述的。然而,可以理解,这里描述的阴影分页不局限于数据库应用,而是可以在各种牵涉存储器利用的其它情况中使用。
图1描述的页是数据库文件的页,包括数据库头页12、目录页13、至少一个映射表页16以及至少一个用户数据页18。图1描述的数据库文件的页包括内存或存储器的页。这类内存或存储器不局限于特定类型或分类的存储器,而可以包括半导体存储器、磁存储器(如盘)、光存储器、机械存储器、随机存储存储器(RAM)、易失存储器以及非易失存储器、或其它任何类型能够储存数据的设备。在以下描述中,术语“存储器页”不局限于传统“存储器”设备(如RAM或ROM),而应该理解为包括所有类型的数据存储设备。
图1所示的页结构能够使用相对较小存储来实现。例如,如果页的尺寸是4096字节,最大数据库文件尺寸是232字节(4千兆字节),作为结果的文件中页的最大数量是220页。因此,映射表页16储存最多220个条目(每页一个条目)。如果文件中页的物理位置用字节偏移来标识,则用32位来代表每页。可以通过将页的偏移储存为页尺寸的增量来减少到每页20位。因此,映射表页16采用(220)×20位的空间,结果是2,621,440字节。在一示例实施例中,映射表页16作为一组页储存在数据库文件中。如果映射表页是4096字节,并使用20位来储存一页的物理位置,则每一映射表页最多可以引用1638页。这样,可以用最多641个映射表页来引用最多220页。典型的数据库文件远小于4千兆字节,这样可使用更少的映射表页。如上所述,使用目录页14来跟踪数据库文件中映射表页16的物理位置(如,当映射表页16被修改并转储到新的位置)。依照以上示例,目录页14具有一个20位的条目,它跟踪着数据库文件中每一映射表页的物理位置。头页12、目录页14和映射表页16与用户数据页18的数量相比消耗的盘空间(存储)相对较小。例如,1,047,933(220减643)个用户数据页18可以由643个“维护页”来维护。(在本发明中,所谓“维护页”是储存数据库***使用的管理数据的页,而不是用户数据。在图1的示例中,头页12、目录页14和映射表页16是“维护页”。)这样一来,维护页仅消耗总数据库文件空间的0.06%。应当注意,以上描述的4096字节页的值和20位数据类型是示例性的。可以想像,以上描述的文件结构的实现可以使用数据压缩来将20位数据类型减少到更小尺寸的数据类型。
维护页维护图1描述的所有页的位置。数据库头页12维护目录页14的位置。在一示例实施例中,目录页14的物理地址储存在数据库头页12的第一扇区中,并且数据库头页12储存在数据库文件的起点。如下文所述,这能够确保事务是原子型事务。目录页14维护映射表页16的位置。映射表页16维护用户数据页18的位置。用户数据页18可包含数据库数据,如记录和/或索引键等。如下文更加详细描述的,图1所示的存储器页结构用来在阴影分页过程中跟踪并维护存储器页。
图1所示的结构使页可以由“逻辑”标识符来标识。典型的数据库产品使用代表文件中页的物理地址的页标识符。例如,典型数据库产品可通过从数据库文件的逻辑起点引用的偏移值来标识一个给定页。由于页可引用其它页,这些标识符可能经常出现在贯穿数据库的各种地方。这一标识页的方法令将页从文件的一个位置移到另一各位置变得很困难,因为只要移动一个或多个页,就必需更新所有引用所移动的页的页标识符来反映新的位置(如新页偏移值)。然而,当使用图1所示的结构时,可以在目录页和指向给定页的映射表页内的元素的基础上标识一个给定页。例如,一个给定页可以由到目录页的偏移和到映射表页的偏移来标识;然后给定页通过以下方式来定位:(1)根据在目录页的指定偏移中找到的指针来定位特定映射表页,以及(2)通过定位的映射表页中找到的指针来找到给定页。这样,通过简单地更新目录页和映射表中的适当条目,页可以移动到数据库文件的另一个位置,而不需要改变其逻辑标识符。这一技术与虚拟存储器***中的地址变换表的使用类似。
如下文更详细的讨论,逻辑页标识符的使用方便了阴影分页的实现,这样,在本发明的一个示例实施例中,数据库文件中的页由逻辑页标识符(ID)来标识。在数据库中,页通过逻辑ID来访问并跟踪。页的位置也通过使用逻辑页ID来维护。图2是表示映射到用户数据页18的物理位置15的逻辑ID 13的映射表页16的一部分。(可以理解,数据库文件中页的“物理”位置指的是这样一个事实,数据库文件(或任意文件)的每一页由基本文件***来定义,从文件的开始处有一定偏移,而这一偏移不会改变-即使文件***重新安排盘上的页的实际位置。然而,术语“物理”位置不表示数据库管理***必需知道给定页储存在盘的何处。)逻辑页ID 13映射到用户数据页18的一个物理页地址。这一映射通过映射表16来实现。映射表16作为一组页储存在数据库文件内。每一映射表16包括将逻辑页ID 13映射到相应用户数据页18的物理页地址15(也称位置)的条目11。当用户数据页18的物理位置改变(如,当数据被转储到数据库),更新映射表16中其相应的条目。对于该条目,被移动的用户数据页18的逻辑ID 13没有改变,但是用户数据页18所移往的物理地址被输入进映射表16中条目11的物理位置部分15中。
数据库头页12和目录页14也包含将逻辑ID映射到物理地址的条目。数据库头页12包含将逻辑ID映射到目录页14的物理地址的条目。目录页14包含将逻辑ID映射到映射表16的物理地址的条目。
图3是表示映射到映射表页16的物理位置21的逻辑ID 19的目录页14的一部分。每一目录页14包括将逻辑ID 19映射到相应映射表页16的物理页地址21的条目17。当映射表页16的物理地址改变时(如,当数据被转储到数据库),更新目录页14中其相应的条目。对于该条目,移动的映射表页16的逻辑ID 19没有改变,但是映射表页16所移往的物理地址被输入进目录页14中条目17的物理位置部分21中。
图4是表示映射到目录页14的物理位置27的逻辑ID 25的数据库头页12的一部分。数据库头页12包括将逻辑ID 25映射到目录页14的物理地址27的条目。当目录页14的物理位置改变时(如,当数据被转储到数据库),更新数据库头页12中其相应的条目。对于该条目,要移动的头页12的逻辑ID 25没有改变,但是目录页14要移往的物理地址被输入进数据库头页12中条目23的物理位置部分27中。
在一个示例实施例中,要这样来分配逻辑ID,使得逻辑ID所引用的页的类型(如头、目录、映射表或用户数据页)能够从逻辑ID引用中推断出来。例如,使用以上描述的页和条目大小,页ID是0的可能指的是数据库头页12,页ID是1的可能指的是目录页14,页ID是2到643(包括643)的可能指的是映射表页16,大于或等于644的页ID可能指用户数据页18。逻辑ID可以以任意合适的方式来表示。在一个示例实施例中,逻辑ID用20位无符号值来表示。10个最低位对应目录页中包含相应映射表页16的物理页地址的条目。10个最高位对应于适当映射表页16中包含相应用户数据页18的物理页地址的条目。
逻辑ID可以以任意合适的方式映射到物理地址。表1以伪代码的形式描述了将逻辑ID映射到物理地址的一个示例技术。表1所示的技术采用上文描述的逻辑ID到物理地址分配。
表1
DWORD TranslateLogicalPageId(PAGEID idPage){//local variables//DWORD iEntry;20bitValue ofDirectoryPage;20bitValue ofMapPage;20bitValue ofDataPage;DATABASEHEADERPAGE headerPage;DIRECTORYPAGE directoryPage;MAPPINGTABLEPAGE mapPage;//if the page id refers to the database header page//if (0==idPage){//return zero(db header page is always at offset zero)//return 0;}//read the database header page//ReadPage(0,&headerPage);//save the physical address of the directory page//ofDirectoryPage=headerPage.DirectoryPageAddress;//if the logical page id refers to the directory page?//if(l==idPage){//return the physical address of the directory page//return ofDirectoryPage;}//read the directory page from the database//ReadPage(ofDirectoryPage*PAGESIZE,&directoryPage);//the least significant 10 bits are an index into the directorypage//iEntry=GetLeastSignificant10Bits(idPage);//get the physical address of the corresponding mapping table page//ofMapPage=directoryPage.rgMappingTablePageAddress[iEntry];//if the logical page id refers to this mapping table page?//if(idPage<=643){//return the physical address of the mapping table page//return of MapPage;}//read the mapping table page from the database |
//ReadPage(ofMapPage*PAGESIZE,&mapPage);//the most significant 10 bits are an index into the mapping page//iEntry =GetMostSignifican10Bits(idPage);//get the physical address of the corresponding data page//ofDataPage=mapPage.rgUserDataPageAddress[iEntry];//return the physical address of the user data page(idPage)//return ofDataPage;} |
如下文更详细的描述,依照本发明的一个实施例的阴影分页牵涉向可用页写页的内容。在这一进程中,一些页会变为空闲,而另一些会变为已用。为达到这一目标,提供了分配指示器。分配指示器指示逻辑ID和物理地址的状态(可用或不可用)。可以使用任何使用指示状态的方法。在一个示例实施例中,使用位图来指示逻辑ID的分配状态。逻辑ID分配位图包含对维护页(映射表页16、目录页14和数据库头页12)中的每一条目的一位。在一个示例实施例中,位设为1,则指示相应的条目已分配(不可用)。位设为0,则指示相应的条目是空闲的(可用)。在阴影分页进程中,通过搜索值为零的位图可以定位一个可用的页。为指示所找到的页现在已分配(不可用),将相应位图条目变为1。
在一个示例实施例中,逻辑ID分配位图作为一组页储存在数据库文件中。在另一实施例中,该位图不储存在数据库文件中,并且当数据库打开时被初始化。初始化可以通过清点映射表中所有页条目来实现(如,读数据库头页12、目录页14和映射表页16中的每一条目)。如果一个页条目包含一个页的有效物理地址,则与该页相应的页ID被标记为已分配。一旦扫描了所有的条目,该位图现在指示页ID的当前分配状态。
这一分配位图可以储存在数据库文件中。例如,如果最大数据库文件容量为232字节(4千兆字节),并且数据库页容量为4096字节,结果是最多220个逻辑页ID。这样可以使用131,072字节来实现逻辑页ID分配位图。
使用分配位图使逻辑页ID能够被释放和/或分配,而不需要修改或读维护页。这通过允许多重事务在同一时间分配并释放数据库中的页ID来提高并发性。使用分配位图也为分配和释放逻辑页ID提供了一种健壮的机制,因为位图和页条目都包含在数据库文件中。这一机制是健壮的,因为在事务被转储到磁盘以后,空闲物理页地址被标记为空闲,并且已分配的物理页地址被标记为已分配。如果不是这样,如果操作故障,必需重新运行整个转储,这将是非常困难的,因为含有更新的目录页(以及映射表页等等)的新物理地址的数据库头页已经被转储了。
一旦位图被读进内存,或通过扫描页条目被计算,分配和释放页可以通过对位图中的位进行计数直到遇到与要分配/释放的页相应的的位来实现。例如,使用以上示例中描述的页尺寸和数据库结构,与用户数据页相应的页ID可以通过找到第一个设定为0的大于或等于位图中的位644的位来分配。选择数字644是因为所有低于644的页ID在以上示例中保留为维护页。要释放逻辑页ID,只要地将位从1改为0即可。
上文描述的用于分配和释放逻辑页ID的位图型机制同样也适用于分配和释放物理页地址。在这一情况下,位图对于数据库文件中每一物理地址都有一个位。在一个示例实施例中,设定为1的位指示该物理页地址已分配。设定为0的位指示该物理页地址是空闲的。
物理页地址是页在数据库中的位置。当事务提交且页在盘上被投以阴影、当在阴影池中的脏页被替代时,分配物理页地址。脏页是已被修改的页。这里描述的阴影分页提供了有效地找到空/未使用页的物理页地址的能力。在一个示例实施例中,这一物理地址分配位图储存在数据库文件中。如上文所述,这一物理地址分配位图可以在131,072字节的最大容量范围内实现。在另一实施例中,当打开数据库时,通过扫描数据库头页12、目录页14和映射表页16来计算物理地址分配。如果计算位图,则可以在计算逻辑页ID位图的同时对其进行计算,因为扫描了同一组页。
释放物理页地址的计数与上文描述的释放逻辑页ID的计数相同。分配物理页地址的计数几乎与分配逻辑页ID的计数相同。不同之处在于,如果现存的物理页没有一个是空闲的,则增大数据库文件(即,在文件的末端添加一定数量的物理页),并且添加到数据库文件的新物理页地址被标记为地址位图中的空闲物理页地址。
以下表2以伪代码的形式显示了当第一次打开数据库时初始化逻辑页ID位图和物理页地址位图的一个示例技术。
表2
//this class is used to maintain a set of bit values//class Bitmap{//set the value of the bit at position iBit to 1 or 0//void SetBit(DWORD iBit,bool fValue);//get the value of the bit at position iBit//bool GetBit(DWORD iBit);};//some useful constants//const ULONG PAGEID_HEADER=0;const ULONG PAGEID_DIRECTORY=1;DWORD ComputeBitmaps(Bitmap& idBitmap, //free/allocated page id bitmapBitmap& addressBitmap) //free/allocated page address bitmap{//local variables//ULONG idPage;20bitValue ofMapPage; |
20bitValue ofDataPage;DATABASEHEADERPAGE headerPage;DIRECTORYPAGE directoryPage;MAPPINGTABLEPAGE mapPage;//mark the header page id and address as allocated//idBitmap.SetBit(PAGEID_HEADER,1);addressBitmap.SetBit(0,1);//read the database header page from offset zero//ReadPage(0,&headerPage);//mark the directory page id and address as allocated//idBitmap.SetBit(PAGEID_DIRECTORY,1);addressBitmap.SetBit(headerPage.DirectoryPageAddress,1);//read the directory page from the database//ReadPage(headerPage.DirectoryPageAddress*PAGESIZE,&directoryPage);//enumerate through the mapping table pages referenced//for(ULONG i=0;i<641;i++){//get the address of the map page//ofMapPage =directoryPage.rgMappingTablePageAddress[i];//if there is no mapping table page referenced here?//if(0==ofMapPage){//go to the next mapping table page//continue;}//make a page id//idPage=MakePageId(i/*high 10 bits*/,j/*low 10 bits*/);//mark the mapping table page id and address as allocated//idBitmap.SetBit(idPage,1);addressBitmap.SetBit(ofMapPage,1);//read the mapping table page from the database//ReadPage(ofMapPage*PAGESIZE,&mapPage);//enumerate through the user data pages referenced//for(ULONG j=0;j<1638;j++){//get the physical address of the corresponding data page//ofDataPage=mapPage.rgUserDataPageAddress[j]; |
//if there is no user data page referenced here?//if(0==ofDataPage){//go to the next user data page in this mapping tablepage//continue;}//make a page id//idPage=MakePageId(i/*high 10 bits*/,j/*low 10 bits*/};//mark the user data page id and address as allocated//idBitmap.SetBit(idPage,1);addressBitmap.SetBit(ofDataPage,1);}}//at this point the page id bitmap and address bitmap represent the//current set of allocated/free logical page ids,and the current//set of allocated/free physical page addresses.} |
图5到图7是实现阴影分页的示例进程的流程图。如上所述,当提交事务时,所有被事务所修改的页写入数据库文件(第一数据库存储)中的未使用(空闲)页。在事务的执行过程中,保留事务之前的存储状态和对数据库的访问。图5到图7中所描述的进程在下文示例性参考图1到图4所描述的组件来描述。
在步骤20,在数据库文件中产生映射表页(如映射表页18)。这些映射表页被用来维护数据库文件中用户数据页(如用户数据页18)的位置。通过映射表页对用户数据页的位置的维护可如上文所述的来实现。在步骤22,在数据库文件中产生目录页(如目录页14)。目录页用来维护映射表页的位置。通过目录页对映射表页的位置的维护可如上文所述的来实现。在步骤24,在数据库文件中产生数据库头页(如数据库头页12)。数据库头页用来维护目录页的位置。通过数据库头页对目录页的位置的维护可如上文所述的来实现。可任选地,如上文所述,在步骤26产生页分配位图。这一位图的产生包括指示逻辑ID的分配的位图、指示物理地址的分配的位图或两者的组合。通常,当最初创建数据库文件并在任何数据放入数据库文件中之前,产生维护页以及位图。
在步骤28,数据库文件中要修改的用户数据页(脏页)的内容储存在数据库文件中的未使用页中。在一个实施例中,修改的页保留在易失存储器中直到事务提交。当事务提交,将脏用户数据页从易失存储器写入数据库文件的未使用页中。储存脏页的内容的未使用页称为阴影页。这样,将脏用户数据页写入工作空间的未使用页(阴影页)中。在原用户数据页被标记为空闲之前写入阴影页,这样将原始用户数据页保留了一段时间。如果在完成之前操作故障,数据库仍处于相容(consistent)状态,因为仅改写未使用页,头、目录和映射表仍仅反映旧页的存在,而不是阴影页。在一个实施例中,可以通过将原始用户数据页复制到工作空间来实现这一目标。修改在工作空间中进行,然后将修改的工作空间页在事务提交之前复制到空闲页(阴影页)中。
在步骤30,将用户数据阴影页标记为已分配。即,脏页已写入的页不再空闲。这一分配状态可由任一合适的机制来指示。一种机制是分配位图。这样,在一个示例实施例中,在步骤30,阴影页的分配状态由分配位图来指示。随着每一用户数据页写入一个新物理页地址(被投以阴影),在步骤32更新映射表中用户数据页的相应条目来反映用户数据页的新位置。在步骤34,将用户数据页的前一物理地址(内容从其移出的地址)维护为“已分配”。即,用户数据页先前的物理地址未宣称为空闲。因为用户数据也还未更新,如果发生故障,数据库***能够恢复到它先前的状态。这样,“保护”了(saved off)用户数据页的旧物理地址,并如下文所述,在事务完成之后,将旧物理页地址标记为空闲(见步骤58)。
在步骤36,已修改(更新)的映射表页的内容储存在数据库文件的未使用页中(映射表阴影页)。这样,将脏映射表页写入数据库文件的未使用页(阴影页)。阴影页在做出任何修改之前先写入,这样将旧页保留一段时间。如果这一操作在完成之前失败,则数据库仍处于相容状态,因为仅改写了未使用页。在一个实施例中,通过将原始映射表页复制到工作空间来实现这一目标。修改在工作空间中进行,然后在事务提交之前将修改的工作空间页复制到空闲页(阴影页)。在步骤38,将映射表阴影页标记为已分配。即,脏页已写入的页不再空闲。这一分配状态可由任何合适的机制来指示。一个这样的机制是分配位图。这样,在一个示例实施例中,在步骤38,映射表页的分配状态由分配位图来指示。在步骤40,更新目录页(如目录页14)来反映映射表阴影页的位置。这样,随着每一映射表页写入一个新物理页地址,目录页中映射表页的相应条目被更新,来反映映射表的新位置。在步骤42维护了映射表页的先前的物理地址(内容从其移出的地址)。即,先前映射表页的物理地址未宣称为空闲。如果发生故障,这使数据库***能够恢复到它先前的状态。这样,“保护”了映射表页的旧物理地址,并且如下文所述,在事务完成之后,将旧物理页地址标记为空闲(见步骤58)。
在步骤44,目录页的内容储存在数据库文件的未使用页中(目录阴影页)。在做出任何修改之前将阴影页先写入,这样将旧页保留一段时间。在一个实施例中,通过将原始目录页复制到工作空间来实现这一目标。修改在工作空间中进行,然后在事务提交之前将修改的工作空间页复制到一个空闲页(阴影页)。在步骤46,将目录阴影页标记为已分配。即,目录页已写入的页不再空闲。这一分配状态可由任一合适的机制来指示。一个这样的机制是分配位图。这样,在一个示例实施例中,在步骤46,目录页的分配状态由分配位图来指示。在步骤48更新数据库头页(如数据库头页12)来反映目录阴影页的位置。这样,当目录页写入新物理地址时,更新数据库头页中目录页的相应条目来反映目录页的新位置。在步骤50维护目录页先前的物理地址(内容从其移出的地址)。即,先前目录页的物理地址未宣称为空闲。当发生故障时,这使得数据库***能够恢复到它先前的状态。这样,“保护”了目录页的旧物理地址,并且如下文所述,在事务完成之后,将旧物理页地址标记为空闲(见步骤58)。
在步骤52,数据库中所有阴影页(用户数据阴影页、映射表阴影页、目录阴影页)的内容储存在数据库永久存储器(已转储)中。转储(flush)数据库文件阴影,这样将前面的步骤中所有的变化固化到持久存储机制(如磁盘)中。在步骤54,数据库头页储存在数据库(已转储)中。在步骤56,再一次转储阴影页。这一双重转储技术确保数据库***在出现故障的情况下一恢复就处于相容状态。在写数据库头页之前,没有对数据库文件做出任何不安全的变化。其它事务可以使用数据库头页、目录页和映射表页的旧的或当前提交的版本。当提交数据库头页时,这激活了新目录页,从而激活了新映射表页,进而激活了用户数据页的新版本。例如,如果仅在写数据库头页之后出现转储,可能在目录页固化到存储盘之前将数据库头页固化到盘(保存目录页的新位置)。这可能会导致数据库***的状态变为不相容。步骤52、54和56的成功完成能够确保事务完全执行,这样旧物理地址变为空闲以便使用(可用)。因此,在步骤58宣称用户数据页、映射表页和目录页为空闲。这一分配状态可由任一合适的机制来实现,例如上述分配位图。在步骤58,释放所有旧物理页地址,这样它们可以用于其它操作。然而,如果在转储进程完成之前出现故障,所有新分配的物理页地址被释放,***处于其先前状态。
在一个示例实施例中,为确保事务是原子性的(如,一个扇区决不能部分地写),将目录页的物理页地址储存在数据库头页的第一扇区中,数据库头页储存在数据库文件的起点(如,第一扇区)。这样,提交一个事务是原子性的,因为如果没有写数据库头页的第一扇区,则事务不提交,并且数据库仍然相容,因为仅改写了未使用页。
参考图8到图13,下文提供了使用阴影分页完成事务的一个示例。图8说明了数据库文件的页0到8。页0是数据库头页,页1是目录页,页2是映射表页,页3到4是脏用户数据页,页5到8是空(未使用)页。实线代表头页中的条目(逻辑ID)指向目录页,目录页中的条目指向映射表页,以及映射表页中的条目指向用户数据页。这一示例从以下假定开始,假定事务已开始并已修改了用户数据页1和用户数据页2并正在提交。如上文所述,用户页1和用户页2的脏副本写入文件中的未使用位置中。
图9说明了分别将写入物理页地址5和6的用户页1和2(即,分别为物理页3和4)。对相应的映射表页进行修改以表示出用户页1和用户页2的新位置。将要写入页5和6的用户页1和2用从有灰条纹的映射表页出发的虚线箭头来指示。正在修改以表示出用户页1和2的新位置的映射页2用从有灰条纹的映射表页出发的实线箭头来指示。对映射表页的修改使其变为当前事务中的脏页。由于该事务正在执行,其它事务使用储存在页2中的映射表页(带阴影的灰色)。下一步,将已修改的映射表页写入未使用页。注意,参考图9,在每一步将页写入盘,然而在参考图5到图7的描述中,是在更新所有维护页之后将页转储到盘。依照本发明,两种技术都是合适的。这样,可以在进程中的任一合适时刻将页写入盘。
图10说明了将要被写入未使用页7的映射表页以及将要被更新来反映映射表页新地址的目录页。在这一示例中,仅修改了一个映射表页。同先前描述的步骤相类似来完成这一进程。将映射表页写入数据库文件的未使用页,并更新目录页来反映映射表页的新位置。其它事务仍使用分别位于页1和2的目录页和映射表页的灰色阴影部分。
下一步,将目录页写入未使用页,(本示例中的页8),如图11所示。图11也描述了将要更新以反映目录页的新位置的的数据库头页。下一步,如图12所示,写数据库头页(使用上文描述的双重转储技术)。在写头页并完成双重转储进程之后,事务成功地提交,并且其结果现在通过暴露在用户面前的数据库状态来反映(即,数据库用户现在可以“看见”对用户数据页、映射表页和目录页所做出的变化)。如图13所示,作为将四页移动到新物理页地址的结果,所释放的物理页地址(页1-4)被解除分配(设为可用)。
图14是完成阴影分页的***的流程图。在一个示例实施例中,***用来访问数据库,并在这一前提下进行描述。***包括工作空间(第一数据库存储)78、永久存储(第二数据库存储)80、页分配指示器72、控制器74以及可任选数据压缩器76。工作空间78和永久存储器80可以包括任何合适类型的存储器,如半导体存储器、磁存储器(如盘)、光存储器或其组合。通常并优选地,永久存储器80具有永久储存数据的能力。这样,在正常操作条件下,写入永久存储器80的数据一直可用,直到数据特别地被移出和/或改写。如这里所述,术语“转储”(flush)是指将数据传输到永久存储器80。
页分配指示器72完成如上所述的指示逻辑ID和物理地址的分配状态的功能。在一个示例实施例中,页分配指示器72包括如上所述的位图。数据压缩器76是可任选的。数据压缩器76压缩工作空间78和/或永久存储器80中的数据,来减少***中使用的存储器的容量。数据压缩器76可以采用任一合适的数据压缩技术。
控制器74执行许多与维护页(数据库头页、目录页和映射表页)相关联的功能,并同时控制用于实现如上文所述的阴影分页的步骤的处理。控制器74产生用于维护数据库文件中页的位置的维护页。控制器也将所选的页的内容储存在未使用页中(阴影页)。控制器74更新维护页来反映工作空间中阴影页的位置。控制器74也将维护页的内容储存在工作空间的未使用页中。控制器将工作空间78的内容储存在永久存储器80中。控制器74控制上文描述的双重转储进程。
合适计算***环境的概述
图15说明了一个可实现阴影分页方法和***的合适计算***环境100的示例。该计算***环境100仅是合适计算环境的一个示例,并非建议对用于动态并个别控制显示元素的方法和***的使用范围或功能的限制。也不应将该计算环境100解释为关于示例操作环境100中说明的任一组件或其组合具有任何依赖或需求。
阴影分页的方法和***可操作于许多其它通用或专用计算***环境或配置中。众所周知的适合与用于动态并个别控制显示元素的方法和***使用的计算***、环境和/或配置的示例包括但不限于,个人计算机、服务器计算机、手持式或膝上设备、多处理器***、基于微处理器的***、机顶盒、可编程消费类电子产品、网络PC、小型机、大型机、包括以上***或设备的分布式计算环境等等。
阴影分页的方法和***可能在计算机可执行指令的普通语境下描述,如由计算机执行的程序模块。通常,程序模块包括例程、程序、对象、组件、数据结构等等,完成特定的任务或实现特定的抽象数据类型。阴影分页的方法和***也可以在由通过通信网络或其它数据传输媒质连接的远程处理设备完成任务的分布式计算环境中实践。在分布式计算环境中,程序模块和其它数据可以位于包括存储器存储设备的本地和远程计算机存储媒质中。
参考图15,用于实现阴影分页方法和***的示例***包括以计算机110形式的通用计算设备。计算机110的组件可以包括但不限于,处理单元120、***存储器130以及将包括***存储器130的各种***组件耦合到处理单元120的***总线121。***总线121可以是若干总线结构类型中的任一种,包括存储器总线或存储器控制器、***总线以及使用任一各类总线结构的本地总线。作为示例而非局限,这类结构包括工业标准体系结构(ISA)总线、微通道结构(MCA)总线、增强型ISA(EISA)总线、视频电子标准协会(VESA)本地总线以及外设部件互连(PCI)总线(也称为Mezzanine总线)。
计算机110通常包括各种计算机可读媒质。计算机可读媒质可以是任意计算机110可访问的可用媒质,包括易失和非易失媒质、可移动和不可移动媒质。作为示例而非局限,计算机可读媒质可以包括计算机存储媒质和通信媒质。计算机存储媒质包括在任何用于储存如计算机可读指令、数据结构、程序模块或其它数据的信息的方法或技术中实现的易失和非易失、可移动和不可移动媒质。计算机存储媒质包括但不限于,RAM、ROM、EEPROM、闪存或其它存储器技术、CD-ROM、数字多功能盘(DVD)或其它光盘存储、磁盒、磁带、磁盘存储或其它磁存储设备、或其它任何可以用来储存所需要的信息并可由计算机110访问的媒质。通信媒质通常包含计算机可读指令、数据结构、程序模块或其它在如载波或其它传输机制的已调制数字信号中的数据,并包括任意信息传送媒质。术语“已调制数字信号”指其一个或多个特性以某种方式设定或改变来对信号中的信息进行编码的信号。作为示例但非局限,通信媒质包括有线媒质如有线网络或直接连线连接以及无线媒质如声学、RF、红外或其它无线媒质。可以理解,任何这些媒质的组合也包括在计算机可读媒质的范围内。
***存储器130包括以易失和/非易失存储器形式的计算机存储媒质,如ROM 131和RAM 132。基本输入/输出***133(BIOS)包括如在启动时帮助在计算机110内的元件之间传输信息的基本例程,通常储存在ROM 131中。RAM 132通常包含处理单元120立即可访问并且/或者当前正在操作的数据和/或程序模块。作为示例但非局限,图15说明了操作***134、应用程序135、其它程序模块136以及程序数据137。
计算机110也可以包括可移动/不可移动、易失/非易失计算机存储媒质。仅作为示例,图15说明了对不可移动、非易失磁媒质进行读写的硬盘驱动器141、对可移动、非易失磁盘152进行读写的磁盘驱动器151以及对可移动、非易失光盘156如CD-ROM、CDRW或其它光媒质进行读写的光盘驱动器155。其它可用在示例操作环境的可移动/不可移动、易失/非易失计算机存储媒质包括但不限于,磁带盒、闪存卡、数字多功能盘、数字视频带、固态RAM、固态ROM等等。硬盘驱动器141通常通过不可移动存储器接口如接口140连接到***总线121,并且磁盘驱动器151和光盘驱动器155通常通过可移动存储器接口,如接口150连接到***总线121。
以上讨论的并在图15中说明的驱动器及其相关计算机存储媒质为计算机110提供了计算机可读指令、数据结构、程序模块和其它数据的存储。例如,在图15中,说明硬盘141储存操作***144、应用程序145、其它程序模块146以及程序数据147。注意,这些组件可以与操作***134、应用程序135、其它程序模块136以及程序数据137相同,也可以与它们不同。这里对操作***144、应用程序145、其它程序模块146以及程序数据147给予不同的数字,来说明至少它们是不同的副本。用户可以通过输入设备如键盘162和指向设备161,通常称为鼠标、轨迹球或触摸板向计算机110输入命令和信息。其它输入设备(未示出)可以包括麦克风、操纵杆、游戏板、圆盘式卫星天线、扫描仪等等。这些和其它输入设备通常通过耦合至***总线121的用户输入接口160连接到处理单元120,但也可以通过其它接口和总线结构来连接,如并行端口、游戏端口或通用串行总线(USB)。监视器191或其它类型的显示设备也通过接口,如视频接口190连接到***总线121。除监视器之外,计算机也可以包括其它***输出设备,如扬声器197和打印机196,通过输出***接口190连接。
计算机110可以运行在使用到一个或多个远程计算机,如远程计算机180的逻辑连接的网络化环境中。远程计算机180可以是个人计算机、服务器、路由器、网络PC、对等设备或其它公用网络节点,通常包括许多或所有以上描述的与计算机110相关的元件,尽管在图15中仅说明了存储器存储设备181。所描述的逻辑连接包括局域网(LAN)171和广域网(WAN)173,但也可以包括其它网络。这类网络环境常见于办公室、企业范围计算机网络、企业内部互联网以及因特网。
当用在LAN网络环境中时,计算机110通过网络接口或适配器170连接到LAN 171。当在WAN网络环境中使用时,计算机110通常包括调制解调器172或其它装置,用于通过WAN 173,如因特网建立通信。调制解调器172可以是内置的或外置的,可以通过用户输入接口160或其它合适的机制连接到***总线121。在网络化环境中,所描述的与计算机110相关的程序模块或其部分可以储存在远程存储器存储设备上。作为示例但非局限,图15说明了远程应用程序185驻留在存储器设备181上。可以理解,这里示出的网络连接是示例性的,可以使用在计算机之间建立通信链路的其它装置。
从个人计算机和因特网的集中的观点,已经发展并且正在发展各种分布式计算框架。个人和商业用户同样地拥有用于应用和计算设备的无缝共同操作并且web激活的接口,使得计算活动越来越面向web浏览器和网络。
例如,
的.NET平台包括服务器、构件服务如基于web的数据存储以及可下载设备软件。通常来说,.NET平台提供(1)令整个范围的计算设备共同工作并在所有设备上自动更新并同步化用户信息的能力,(2)提高的web站点交互能力,通过大量使用XML而不是HTML来实现,(3)从用于各种应用,如电子邮件,或软件,如Office.NET的管理的中央起点到用户的具有产品和服务的定制访问和传送的特点的在线服务,(4)中央化数据存储,将增加信息访问以及用户和设备间的信息同步的效率和简易性,(5)整合各种通信媒质,如电子邮件、传真和电话的能力,(6)对开发员来说,创建可重复使用模块的能力,借此提高生产力并降低编程错误数,以及(7)还有其它跨平台综合特性。
这里的示例性实施例是结合驻留在计算设备上的软件描述的,也可以通过操作***、应用程序接口(API)或协处理器和请求对象之间的“中间人”对象来实现阴影分页的方法和***的一个或多个部分,使服务可以由所有.NET的语言和服务,以及在其它分布式计算框架中完成、支持或访问。
这里描述的阴影分页的方法可以以由计算机实现的进程和用于实践这些进程的***的形式来实施。这里描述的阴影分页方法也可以以配备在有形媒质,如软盘、只读存储器(ROM)、CD-ROM、硬盘、高密度盘或其它任何计算机可读存储媒质中的计算机程序代码的形式来实施,其中,当计算机程序代码装载到计算机并由其执行时,该计算机变为用于实践本发明的***。这里描述的阴影分页的方法也可以以计算机程序代码的形式来实施,如储存在存储媒质中、装载到计算机并由其执行、或者通过一些传输媒质,如电线或电缆、通过光纤或通过电磁辐射来传输的程序代码,其中,当该计算机程序代码装载到计算机并由其执行时,该计算机变为可实践本发明的***。当在通用处理器上实现时,计算机程序代码段配置处理器来创建特定逻辑电路。
这里描述的各种技术可以结合硬件或软件,或者,如果合适的话,两者的组合来实现。这样,本发明的方法和装置或其特定方面或部分,可以采用配备在有形媒质,如软盘、CD-ROM、硬盘或其它任何机器可读存储媒质中的程序代码(即,指令)的形式,其中,当程序代码装载到机器,如计算机,并由其执行时,该机器变为用于实践本发明的装置。在程序代码在可编程计算机上执行的情况下,计算设备通常包括处理器、处理器可读的存储媒质(包括易失和非易失存储器和/或存储元件)、至少一个输入设备以及至少一个输出设备。可能使用本发明的信号处理服务,如通过使用数据处理API或其类似物的一个或多个程序优选地在高级程序语言或面向对象编程语言中实现,来与计算机通信。然而,如果需要,程序可以在汇编语言或机器语言中实现。无论如何,语言可以是已编译或已解释的语言,并且与硬件实现组合。
本发明的方法和装置也可以通过以通过一些传输媒质,如通过电线或电缆、通过光纤或通过其它任何传输形式来发送的程序代码的形式实施的通信来实践,其中,当程序代码被机器,如EPROM、门阵列、可编程逻辑设备、客户端计算机、视频记录器或其类似物、或具有如以上示例实施例中描述的信号处理能力的接收机器接收、装载并执行时,该机器变为可实践本发明的装置。当在通用处理器上实现时,程序代码与处理器组合来提供可操作来调用本发明的函数的独特装置。另外,与本发明结合使用的任一存储技术可以不变地为硬件和软件的组合。
本发明的实施例是结合各种示图的较佳实施例来描述的,可以理解,也可以使用其它类似的实施例,或者在不偏离本发明的情况下对所描述的实施例作出修改或添加,来完成相同的功能。此外,必需强调,可以考虑各种计算机平台,包括手持式操作***或其它应用指定操作***,尤其是在大量无线网络化设备继续增加的情况下。因此,本发明不应局限于任一单个实施例,而应根据后附权利要求书的宽度和范围来解释。