数据库系统概念笔记——第10章 存储和文件结构

第10章 存储和文件结构

物理存储介质概述

大多数计算机系统中存在多种数据存储类型。可以根据访问数据的速度,购买介质时每单位数据的成本,以及介质的可靠性对这些存储介质进行分类。以下是几种有代表性的介质:

  • 高速缓冲存储器(cache)。高速缓冲存储器是最快最昂贵的存储介质。高速缓冲存储器一般很小,由计算机系统硬件来管理它的使用。在数据库系统中,我们不需要考虑高速缓冲存储器的存储管理。但值得注意的是,在设计查询处理的数据结构和算法时,数据库实现者也会注意高速缓冲存储器的影响。

  • 主存储器(main memory)。主存储器是用于存放可处理的数据的存储介质。通用机器指令在主存储器上执行。尽管在个人电脑上的主存储器可以包含几个GB的数据,甚至在大型服务器系统中包含数百个GB的数据,但是一般情况下它对于存储整个数据库来说还是太小(或太昂贵)。如果发生电源故障或者系统崩溃,主存储器中的内容通常会丢失。

  • 快闪存储器(flash memory) 是在电源关闭(或故障)时数据可保存下来。目前有两种类型的快闪存储器,称作NAND和NOR快闪。对于既定价格,NAND快闪拥有更高的存储容量,并且广泛作为一些设备的数据存储使用,例如照相机、音乐播放器和手机,同时也越来越多地用于笔记本电脑。相比于主存储器,快闪存储器拥有每字节更低的价格,以及具有非易失性,即便电源切断,它也能保留存储的数据。

  • 磁盘存储器(magnetic-disk storage)。用于长期联机数据存储的主要介质是磁盘。通常整个数据库都存储在磁盘上。为了能够访问数据,系统必须将数据从磁盘移到主存储器。在完成指定的操作后,修改过的数据必须写回磁盘。

  • 光学存储器(optical storage):光学存储器最流行的形式是光盘(Compact Disk,CD),它可以容纳大约700MB的数据,播放约80分钟。数字视频光盘(Digital Video Disk,DVD)的每一盘面可以容纳4.7GB或者8.5GB的数据(一张双面盘最多可以容纳17GB的数据)。可以用数字万能光盘(digital versatile disk)代替数字视频光盘(digital video disk)作为DVD的全称,因为DVD可以存储任何数字数据,而不仅仅是视频数据。数据通过光学的方法存储到光盘上,并通过激光器读取。一种称作蓝光(Blu-ray)DVD的更高容量格式可以单层存储27GB或双层存储54GB数据。

  • 磁带存储器(tape storage)。磁带存储器主要用于备份数据和归档数据。尽管磁带比磁盘便宜得多,但是访问数据也比磁盘慢得多,这是因为磁带必须从头顺序访问。因为这个原因,磁带存储器称为顺序访问(sequential-access)的存储器。相对而言,磁盘存储器称为直接访问(direct-access)的存储器,因为它可以从磁盘的任何位置读取数据。

磁带具有很大的容量(现在的磁带可以容纳40~300GB的数据),并且可以从磁带设备中移出,因此它们非常适合进行便宜的归档存储。磁带库(自动磁带机)用于存储异常巨大的数据集合,比如可能有几百TB(1TB=101210^{12}字节)的卫星数据,或少数情况下甚至是若干PB的数据(1PB=101510^{15}字节)。

在这里插入图片描述
最快的存储介质(例如高速缓冲存储器和主存储器)称为基本存储(primary storage)。层次结构中基本存储介质的下一层介质(例如磁盘)称为辅助存储(secondary storage)联机存储(online storage)。层次结构中最底层的介质(如磁带机和自动光盘机)称为三级存储(tertiary storage)或脱机存储(offline storage)

磁盘和快闪存储器

磁盘的物理特性

磁盘在物理上是相对简单的。磁盘的每一个盘片(platter)是扁平的圆盘。它的两个表面都覆盖着磁性物质,信息就记录在表面上。盘片由硬金属或玻璃制成。
在这里插入图片描述

当磁盘被使用时,驱动马达使磁盘以很高的恒定速度旋转(通常为每秒60、90或120转,也可达到每秒250转)。有一个读写头恰好位于盘片表面的上方。盘片的表面从逻辑上划分为磁道(track),磁道又划分为扇区(sector)。扇区是从磁盘读出和写入信息的最小单位。对于现在的磁盘,扇区大小一般为512字节,每一个盘片有约50000 \sim 100000条磁道,每条磁盘有151\sim 5个盘片。内侧的磁道(离转轴近的地方)长度较短,在现代的磁盘中,外侧的磁道比内侧的磁道拥有更多的扇区。一般而言,内侧每磁道大约包含5001000500\sim 1000个扇区,而外侧每磁道大约包含100020001000\sim 2000个扇区。对于不同模式的磁盘,上面的数字会有变化,高容量的模式通常在每条磁道上含有更多的扇区,而且在每个盘片上有更多的磁道。

通过反转磁性物质磁化的方向,读写头(read-write head)将信息磁化存储到扇区中。

磁盘的每个盘片的每一面都有一个读写头,读写头通过在盘片上移动来访问不同的磁道。一张磁盘通常包括很多个盘片,所有磁道的读写头安装在一个称为磁盘臂(diskarm)的单独装置上,并且一起移动。安装在转轴上的所有磁盘盘片和安装在磁盘臂上的所有读写头统称为磁头-磁盘装置(head-disk assembly)。因为所有盘片上的读写头一起移动,所以当某一个盘片的读写头在第ii条磁道上时,所有其他盘片的读写头也都在各自盘片的第ii条磁道上。因此,所有盘片的第ii条磁道合在一起称为第ii柱面(cylinder)

为了增大记录密度,读写头尽可能地靠近磁盘盘片的表面。读写头一般浮于盘片表面之上几微米;磁盘的旋转产生微风,而磁头装置的形状使其在微风作用下恰好浮于盘片表面之上。因为读写头离盘片表面非常近,所以盘片必须制作得非常平。

