如何在Postgres中对文件系统和数据库进行原子操作?

时间:2019-01-23 09:38:31

标签: database postgresql file filesystems atomic

我认为以下应该是一种非常常见的模式:

  • 数据库用于存储文件路径
  • 文件本身存储在文件系统中

说我们要修改文件路径时可能会发生问题:我们都需要修改 数据库文件路径并在文件系统中移动文件。重要的是“原子地”完成。确实,当我们进行修改时,另一个过程可能会尝试读取datadase中的文件路径,然后尝试访问文件系统中的文件。我们应该确保元组

(“文件路径”,“实际文件位置”)

始终保持一致。

是否存在使用Postgres / Linux的规范/简单方法?

1 个答案:

答案 0 :(得分:1)

数据库的主要功能之一是流程始终如一地看到它。这也意味着不同的客户端会看到不同的数据库状态。

这意味着,当您更正数据库中的文件路径并提交更改时,在提交之前启动的任何事务都可以在提交之后的一段时间内看到旧路径。

因此,实际上要确保没有人会尝试读取旧文件路径,您必须等到提交结束之前的所有事务为止。这可能需要几毫秒的时间,在极端情况下甚至可能需要几天。如果您有

我将尝试实现以下方案(伪代码):

sql("begin")
os.hardlink(old_path, new_path)
sql("update files set path=? where path=?, new_path, old_path)
sql("insert into files_to_clean values (?, txid_current())", old_path)
sql("commit")

if random()<CLEANUP_PROBABILITY:
  sql("begin")
  for delete_path in sql("
    delete from files_to_clean
    where txid<txid_snapshot_xmin(txid_current_snapshot())
    returning path skip locked
  "):
    os.delete(delete_path)
  sql("commit")