InnoDB的双写缓冲

时间:2021-08-06 07:33:02

    昨天看了InnoDB的双写缓冲,书上说的不太详细,网上也人云亦云。想了一段时间,终于有一些头绪。
    首先需要说一下为什么需要双写缓冲?由于InnoDB和操作系统的页大小不一致,InnoDB页大小一般为16k,操作系统页大小为4k,导致InnoDB回写dirty数据到操作系统中,一个页面需要写4次,写入过程出现问题无法保持原子性。写的过程如果崩溃或者断电,可能导致只有一部分写回到操作系统文件系统中,整个数据只是部分成功,其实数据是损坏的。
如果需要保证数据成功,又不采用双写缓冲,也有比较笨的办法,redo日志中记录整个变更的页数据,回写的时候从redo日志中拷贝页数据到文件系统中,这样会导致redo日志非常大,可能给系统性能带来很大问题。
采用双写缓冲,redo日志只需要记录很少的变更信息,原数据还是存在原来的文件系统中,写入到doublewrite buffer中时,根据redo日志和元数据信息计算得到新数据,先写入到doublewrite buffer中。如果这时系统崩溃,恢复以后InnoDB可以计算校验位,知道数据不正确,重新根据redo日志和元数据计算生成数据覆盖doublewrite buffer中的损坏数据。当doublewrite buffer中的数据全部成功写入以后,此时doublewrite buffer会将数据写入到文件系统中,如果此时系统崩溃,只需要遍历doublewrite buffer,重新将数据写入文件系统,覆盖损坏数据即可。
    由于书里和网上一直语焉不详,一直思考为什么需要doublewrite buffer,如果没有是不是也是可行的,答案是没有也可行,但是这样就需要redo日志记录所有变更的页数据,会导致redo日志特别大。如果redo日志只记录变化是否可行?这样会有问题,因为如果直接写入到文件系统中,如果数据损坏,原数据已经被覆盖,单独根据只含有变化信息的redo日志没法计算出新的正确数据。所以doublewrite buffer相当于承担存储中间状态的介质,这样可能会导致多一些IO,但是由于doublewrite buffer是顺序写入,应该影响不太大,数据正确性和redo日志大小得到控制,利大大大于弊。