读写头损坏是一个问题。如果读写头接触到盘片的表面,读写头会刮掉磁盘上的记录介质,破坏存放在那里的数据。在早期的磁盘上,读写头接触盘片表面所刮掉的介质将散落到其他盘片及其读写头之间,引起更多的损坏,因此一个读写头的损坏可能导致整张磁盘失效。目前使用的磁盘驱动器使用一层磁金属薄膜作为存储记录的介质。这样的磁盘和以前的涂氧化膜的磁盘相比,不易因为读写头损坏而产生故障。

磁盘控制器(disk controller)作为计算机系统和实际的磁盘驱动器硬件之间的接口。在现代磁盘系统中,磁盘控制器在磁盘驱动单元内部实现。它接受高层次的读写扇区的命令,然后开始动作,如移动磁盘臂到正确的磁道,并实际地读写数据。磁盘控制器为它所写的每个扇区附加校验和(checksum),校验和是从写到扇区中的数据计算得到的。当读取一个扇区时,磁盘控制器用读到的数据再一次计算校验和,并且把它与存储的校验和比较。如果数据被破坏,则新计算出的校验和与存储的校验和不一致的可能性就很高。如果发生了这样的错误,磁盘控制器就会重读几次;如果错误继续发生,磁盘控制器就会发出一个读操作失败的信号。

磁盘控制器执行的另一个有趣的任务是坏扇区的置映射(remapping of bad sector)。当磁盘初始格式化时,或试图写一个扇区时,如果磁盘控制器检测到一个损坏的扇区,它会把这个扇区在逻辑上映射到另一个物理位置(从为此目的而留出的额外扇区中分配)。重映射记录在磁盘或非易失性存储器中,而写操作在新的位置上执行。

