SimpleDBM 组件分析 (二)
D Log Manager
WAL 提供恢复功能的基础,同时,对OLTP系统的性能有重大的影响,是系统中至关重要的一部分。
每条日志记录用LSN(Log Sequence Number)进行标识。LSN被专门设计,通过LSN可以迅速定位到指定的日志记录。LSN被设计为严格的升序,这对恢复来说,是个非常重要的特性。
Log Records 初始在内存中,在事务提交和checkpoint时,被flush到硬盘上。在系统崩溃时,有可能丢失未写入硬盘的日志。这不会引起什么问题,因为按照定义,这些日志记录必须反映为完成事务引起的数据库的改变。此外,WAL协议保证这样的日志记录不包含已存入数据库的改变的日志。
Write Ahead Log Protocol
1、事务所引起的所有改动都要记录在日志中,在事务提交完成之前,所有的这些记录必须被写入硬盘;
2、一个数据库的缓冲页直到被记入日志后才能发生修改。直到缓冲页对应的日志被写入磁盘之后,该缓冲页才会存入磁盘;
3、当缓冲页被修改和日志被更新的时候,在也上必须加上互斥锁,以保证改动被记录到日志中的顺序与它发生的顺序是一致的。
以上规则的结果:
1、如果一条日志记录未被存入硬盘,则它可以被忽略,因为该日志中包含的改动一定属于未提交的事务。此外,这样的日志不能反映已持久化在数据库中的改动;
2、日志记录按顺序记录系统的改动。加锁协议(latch protocol)保证如果有对于同一页改动的两条日志记录,则两条记录的顺序反映对页发生改变的顺序。
WAL 特点:
改动写到硬盘上是随机的,在硬盘的不同地方,但是,日志记录则要保证顺序,在事务提交时,仅保证log全部写入硬盘。这样Log就相当于将随机写入转化为顺序写入,因此大幅提高性能。
Log Manager没有对日志记录做任何的假设,它并未指明日志记录的格式。
SimpleDBM的日志实现:
SimpleDBM 维护独立于Log文件的控制信息,并且这些控制信息具有多重拷贝。
SimpleDBM有3个Log Group,每个Log Group中含有8个Log file。
在log 有确定集合的在线日志记录(online log file)和 动态集合的归档日志记录(archived log file)。
日志文件的计数从1开始,这个顺序号叫做LogIndex。实际的log file与逻辑的log file还有所不同。实际的log file按其logindex的编号,而逻辑的log file则不指定哪几个。物理log file在任何的时间点,在线日志文件的物理集合总是包含一组逻辑的日志文件。
关于log文件的写:
当一条日志记录写出到硬盘,它被写到在线日志文件上,如果存在多个Log Group,则这条记录会写向每个Log Group。写操作顺序完成,保证有一个写失败时,损害只限制在一个Log Group上(保证信息不丢失,还有其他的Log Group做备份)。由于这种工作方式,当有多于一个Log Group时,会降低写出日志的速率。因此,用硬件的磁盘镜像要比使用写多个Log Group的方式更好。
新日志记录被创建时,被存在缓存中,只有是因为Client的写出请求,或者是缓存的阶段性flush事件才会将日志记录写到日志文件中。
在flush的时期,系统会决定使用哪个日志文件。有个Current Log File的概念,即写操作想要定位到的文件。如果当前的log file已满,将它放入归档的队列,然后切换日志文件。直到一个在线日志文件被归档完毕,它的物理文件不可以再被重用。一个独立的归档线程监视归档请求并在后台扫描日志文件。
在任一时间点,只有一个flush操作被执行,同理,任一时间点只有一个归档操作被执行。但是多客户端允许并发地插入和读log文件,即使flush和archive正在进行,以下情况除外:
1、当系统为了一个插入操作,使用过量内存空间时,该日志插入操作无法执行。这种情况下,必须等待内存释放,为保证最大化的并发,内存计算是近似的;
2、当所有的在线日志记录已满时,日志flush无法完成,在这种情况下,flush操作必须等待至少一个文件被归档(archived);
3、在读一条日志记录时,如果该在线日志文件包含正在归档的记录,读者必须等待日志文件状态的改变,之后才能处理读操作,相反,当读操作正在进行,归档线程必须等读完了,才能改变log file的状态。
如果归档模式开启,日志文件会在重用之前归档,否则,若该日志不再被使用,则这些文件将会被直接重用(这个还没有实现),默认的归档模式开启。