部分写(Partial writes)情形: 假设数据库块(或page)大小设置为16kb,操作系统层IO的最小单位为4kb。 首先,数据库的commit操作可以确保日志(redo/wal)已经落盘,和数据文件是否落盘无关。 当16kb大小的数据块落盘时,如果在刚完成4kb写入的时候发生了crash,那么这个数据块实际上是corruption的; 但是在日志中,当前的事务已经正常完成。 这就是partial writes的情况。 以下是三种数据库对此种情况的处理手段。 | ||
Oracle | MySQL | PostgreSQL |
---|---|---|
官方文档未提及相关内容 | innodb_doublewrite | |
1 | on | |
doublewrite buffer是在system表空间中的一块存储区域。 在pages写到他们正确的数据文件之前,它们要先从InnoDB buffer pool中flush到doublewrite buffer中。 所以,如果发生了partial writes,InnoDB可以从doublewrite buffer中找到完整的pages,以进行实例恢复。 虽然写了两次,但是性能不会下降一半。因为doublewrite buffer写操作是一个大的顺序IO,只执行一次fsync()。 | 对于每一个page,在检查点之后的第一次修改时,将整个page都写入到WAL中。 这样的话,如果发生了partial writes,可以从WAL中得到完整的page,以进行实例恢复。 这样做的劣势是会增大WAL的大小,降低WAL大小的方式是增大检查点的触发时间间隔。 |