磁盘通过一个高速互连通道连接到计算机系统。有大量的通用接口用于将磁盘连接到计算机,现今一般使用的接口是:

  1. SATA,也叫串行ATA(serialATA9),最新版本的SATA称作 SATAⅡ
    或者SATA3Gb(ATA标准的旧版本称作PATA,或并行ATA,或者IDE,在早期广泛地使用,并且现在依旧可用)
  2. 小型计算机系统互联(Small-Computer-System Interconnect,SCSI,发音为
    “scuzzy”
  3. SAS,也叫串行附着SCSI(serial attached SCSI),和(4)光纤通道接口(Fibre Channel Interface)。
  4. 便携式外部磁盘系统经常使用USB接口或IEEE1394火线接口。

磁盘通常可以通过电缆直接与计算机系统的磁盘接口相连,也可以放置到远端并通过高速网络与磁盘控制器相连。在存储区域网(Storage Area Network,SAN)体系结构中,大量的磁盘通过高速网络与许多计算机服务器相连。通常磁盘采用独立磁盘冗余阵列(Redundant Array of Independent Disk,RAID)技术进行本地化组织,从而给服务器一个很大且非常可靠的磁盘的逻辑视图。尽管可能被网络分开,计算机和磁盘子系统继续通过SCSI、SAS和光纤通道接口互相通信。

网络附加存储(Network Attached Storage,NAS)由SAN发展而来。NAS很像SAN,但是它通过使用网络文件系统协议(如NFS或CIFS)提供文件系统接口,而不是看似一张大磁盘的网络存储器。

磁盘性能的度量

磁盘质量的主要度量指标是容量、访问时间、数据传输率和可靠性。

访问时间(access time)是从发出读写请求到数据开始传输之间的时间。磁盘上指定扇区的数据,磁盘臂首先必须移动,以定位到正确的磁道,然后等待磁盘旋转,直到指定的扇区出现在它下方。磁盘臂重定位的时间称为寻道时间(seek time),它随磁盘臂移动距离的增大而增大。典型的寻道时间在2302\sim 30毫秒之间,依赖于目的磁道距离磁盘臂的初始位置有多远。较小的磁盘因为移动距离较短而寻道时间较短。

平均寻道时间(average seek time) 是寻道时间的平均值,是在一个(均匀分布的)随机请求的序列上计算得到的。假设所有的磁道包含相同的扇区数,同时我们忽略读写头开始移动和结束移动所花费的时间,我们可以得到平均寻道时间是最坏情况下寻道时间的1/3。考虑到前面忽略的这些因素,平均寻道时间大约是最长寻道时间的1/2。现在,平均寻道时间在4104\sim 10毫秒之间,依赖于磁盘模式。

一旦读写头到达了所需的磁道,等待访问的扇区出现在读写头下所花费的时间称为旋转等待时间(rotational latency time)。现在一般的磁盘转速在每分钟5400转(每秒90转)到每分钟15000转(每秒250转)之间,或者等价地,在每转4毫秒到每转11毫秒之间。平均情况下,磁盘需要旋转半周才能使所要访问的扇区开始处于读写头的下方。因此磁盘的平均旋转等待时间是磁盘旋转一周时间的1/2。

数据传输率(data-transfer rate) 是从磁盘获得数据或者向磁盘存储数据的速率。目前的磁盘系统支持每秒25100 MB25\sim 100 \ MB的数据最大传输率。对于磁盘的内侧磁道,数据传输率明显低于最大传输率。

最后一个经常使用的磁盘度量标准是平均故障时间(Mean Time To Failure,MTTF),这是磁盘可靠性的度量标准。磁盘(或其他任何系统)的平均故障时间是,平均说来我们可以期望系统无故障连续运行的时间量。据生产商声称,现代磁盘的平均故障时间在5000001200000500000\sim 1200000小时之间(大约5713657\sim 136年)。事实上,这里声称的平均故障时间是基于全新磁盘发生故障的可能性计算的。

磁盘块访问的优化

磁盘I/O请求是由文件系统和大多数操作系统具有的虚拟内存管理器产生的。每个请求指定了要访问的磁盘地址,这个地址是以块号的形式提供的。一个块(block) 是一个逻辑单元,它包含固定数目的连续扇区。块大小在512字节到几KB之间。数据在磁盘和主存储器之间以块为单位传输。术语页(page)常用来指块,尽管在有些语境(例如闪存)中指的是另外的含义。

来自磁盘的连续请求有可以归类成顺序访问模式或随机访问模式。在一个顺序访问(sequentialaccess) 模式中,连续的请求会请求处于相同的磁道或是相邻的磁道上连续的块。在顺序访问中读取块时,第一块可能需要一次磁盘寻道,但是相继的请求既不需要寻道,也不需要对相邻磁道的寻道,这比对一条更远处的磁道寻道要快。

与之相反,在随机访问(random access)模式中,相继的请求会请求那些随机位于磁盘上的块。每一个请求都需要一次磁盘寻道。一张磁盘在一秒钟内能满足的随机块访问的数量取决于寻道时间,并且通常是每秒100200100\sim 200的访问次数。由于每次寻道只有少量的数据(一块数据)被读取,因此随机访问模式的数据传输率明显低于顺序访问模式。

为了提高访问块的速度,产生了许多技术。

  • 缓冲(buffering):从磁盘读取的块暂时存储在内存缓冲区中,以满足将来的要求。缓冲通过操作系统和数据库系统共同运作。
  • 预读(read-ahead):当-一个磁盘块被访问时,相同磁道的连续块也被读入内存缓冲区中,即便没有针对这些块的即将来临的请求。在顺序访问的情况下,当它们被请求时,这种预读可以确保许多块已经在内存中,减少了磁盘寻道和读取每块的旋转等待时间。操作系统也经常对操作系统文件预先读取连续的块。但是,预读对于随机块访问并不是很有用。
  • 调度(scheduling):如果需要把一个柱面上的几个块从磁盘传输到主存储器,我们可以按块经过读写头的顺序发出访问块的请求,从而节省访问时间。如果所需的块在不同的柱面上,按照使磁盘臂移动最短距离的顺序发出访问块的请求是非常有利的
    • 磁盘臂调度(disk-arm scheduling)算法试图把对磁道的访问按照能增加可以处理的访问数量的方式排序。通常使用的算法是电梯算法(elevator algorithm),这种算法的工作方式与许多电梯的工作方式非常相似。假设一开始,磁盘臂从最内端的磁道向磁盘的最外端移动。在电梯算法的控制下,对每条有访问请求的磁道,磁盘臂都在那条磁道停下,为这条磁道的请求提供服务,然后继续向外移动,直到没有对更外层磁道的等待请求。这时,磁盘臂掉转方向,开始向内侧移动,同样在每条有请求的磁道处停下,直到没有更靠近中心的磁道上有请求在等待。接着,它掉转方向,开始一个新的周期。磁盘控制器通常对读请求进行重新排序以提高性能,因为它最清楚磁盘块的组织、磁盘盘片的旋转位置和磁盘臂的位置。
  • 文件组织(file organization):为了减少块访问时间,我们可以按照与预期的数据访问方式最接近的方式来组织磁盘上的块。例如,如果我们预计一个文件将顺序地访问,那么理想情况下我们应该使文件的所有块存储在连续的相邻柱面上。随后的操作系统,如UNIX和Windows操作系统,对用户隐藏了磁盘的组织,并且由操作系统内部来管理空间的分配。尽管它们不能保证一个文件的所有块顺序分布,但它们一次为一个文件分配多个连续的块(一个区(extent))。然后,文件的顺序访问只需每个区寻道一次,而不是每个块寻道一次。经过一段时间,一个连续的文件将变得碎片化(fragmented),即它的块散布在整张磁盘上。为了减少碎片,系统可以对磁盘上的数据进行一次备份,然后再恢复整张磁盘。恢复操作将每个文件的块连续地(或几乎连续地)写回。一些系统(如Windows操作系统的不同版本)提供扫描整张磁盘然后移动块以减少碎片的工具。这种技术所实现的性能提高非常显著。
  • 非易失性写缓冲区(nonvolatile write buffer)。因为主存储器中的内容在发生电源故障时将全部丢失,所以关于数据库更新的信息必须记录到磁盘上,这样才能在系统崩溃时得以保存。因此,更新操作密集的数据库应用的性能,如事务处理系统的性能,高度依赖于磁盘写操作的速度。
  • 日志磁盘(log disk)。减少写等待时间的另一种方法是使用日志磁盘,即一种专门用于写顺序日志的磁盘,这和非易失性RAM缓冲区的使用非常相似。对日志磁盘的所有访问都是顺序的,这从根本上消除了寻道时间,并且一次可以写几个连续的块,使得写日志磁盘比随机的写要快许多倍。和前面一样,数据也必须写到它们在磁盘上的实际位置,但是数据库系统不需要等待这种写操作的完成,日志磁盘会在以后完成写操作。进一步说,日志磁盘可以为了最少化磁盘臂的移动而重排写操作的顺序。如果系统在实际磁盘写操作完成以前崩溃,在系统恢复后,系统可以读取日志磁盘,找到那些还没有完成的写操作并将它们完成。

为了处理这种数据结构破坏的可能性,早期文件系统必须在系统重新启动时执行一个文件系统一致性检验,以保证数据结构是一致的。且如果它们不一致,必须执行额外的步骤还原它们以保证一致性。这些检验会使得系统崩溃后的重启动有较长的延时,而且这个延时随着磁盘系统容量的增加而变得更加严重。日志文件系统允许快速重启动而不需要这样的一致性检验。

快闪存储

一共有两种快闪存储器,即NOR快闪和NAND快闪。NOR快闪允许随机访问闪存中的单个字,并且拥有和主存可媲美的读取速度。而NAND快闪和NOR快闪不同,它的读取需要将整个数据页从NAND快闪取到主存储器中,该数据页通常包括5124096512\sim 4096字节。NAND快闪中的页和磁盘中的扇区十分相似。但是NAND快闪明显比NOR快闪便宜,并且拥有更高的存储容量,且目前更广泛使用。

采用NAND快闪构建的存储系统提供与磁盘存储器相同的面向块的接口。与磁盘相比,闪存可以提供更快的随机存取:一个数据页,从闪存中可以在约121\sim 2微秒内检索到,而从磁盘上的一个随机访问则需要5105\sim 10毫秒。闪存具有比磁盘低的传输速率,一般来说为每秒20MB。最近的一些闪存的传输速率增加到每秒100200MB100\sim 200MB。然而,固态驱动器并行地使用多块闪存芯片,将传输速率提高到每秒200MB以上,这比大多数磁盘的传输速率更快。

闪存的写入稍有些复杂。写一个闪存页面通常需要几微秒。然而,一旦写入,闪存的页面不能直接覆盖。它必须先擦除然后再重写。一次擦除操作可以在多个页面执行,称为擦除块(erase block),这种操作需时约121\sim 2毫秒。一个擦除块的大小(在闪存文献中通常描述为“块”)通常明显比存储系统的块大很多。此外,对一个闪存页可以擦除多少次存在限制,通常大约为1010010万\sim 100万次。一旦达到此限制,在存储位就可能发生错误。

闪存系统通过映射逻辑页码到物理页码,限制了慢擦除速度和更新限制的影响。当一个逻辑页更新时,它可以重新映射到任何已擦除的物理页,它原来的位置可以随后擦除。每个物理页都有一个小的存储区域来保存它的逻辑地址;如果逻辑地址重新映射到一个不同的物理页,则原来的物理页被标记为已删除。因此,通过扫描物理页,我们可以发现每个逻辑页的位置。为了快速访问,逻辑到物理的页面映射被复制到内存的转换表(translation table) 中。

所有的上述动作通过一个叫做闪存转换层(flash translation layer) 的软件层完成。在这一层之上,闪存存储器看起来和磁盘存储器一样,都提供同样的面向页/扇区的接口,除了闪存存储器快得多。因此,文件系统和数据库存储结构可以看到相同的底层存储结构逻辑视图,无论是闪存存储器或磁盘存储器。

混合硬盘驱动器(hybird disk drive) 是结合了小容量闪存存储器的硬盘系统,对频繁访问的数据,该驱动器作为缓存使用。频繁访问但很少更新的数据最适合于缓存在闪存存储器中。

RAID

为了提高性能和可靠性,人们提出了统称为独立磁盘冗余阵列(Redundant Array of Independent Disk,RAID)的多种磁盘组织技术。

通过冗余提高可靠性

引入冗余(redundancy) 是解决这个可靠性问题的方法,即存储正常情况下不需要的额外信息,但这些信息可在发生磁盘故障时用于重建丢失的信息。这样,即使有一张磁盘发生了故障,数据也不会丢失,从而延长了磁盘发生故障的有效平均时间(这里只计导致数据丢失或数据不可用的磁盘故障)。

实现冗余最简单(但最昂贵)的方法是复制每一张磁盘。这种技术称为镜像(mirroring)(或者有时称为影子)。这样,一张逻辑磁盘由两张物理磁盘组成,并且每一次写操作都要在两张磁盘上执行。如果其中一张磁盘发生了故障,数据可以从另一张磁盘读出。只有当第一张磁盘的故障被修复之前,第二张磁盘也发生了故障时,数据才会丢失。

采用镜像技术的磁盘的平均故障时间(这里的故障是指数据的丢失)依赖於单张磁盘的平均故障时间和平均修复时间(mean time to repair)平均修复时间是替换发生故障的磁盘并且恢复这张磁盘上的数据所花费的(平均)时间。假设两张磁盘发生故障是相互独立的,即一张磁盘的故障和另一张磁盘的故障之间没有联系。

通过并行提高性能

我们可以通过在多张磁盘上进行数据拆分(striping data)来提高传输速率。数据拆分最简单的形式是将每个字节按比特分开,存储到多个磁盘上。这种拆分称为比特级拆分(bit-level striping)

块级拆分(block-level striping) 是将块拆分到多张磁盘。它把磁盘阵列看成一张单独的大磁盘,并且给块进行逻辑编号,这里我们假设块的逻辑编号从0开始。对于n张磁盘的阵列,块级拆分将磁盘阵列逻辑上的第ii个块存储到第imod  n+1(i\mod n)+1张磁盘上:即用第in\lfloor\frac{i}{n} \rfloor个物理块存储逻辑块ii

块级拆分是最常用的数据拆分形式。其他层次的拆分,例如将扇区按字节拆分或者将块按扇区拆分,也是可以实现的。
总之,磁盘系统中的并行有两个主要的目的:

  1. 负载平衡多个小的访问操作(块访问),以提高这种访问操作的吞吐量。
  2. 并行执行大的访问操作,以减少大访问操作的响应时间。

RAID级别

镜像提供了高可靠性,但它十分昂贵。拆分提供了高数据传输率,但不能提高可靠性。通过结合“奇偶校验位”(在下文描述)和磁盘拆分思想,从而以较低的代价提供数据冗余,人们已经提出了一些不同的替换方案。这些方案具有不同的成本和性能之间的权衡,并且分为若干RAID级别(RAID level)。

RAID 0级(RAID level 0)

指块级拆分但没有任何冗余(例如镜像或奇偶校验位)的磁盘阵列。

在这里插入图片描述

RAID 1级(RAID level 1)

指的是使用块级拆分的磁盘镜像。
在这里插入图片描述

注意一些厂商使用RAID1+0级或RAID10级来指代使用拆分的镜像,使用RAID1级指代不使用拆分的镜像。不使用拆分的镜像可以与磁盘阵列一起使用,以呈现为一张单一的大型可靠磁盘:如果每张磁盘有M块,逻辑块0M10\sim M-1存储在磁盘0上,逻辑块M2M1M\sim 2M-1存储在磁盘1(第二张磁盘)上,依次类推,且每张磁盘都有镜像。

RAID 2级(RAID level 2)

称为内存风格的纠错码(Ermor-Correcting-Code,ECC) 组织结构,使用奇偶校验位。长期以来,内存系统使用奇偶校验位来实现错误检测和纠正。内存系统中的每个字节都有一个与之相联系的奇偶校验位,它记录了这个字节中为1的位数是偶数(奇偶校验位=0)还是奇数(奇偶校验位=1)。如果这个字节中有一位被破坏(1变成0,或0变成1),那么这个字节的奇偶校验位就会改变,而与存储的奇偶校验位不匹配。同样地,如果存储的奇偶校验位被破坏,它就不能和计算出的奇偶校验位相匹配。因此,内存系统可以检测到所有的1位错误。纠错码机制存储两个或更多的附加位,并且如果有一位被破坏,它可以重建数据。

在这里插入图片描述
通过把字节拆分存储到多张磁盘上,纠错码的思想可以直接用于磁盘阵列。例如,每个字节的第一位存储在磁盘0中,第二位存储在磁盘1中,如此下去,直到第8位存储在磁盘7中,纠错位存储在其余的磁盘中。

RAID 3级(RAID level 3)

RAID3级在RAID2级的基础上进行了改进。与内存系统不同,磁盘控制器能够检测一个扇区是否正确地读出,所以可以使用一个单一的奇偶校验位来检错和纠错。它的思想如下:如果一个扇区被破坏,系统能准确地知道是哪个扇区坏了,并且对扇区中的每一位,系统可以通过计算其他磁盘上对应扇区的对应位的奇偶值来推断出该位是1还是0。如果其余位的奇偶校验位等于存储的奇偶校验位,则丢失的位是0,反之为1。

RAID3级和RAID2级一样好,但是在额外磁盘的数目方面更加节省(它只有一张磁盘的开销),所以在实际中并不使用RAID2。

在这里插入图片描述
RAID3级与RAID1级相比有两个好处。

  • RAID3级对多张常规磁盘只需要一个奇偶校验磁盘,而RAID1级对每张磁盘都需要一张镜像磁盘,因此RAID3级减少了存储的开销;因为使用N道数据拆分的RAID3级对一个字节的读写散布在多张磁盘中,所以它使用N道数据拆分读写一个块的传输率是RAID1级的N倍
  • 因为每张磁盘都要参与每个I/O请求,所以RAID3级每秒钟支持的I/O作数较少。

RAID 4级(RAID level 4)

RAID4级(RAID level4),块交叉的奇偶校验组织结构。它像RAID0级一样使用块级拆分,此外在一张独立的磁盘上为其他N张磁盘上对应的块保留一个奇偶校验块。如果一张磁盘发生故障,可以使用奇偶校验块和其他磁盘上对应的块来恢复发生故障的磁盘上的块。

它读取一个块只访问一张磁盘,因此允许其他的请求在其他磁盘上执行。这样,每个访问操作的数据传输率较低,但可以并行地执行多个读操作,从而能产生较高的总I/O传输率。由于所有磁盘可以并行地读,因此读取大量数据的操作有很高的传输率。写入大量数据的操作也有很高的传输率,因为数据和奇偶校验位可以并行地写。

在这里插入图片描述

RAID 5 级(RAID level 5)

块交叉的分布奇偶校验位的组织结构。RAID5级在RAID4级的基础上进行了改进,将数据和奇偶校验位都分布到所有的N+1张磁盘中,而不是在N张磁盘上存储数据并在一张磁盘上存储奇偶校验位。在RAID5级中,所有磁盘都能参与对读请求的服务,而不像RAID4级中存储奇偶校验位的磁盘不参与读操作,所以RAID5级增加了在一段给定的时间中能处理的请求总数。对每个由N个逻辑磁盘块组成的集合来说,其中一张磁盘存储奇偶校验块,而其余的N张磁盘存储逻辑磁盘块。
在这里插入图片描述

RAID 6 级(RAID level 6)

P+Q冗余方案。它和RAID5级非常相似,但是存储了额外的冗余信息,以应对多张磁盘发生故障的情况。RAID6不使用奇偶校验的方法,而是使用像Reed Solomon 码之类的纠错码。这种方法与RAID5级对每4位数据存储1个奇偶校验位不同,它为每4位数据存储2位的冗余信息,这样系统可容忍两张磁盘发生故障。
在这里插入图片描述

RAID级别的选择

选择RAID级别应该考虑以下的因素:

  • 所需的额外磁盘存储带来的花费。
  • 在I/O操作数量方面的性能需求。
  • 磁盘故障时的性能。
  • 数据重建过程(即,故障磁盘上的数据在新磁盘上重建的过程)中的性能。

RAID0级用于数据安全性不是很重要的高性能应用。

因为RAID2级和RAID4级被RAID3级和RAID5级所包含,所以RAID级别的选择只限于在剩下的级别中进行。

比特级拆分(RAID3级)不如块级拆分(RAID5级),这是因为块级拆分对于大量数据的传输有与RAID3级同样好的数据传输率,同时对于小量数据的传输使用更少的磁盘。

对于小量数据传输,磁盘访问时间占主要地位,所以并行读取并没有带来好处。事实上,对于小量数据传输,RAID3级可能比RAID5级的性能更差,这是由于只有当所有磁盘上的相关扇区都读出后传输才算完成,因此采用RAID3级的磁盘阵列的平均延迟变得非常接近於单张磁盘在最坏情况下的延迟,从而抵消了其较高传输速率的长处。

当前,许多RAID的实现并不支持RAID6级,但是RAID6级提供比RAID5级更高的可靠性,可以用于数据安全十分重要的应用。

在RAID1级和RAID5级中做出选择十分困难。由于RAID1级提供最好的写操作的性能,因此在例如数据库系统日志文件的存储这样的应用中使用广泛。RAID5级与RAID1级相比具有较低的存储负载,但写操作需要更高的时间开销。对于经常进行读操作而很少进行写操作的应用,RAID5级是首选。

硬件问题

选择RAID实现要考虑的另一个因素在硬件层上。RAID可以在不改变硬件层,只修改软件的基础上实现,这样的RAID称为软件RAID(software RAID)。然而,建立支持RAID的专用硬件也会带来下面所介绍的很大的好处。具有专用硬件支持的系统称为**硬件 RAID(hardware RAID)**系统。

硬件RAID实现能够使用非易失性RAM在需要执行的写操作执行之前记录它们。如果发生电源故障,在系统恢复时,它可以从非易失性RAM中获得有关未完成的写操作的信息,并完成它们。如果没有这种硬件支持,就需要做一些额外的工作,检测在电源故障前只有部分写人的块。

为了尽量减少数据丢失的可能,良好的RAID控制器会进行擦洗(scrubbing),也就是说,在磁盘空闲时期,对每张磁盘的每一个扇区进行读取,如果发现某个扇区无法读取,则数据从RAID组织的其余磁盘中进行恢复,并写回到扇区中。(如果物理扇区损坏,磁盘控制器将逻辑扇区地址重新映射到磁盘上其他的物理扇区地址。)

一些硬件RAID实现允许热交换(hot swapping),就是在不切断电源的情况下将出错磁盘用新的磁盘替换。由于磁盘的替换不需要等待系统关闭这段时间,因此热交换减少了平均恢复时间。事实上,现在的许多关键系统都以24×7的时间表运行,即:一天运行24小时,一周运行7天。因而没有时间关闭系统和替换故障磁盘。进一步而言,许多RAID实现给每一个磁盘阵列(或一个磁盘阵列集)分配一张空闲磁盘。当系统中有磁盘发生了故障,空闲磁盘会立即代替故障磁盘工作。这样可以显著降低平均修复时间,减小数据丢失的机会。可以从容地替换掉故障磁盘。

第三级存储

光盘

DVD-5格式的光盘可以存储4.7GB的数据(在一个记录层),而DVD-9格式的光盘可以存储8.5GB的数据(在两个记录层)。在光盘的两面都存储就具有更大的容量;如,作为DVD-5格式和DVD-9格式的双面存储版本,DVD-10格式和DVD-18格式分别可以存储9.4GB和17GB的数据。蓝光DVD格式具有275427\sim 54GB的更高的单碟存储容量。

由于CD和DVD驱动器的激光头组件更重,因此比一般的磁盘驱动器需要更长的寻道时间(通常是100毫秒)。虽然最快的CD和DVD驱动器转速和低档的磁盘驱动器转速接近,大约是每分钟3000转,但是仍比一般的磁盘驱动器转速慢。CD驱动器的旋转速度原来是和音频CD的标准一致,DVD驱动器的旋转速度原来是和DVD视频标准一致,但是,现在的驱动器旋转速度比标准速度高很多倍。

CD和DVD的数据传输率比磁盘的数据传输率要慢一些。目前的CD驱动器的读取速度大约是每秒363\sim 6MB,而DVD是每秒8208\sim20MB。与磁盘一样,光盘在外侧轨道存储的数据比内侧轨道要多。光盘的数据传输率用nxnx表示,意思是驱动器支持的传输速率是标准速率的n倍,现在常用的CD是50倍速,DVD是16倍速。

因为可记录一次的光盘(CD-R、DVD-R和DVD+R)容量大,比磁盘有更长的寿命,而且可以在远程存储和移除,所以适合于数据分发,尤其适合于数据的归档存储。因为它们不能重写,所以它们可用于存储不应更改的信息,比如审计追踪信息。可多次重写的版本(像CD-RW、DVD-RW、DVD+RW和DVD-RAM)也可用于数据归档。

磁带

尽管相对而言磁带的保存时间更长久些,并且能够存储大量的数据,但是它与磁盘和光盘相比速度较慢。更重要的是,磁带只能进行顺序存取。因此磁带不能提供辅助存储所需的随机访问,虽然在历史上,磁带是先于磁盘被作为辅助存储介质使用的。
磁带主要用于备份,存储不经常使用的数据,以及作为将数据从一个系统转到另一个系统的脱机介质。磁带还应用于存储大量数据,例如视频和图像数据,它们不需要迅速地访问,或者因为数据量太大以至于磁盘存储太昂贵。

当前磁带的容量也相差甚远,有几个GB的数字音频磁带(Digital Audio Tape,DAT)格式,1040GB10\sim 40GB的数字线性磁带(Digital Linear Tape,DLT)格式,100GB或者更高的UItrium格式,以及330GB的Ampex螺旋扫描(Ampex helical scan)磁带格式。数据传输率在每秒几到几十MB的数量级。

文件组织

一个数据库被映射到多个不同的文件,这些文件由底层的操作系统来维护。这些文件永久地存在于磁盘上。一个文件(file)在逻辑上组织成为记录的一个序列。这些记录映射到磁盘块上。因为文件由操作系统作为一种基本结构提供,所以我们将假定作为基础的文件系统是存在的。我们需要考虑用文件表示逻辑数据模型的不同方式。
每个文件分成定长的存储单元,称为块(block)。块是存储分配和数据传输的基本单元。大多数数据库默认使用484\sim 8KB的块大小,但是当创建数据库实例时,许多数据库允许指定块大小。更大的块在一些数据库应用中是很有用的。

在关系数据库中,不同关系的元组通常具有不同的大小。把数据库映射到文件的一种方法是使用多个文件,在任意一个文件中只存储一个固定长度的记录。另一种选择是构造自己的文件,使之能够容纳多种长度的记录。然而,定长记录文件比变长记录文件更容易实现。很多用于定长记录文件的技术可以应用到变长的情况。因此,我们首先考虑定长记录文件,并且随后考虑变长记录存储。

定长记录

type 
	instructor=record 
	ID varchar(5); 
	name varchar(20); 
	dept_name varchar(20); 
	salary numeric(8,2); 
end

假设每个字符占1个字节,numeric(8,2)占8个字节。假设我们为每个属性ID、name和dept_name分配可以容纳的最大字节数,而不是分配可变的字节数。于是instuctor记录占53个字节。一个简单的方法是使用前53个字节来存储第一条记录,接下来的53个字节存储第二条记录,以此类推,然而这种简单的方法有两个问题:

  • 除非块的大小恰好是53的倍数(一般是不太可能的),否则一些记录会跨过块的边界,即一条记录的一部分存储在一个块中,而另一部分存储在另一个块中。于是,读写这样一条记录需要两次块访问。
  • 从这个结构中删除一条记录十分困难。删除的记录所占据的空间必须由文件中的其他记录来填充,或者我们必须用一种方法标记删除的记录使得它可以被忽略。

为了避免第一个问题,我们在一个块中只分配它能完整容纳下的最大的记录数(这个数字可以很容易通过块大小除以记录大小计算出来,并废弃小数部分)。每个块中余下的字节就不使用了。

当一条记录被删除时,我们可以把紧跟其后的记录移动到被删记录先前占据的空间,依次类推,直到被删记录后面的每一条记录都向前做了移动。这种方法需要移动大量的记录。简单地将文件的最后一条记录移到被删记录所占据空间中可能更容易一些。但是移动记录以占据删除记录所释放空间的做法是很不理想的。

在文件的开始处,我们分配一定数量的字节作为文件头(file header)。文件头将包含有关文件的各种信息。到目前为止,我们需要在文件头中存储的只有内容被删除的第一个记录的地址。我们用这第一个记录来存储第二个可用记录的地址,依次类推。我们可以直观地把这些存储的地址看作指针,因为它们指向一个记录的位置。于是,被删除的记录形成了一条链表,经常称为空闲列表(free list)

变长记录

变长记录以下面几种方式出现在数据库系统中:

  • 多种记录类型在一个文件中存储。
  • 允许一个或多个字段是变长的记录类型。
  • 允许可重复字段的记录类型,例如数组或多重集合。

实现变长记录存在不同的技术,任何这样的技术都必须解决两个不同的问题:

  • 如何描述一条记录,使得单个属性可以轻松地抽取。
  • 在块中如何存储变长记录,使得块中的记录可以轻松地抽取。

一条有变长度属性的记录表示通常具有两个部分:初始部分是定长属性,接下来是变长属性。对于定长属性,如数字值、日期或定长字符串,分配存储它们的值所需的字节数。对于变长属性,如varchar类型,在记录的初始部分中表示为一个对(偏移量,长度)值,其中偏移量表示在记录中该属性的数据开始的位置,长度表示变长属性的字节长度。在记录的初始定长部分之后,这些属性的值是连续存储的。因此,无论是定长还是变长,记录初始部分存储有关每个属性的固定长度的信息。
在这里插入图片描述

这个图也说明了空位图(null bitmap) 的使用,它用来表示记录的哪个属性是空值。在这个特定的记录中,如果salary是空值,该位图的第4位将置1,存储在121912\sim 19字节的salary值将被忽略。由于记录有4个属性,尽管更多属性需要更多字节,但该记录的空位图只占用1个字节。在一些表示中,空位图存储在记录的开头,并且对于空属性不存储数据(值或偏移量/长度)。这种表示以抽取记录属性的额外工作为代价来节省存储空间。对于记录拥有大量字段,并且大多数都是空的特定应用,这样的表示特别有用。
在这里插入图片描述

我们接下来处理在块中存储变长记录的问题,分槽的页结构(slotted-page structure) 一般用于在块中组织记录,每个块的开始处有一个块头,其中包含以下信息:

  1. 块头中记录条目的个数。
  2. 块中空闲空间的末尾处。
  3. 一个由包含记录位置和大小的记录条目组成的数组。

实际记录从块的尾部开始连续排列。块中空闲空间是连续的,在块头数组的最后一个条目和第一条记录之间。如果插入一条记录,在空闲空间的尾部给这条记录分配空间,并且将包含这条记录大小和位置的条目添加到块头中。

如果一条记录被删除,它所占用的空间被释放,并且它的条目被设置成被删除状态(例如这条记录的大小被设置为-1)。此外,块中在被删除记录之前的记录将被移动,使得由删除而产生的空闲空间被重用,并且所有空闲空间仍然存在于块头数组的最后一个条目和第一条记录之间。块头中的空闲空间末尾指针也要做适当修改。只要块中有空间,使用类似的技术可以使记录增长或缩短。移动记录的代价并不高,因为块的大小是有限制的:典型的值为484\sim 8KB。

大多数关系数据库限制记录不大于一个块的大小以简化缓冲区管理和空闲空间管理。大对象常常存储到一个特殊文件(或文件的集合)中而不是与记录的其他(短)属性存储在一起。然后一个指向该对象的(逻辑)指针存储到包含该大对象的记录中。大对象常常表示我们的B+B^{+}树文件组织。B+B^{+}树文件组织允许我们读取一个完整的对象,或对象中指定的字节范围,以及插入和删除对象的部分。

文件中记录的组织

文件中组织记录的几种可能的方法:

  • 堆文件组织(heap file organization)。一条记录可以放在文件中的任何地方,只要那个地方有空间存放这条记录。记录是没有顺序的。通常每个关系使用一个单独的文件。

  • 顺序文件组织(sequential file organization)。记录根据其“搜索码”的值顺序存储

  • 散列文件组织(hashing file organization)。在每条记录的某些属性上计算一个散列函数。散列函数的结果确定了记录应放到文件的哪个块中。

通常,每个关系的记录用一个单独的文件存储。但是在**多表聚簇文件组织(multitable clustering file organization)**中,几个不同关系的记录存储在同一个文件中。而且,不同关系的相关记录存储在相同的块中,于是一个I/O操作可以从所有关系中取到相关的记录。

顺序文件组织

顺序文件(sequential file) 是为了高效处理按某个搜索码的顺序排序的记录而设计的。搜索码(search key) 是任何一个属性或者属性的集合。它没有 必要是主码,甚至也无须是超码。

然而,在插入和删除记录时维护记录的物理顺序是十分困难的,因为一次单独的插入或删除操作导致移动很多记录是代价很高的。我们可以按照前面看到的那样,使用指针链表来管理删除。对插入操作,应用如下规则:

  1. 在文件中定位按搜索码顺序处于待插入记录之前的那条记录。
  2. 如果这条记录所在的块中有一条空闲记录,就在这里插入新的记录。

多表聚簇文件组织

很多关系数据库系统将每个关系存储在单独的文件中,以便它们可以利用操作系统所提供的文件系统的所有好处。通常,关系的元组可以表示成定长记录。因此,关系可以映射到一个简单的文件结构上。关系数据库系统的这种简单实现非常适合于廉价的数据库实现,例如,嵌人式系统和便携式设备中的数据库实现。在这种系统中,数据库的规模很小,因此复杂的文件结构不会带来什么好处。而且,在这样的环境中,必须使数据库系统目标代码总量非常小。简单的文件结构可以减少实现这个系统的代码量。

然而,很多大型数据库系统在文件管理方面并不直接依赖于下层的操作系统,而是让操作系统分配给数据库系统一个大的操作系统文件。数据库系统把所有关系存储在这个文件中,并且自己管理这个文件。

多表聚簇文件组织(multitable clustering file organization) 是一种在每一块中存储两个或者更多个关系的相关记录的文件结构,如图10-14所示。这样的文件组织允许我们使用一次块的读操作来读取满足连接条件的记录。因此,我们可以更高效地处理这种特殊的查询。

数据字典存储

关于关系的关系模式和其他元数据存储在称为数据字典(data dictionary)系统目录(system catalog) 的结构中。系统必须存储的信息类型有:

  • 关系的名字。
  • 每个关系中属性的名字。
  • 属性的域和长度。
  • 在数据库上定义的视图的名字和这些视图的定义。
  • 完整性约束(例如,码约束)。

此外,很多系统为系统的用户保存下列效据:

  • 授权用户的名字。
  • 关于用户的授权和账户信息。
  • 用于认证用户的密码或其他信息。

数据库可能还会存储关于关系的统计数据和描述数据。例如

  • 每个关系中元组的总数。
  • 每个关系所使用的存储方法(例如,聚簇或非聚簇)。

数据字典也会记录关系的存储组织(顺序、散列或堆),和每个关系的存储位置:

  • 如果关系存储在操作系统文件中,数据字典将会记录包含每个关系的文件名。
  • 如果数据库把所有关系存储在一个文件中,数据字典可能将包含每个关系中记录的块记在如链表这样的数据结构中。

数据库缓冲区

数据库系统的一个主要目标就是尽量减少磁盘和存储器之间传输的块数目。减少磁盘访问次数的一种方法是在主存储器中保留尽可能多的块。这样做的目标是最大化要访问的块已经在主存储器中的机率,这样就不再需要访问磁盘。

缓冲区(buffer)是主存储器中用于存储磁盘块的拷贝的那一部分。每个块总有一个拷贝存放在磁盘上,但是在磁盘上的拷贝可能比在缓冲区中的拷贝旧。负责缓冲区空间分配的子系统称为缓冲区管理器(buffer manager)

缓冲区管理器

当数据库系统中的程序需要磁盘上的块时,它向缓冲区管理器发出请求(即调用)。如果这个块已经在缓冲区中,缓冲区管理器将这个块在主存储器中的地址传给请求者。如果这个块不在缓冲区中,缓冲区管理器首先在缓冲区中为这个块分配空间,如果需要的话,会把其他块移出主存储器,为这个新块腾出空间。移出的块仅当它自从最近一次写回磁盘后被修改过才被写回磁盘。然后缓冲区管理器把请求的块从磁盘读入缓冲区,并将这个块在主存储器中的地址传给请求者。缓冲区管理器的内部动作对发出磁盘块请求的程序是透明的。

缓冲区管理器必须使用比典型的虚拟存储器管理策略更加复杂的技术:

  • 缓冲区替换策略(buffer replacement strategy)。当缓冲区中没有剩余空间时,在新块读入缓冲区之前,必须把一个块从缓冲区中移出。多数操作系统使用最近最少使用(Least Recently Used,LRU)策略,即最近访问最少的块被写回磁盘,并从缓冲区中移走。这种简单的方法可以加以改进以用于数据库应用。
  • 被钉住的块(pinned block)。为了使数据库系统能够从系统崩溃中恢复,限制一个块写回磁盘的时间是十分必要的。例如:当一个块上的更新操作正在进行时,大多数恢复系统不允许将该块写回磁盘。不允许写回磁盘的块称为被钉住的(pinned)块。尽管很多操作系统不提供对被钉住的块的支持,但是这个特性对可从崩溃中恢复的数据库系统十分重要。
  • 块的强制写出(forced output of block)。在某些情况下,尽管不需要一个块所占用的缓冲区空间,但必须把这个块写回磁盘。这样的写操作称为块的强制写出(forced output)。原因:简单地说,主存储器的内容,包括缓冲区的内容,在崩溃时将丢失,而磁盘上的数据一般在崩溃时得以保留。

缓冲区替换策略

对缓冲区中的块替换策略而言,目标是减少对磁盘的访问。对通用程序来说,精确预言哪个块将被访问是不可能的。因此,操作系统使用过去的块访问模式来预言未来的访问。通常我们假定最近访问过的块最有可能再一次被访问。因此,如果必须替换一个块,则替换最近访问最少的块。这种方法称为最近最少使用(Least Recently Used,LRU)块替换策略。

在操作系统中,LRU是一个可以接受的替换策略。然而,数据库系统能够比操作系统更准确地预测未来的访问模式。用户对数据库系统的请求包括若干步。通过查看执行用户请求所需操作的每一步,数据库系统通常可以预先确定哪些块将是需要的。因此,与依赖过去而预测将来的操作系统不同,数据库系统至少可以得到短期内的将来信息。

为了说明关于未来块访问的信息是如何使我们改进LRU策略的,考虑如下SOL查询处理:

select *
from instructor natural join departmernt

假设所选择的处理这个请求的策略下面的伪码程序给出

for each instructor 中的元组 i do
	for each department 中的元组 d do
		if i [dept_name]=d[dept_name]
		then begin
			令x为下列式子定义的元组:
			x[ID] :=i[ID]
			x[dept_name] :=i[dept_name]
			x[name] :=il name]
			x[building] :=d[building]
			x[budget] :=d[budget]
			将元组x包含进instructorI depurtment的结果中
		end
	end
end

假设该例子中的两个关系存储在不同的文件中。在这个例子中,我们可以看到,一旦instructor中的一个元组处理过,这个元组就不再需要了。因此一旦处理完instructor元组构成的一个完整的块,这个块就不再需要存储在主存储器中了,尽管它刚刚使用过。一旦instructor块中最后一个元组处理完毕,就应该命令缓冲区管理器释放这个块所占用的空间。这个缓冲区管理策略称为立即丢弃(loss immediate)策略

上述过程中块替换的最优策略是最近最常使用(Most Recently Used,MRU)策略。如果必须从缓冲区中移除一个department块,MRU策略将选择最近最常使用的块(当块被使用时不能被替换)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章