以原子方式修改磁盘上文件的内容-如何正确执行?

时间:2018-09-16 22:21:49

标签: database database-design acid

我正在研究如何对文件系统上的文件进行原子(持久)更新的几种可能性。我这样做是因为我想学习和理解它在数据库系统中的工作方式。一些假设:

  • 在任何给定时间只有一个进程访问文件(该进程“拥有”文件)。
  • 没有并发写入,可以对整个文件进行全局读/写锁定。
  • 文件是包含二进制数据(例如B树)的任意大文件(在文件系统允许的范围内)。
  • 仅用户级(不允许内核扩展)

到目前为止我学到的东西:

  • 基本上,所有操作系统都有一个后写缓冲区,用于保存文件修改,直到调用fsync()(或类似命令)将更改内容刷新到磁盘为止。

  • fsync()本身不是原子的,尤其是在涉及多个内存页面的情况下。

  • fsync()是一个相当昂贵的操作,过于昂贵,无法在每次提交时调用。

  • 数据库保留存储所有传入事务的预写日志(WAL)。每隔一定的时间间隔(WAL文件大小或计时器或...)应用更改并进行fsync()编辑。

  • 在执行查询时,需要考虑WAL中的所有更改,就像这些更改已经是主文件的一部分一样。由于当WAL变大(未建立索引)时,它可能变慢,因此希望尽早刷新WAL。大型WAL文件的成本与将更改刷新到主文件的成本之间似乎需要权衡。

  • 由于fsync()可能最终将半页写入磁盘(例如,在断电的情况下),因此WAL中的事务接触的所有内存页面也需要复制到WAL中,以便在重新引导系统时可以还原这些页面。 fsync()命令成功返回后,我们可以从WAL中删除条目。

我的问题:

  • 我到目前为止正确吗?

  • 使用mmap版本的文件而不是常规文件时,上述任何改变吗?

  • 在我看来,所有这些并不能真正“解决”问题,而只是减少了腐败的可能性。最后,WAL本身是一个文件,需要进行fsync()加密,这可能会失败。 WAL上的fsync()比数据文件中的fsync()便宜吗?

  • 我们是否在每次提交后立即执行fsync()?即使是我个人认为非常令人不安的高端数据库系统,例如PostGreSQL seem to do this periodically。如果在fsync()删除WAL文件之前关闭了计算机的电源,我们是否冒着完全丢失提交的风险?

  • 我们如何保护WAL文件以防止由于页面同步不完整而导致数据损坏? WAL的WAL?

任何与该问题有关的学习资源的链接(除了“读取数据库XY的源代码”之外)也将受到高度赞赏。

0 个答案:

没有答案