原子写入多个文件

时间:2012-08-18 22:25:07

标签: python database synchronization filesystems atomicity

假设我有一组文件。如何确保写入所有这些文件是原子的。

我考虑过写入临时文件,只有在写入成功后,才能对每个文件执行原子重命名。但是,一次重命名所有文件不是原子的。如果我们想要附加到这些文件,这也不会扩展到非常大的文件。

相反,我考虑过实施交易,但后来这个项目正在成为一个项目。我意识到这几乎是关于实现一个迷你数据库。

你会怎么用Python做的?

d = FileWriter.open(['file1', 'file2'], 'wb+')
d.write('add hello world to files')
d.close()

如果不成功,请确保d.write是原子的或至少回滚到原始文件。

4 个答案:

答案 0 :(得分:5)

这就是我的想法。首先确保open是同步的,然后执行以下操作:

  1. 写入临时文件:file1~,file2~和特殊文件成功〜(必须先写入)。
  2. 成功写入后,删除文件成功〜。
  3. 将文件重命名为file1和file2。
  4. 如果出现问题:

    1. 检查是否存在成功。
    2. 如果确实如此,请不要打扰修理。由于文件未更新(无重命名),因此隐式执行了回滚。
    3. 如果成功〜不存在,写作和重命名后事情就会破裂。在这种情况下,修复就像将filex~重命名为filex一样简单。

答案 1 :(得分:1)

您的要求在其当前声明中是如此通用,以至于唯一合理的答案是操作系统级别的支持是必要的,而且它甚至不再是严格的Python相关问题。查看有关交易文件系统的内容,例如herehere。关于迄今为止提出的解决方案的一小段摘录:

  

如果没有文件系统事务,确保多个文件系统操作的一致性即使不是不可能,也很困难。文件锁定可以用作单个文件的并发控制机制,但它通常不保护目录结构或文件元数据。例如,文件锁定无法阻止符号链接上的TOCTTOU竞争条件。文件锁定也无法自动回滚失败的操作,例如软件升级;这需要原子性。

所以我建议重新考虑你的问题(也许也是你的问题?)并更详细地分析你的要求。最重要的是,您需要的保证越少,您可以找到更简单的解决方案。也许你可以使用像文件锁定这样简单的东西,或者你会发现需要一个数据库。

说到这一点,如果您正在考虑文件系统,因为您的架构的组件需要访问文件,您是否考虑过将FUSE作为构建文件的方法在常规数据库之上的类似文件系统的外观?使用python-fuse是一件轻而易举的事。

答案 2 :(得分:0)

您可以尝试使用flock来实现目标。它可以在fcntl.flock的python中实现。请注意,这只是顾问衡量指标。为了真正保证你想要的东西,你应该尝试使用支持严格锁定的数据库或文件系统/内核。

答案 3 :(得分:0)

数据库管理系统通常只使用一个预写日志文件或自定义文件系统的原因是,通常的文件系统在确保原子性或执行顺序方面确实很糟糕。

它们完全针对一致性和性能进行了优化。

因此,除非您使用专门的文件系统创建分区或图像文件,否则只能写入单个文件的写入顺序。

但是,您可以在每次写入多个文件时写入事务编号。

并明确表示写入是否完整,例如带有开头/结尾标记的xml或json样式块,如< element> ...< / element>或{...},& c。

然后,您的代码可以轻松检测多个文件中的任何间隙,并确定崩溃后的最后一致状态。

为了避免崩溃后的最后一致状态,因为某些写入已经在缓存中等待了几分钟,因此任何这些方法都可以与sync / fsync结合使用。

使用sync / fsync也可以使事务提交成为可能,即保证到目前为止所有内容都是至少从文件系统的角度编写的。

然而,由于停电,您的存储系统可能仍会丢失最后一次写入,无论是硬盘还是带有内部缓存,NAS和SSD的SSD。 这些系统提供的保证可能会有很大差异,无论是使用文件系统还是使用传统的RDBMS进行存储,这都是所有方法都要考虑的挑战。

如果您正在写入内置硬盘或SSD,使用UPS绝对是一个很好的补充,特别是如果您在USP发出信号表明其关闭时以受控方式关闭系统时间这样做^^