无论是CPU芯片,操作系统还是Web服务器等方方面面,都会使用一个非常重要的技术:缓存。CPU和内存之间的高速缓存,内存和外设之间的系统缓存,局域网与外部网络之间的Web缓存服务器。。。这些“缓存”的具体实现方式各不相同,但原理和目的都是一样的:在高速设备上预存数据以期直接通过高速设备完成读写而避免低速设备上的数据传输,从而提高系统性能。
缓冲池(BufferPool)
对于数据库管这种对性能要求极高的系统而言,缓存自然也是不可少的。数据库中的缓存称为缓冲池,缓冲池存在的唯一目的就是提高数据库系统性能。
缓冲池本质上是分配给数据库管理器管理的一块内存空间,用于读写数据页。(包括表行和索引数据页。内存中表行数据页称为缓存表)由于从内存访问数据比从磁盘访问数据快得多(访问磁盘是典型的I/O操作,一次I/O大概耗时0.0125S),通过将部分常用或者需要预取的数据存放在缓冲池以便系统直接访问和操作可以减少磁盘I/O,合理的缓冲池空间和好的缓冲池页面替换算法(提高命中率)可以大大提高数据库系统的性能。
注意分配给DB2的内存空间不仅仅是缓冲池,还包括包缓存空间,日志缓存空间等等一些其他的内存空间,其中缓冲池占了DB2内存的大部分。
创建数据库时,会创建一个名为 IBMDEFAULTBP 的缺省缓冲池,所有的表空间都共享该缓冲池。可以使用 CREATE BUFFERPOOL 语句添加更多的缓冲池。缓冲池的缺省大小是 BUFFPAGE 数据库配置参数所指定的大小,但是可以通过在 CREATE BUFFERPOOL 命令中指定 SIZE 关键字来覆盖该缺省值。足够的缓冲池大小是数据库拥有良好性能的关键所在,因为它可以减少磁盘 I/O 这一最耗时的操作。大型缓冲池还会对查询优化产生影响,因为更多的工作可在内存中完成。
缓冲池大概实现
DB2缓冲池的结构和具体实现是非常复杂的,只知道一个大概的实现过程,其实也跟操作系统缓存差不多。
首次访问数据库表中的数据行时,由于缓冲池内没有数据页,数据库管理器会将磁盘上相应的数据页读入缓冲池中,每当向缓冲池添加新页时,都会为该页生成一个页面描述符(BPD)以标识该页并指明该页状态,描述符被存放在Database Heap中,删除页时会将其描述符一并删除,页面状态发生变化后会更新该页描述符。
对缓冲池中数据页进行操作时会根据操作类型为数据添加一个共享锁或排它锁以保证数据的同步,添加的锁被存放在Locklist中统一管理。同时将操作的SQL语句存储到包缓存(package Cache)中,根据包缓存的数据在日志缓冲区(Log Cache)中生成日志文件。当操作提交时,如果数据页没有被修改(干净页),则无需向磁盘回写数据页,如果数据页被修改(脏页),则需要将修改后的数据页回写到磁盘,替换原有页,,该脏页变成干净页。同时立即将相应的日志文件写入磁盘,以保证发生断电等突发事故时保证能够利用磁盘上的日志文件进行回滚(Undo)或重做(Redo)。【未提交确认的修改会回滚,已提交确认的修改会重做】
操作提交后,数据页所持有的共享锁或排它锁也相应解除。所有这些数据页在操作提交后都会继续保留在缓冲池中。当下次进行访问时,如果缓冲池中存在需要访问的数据页(命中),则直接对该页进行操作,并同样进行日志记录和数据页回写等操作。如果缓冲池中不存在需要访问的数据页(未命中),则需要先从磁盘将数据页读入缓冲池,重复以上过程。
如果需要将新的数据页从磁盘读入缓冲池,而缓冲池正好已经满了该怎么办呢?这个时候就要根据页面替换算法,选择将某些页从缓冲池删除以容纳新页。页面替换算法有很多种,DB2使用的是一种类似于最近最少使用(LRU)算法的时钟算法。
缓冲池和表空间的关系
一个缓冲池是与单个数据库相关联的,可以被多个表空间使用。一个数据库可以有多个缓冲池。数据库创建时会生成一个名为IBMDEFAULTBP的默认缓冲池。当考虑将缓冲池用于一个或多个表空间时,必须保证表空间页大小和缓冲池页大小对于缓冲池所“服务”的所有表空间而言都是一样的(和表空间一样,缓冲池中的页大小也分为4KB,8KB,16KB和32KB四种)。一个表空间只能使用一个缓冲池。如图:
基于块的缓冲池
DB2允许留出缓冲池的一部分(最高98%)用于基于块的预取操作(块预取:如果多个同区段的页面由于某个单个请求而被读取,就会发生块读取),基于块的I/O可以通过将块(多个页面)读入相邻的内存区而不是将它们分散装入单独的页来提高预取操作的效率。每个缓冲池的块大小必须相同,并且有BLOCKSIZE参数控制,该值等于块的大小(页数),取值范围为2-256。默认为32。