文件+数据库事务安全

时间:2010-06-24 06:03:49

标签: php mysql transactions

我有一个MySQL表,它基本上用作文件索引。每条记录的主键也是我的Web主机上目录中文件的名称。

当用户想要从系统中删除文件时,我想确保某种交易的安全性,即如果在删除文件时出现问题则不删除记录,如果由于某种原因数据库服务器死了文件不会被删除。发生的任何事件都不太可能,但如果有任何问题的可能性,我想要阻止它。

不幸的是,我完全不知道如何实现这一点。我是否需要找出不太可能失败的问题,并简单地假设它永远不会失败?是否有任何已知的最佳实践?

哦,这是踢球者 - 我的网络主机只支持MyISAM表,所以没有MySQL交易。

如果重要,我使用PHP作为我的服务器端脚本语言。

3 个答案:

答案 0 :(得分:3)

在这种情况下,我认为我会使用逻辑删除机制,即使记录仍然存在于数据库中,记录也会被标记为已删除,并且该文件仍然存在于文件系统中。当逻辑删除时,我可能会将文件移动到新位置(想想“回收站”)并使用新位置和“逻辑删除”标记更新记录。

然后,稍后,您可以执行脱机清除操作,以物理方式删除标记为逻辑删除的文件和记录。

这降低了实时数据的风险。它稍微复杂化了SQL,但视图可能有效 - 重命名主表,然后创建一个与以前使用的主表同名的视图,但条件是消除逻辑删除的记录:

CREATE VIEW MainTable(...) AS
    SELECT * FROM RenamedTable WHERE DeleteFlag = 'N';

即使升级到提供MySQL事务的公司也不是一个很大的帮助。您需要一个事务管理器,它可以在文件系统和DBMS之间运行两阶段提交协议,这是非常重要的。

答案 1 :(得分:3)

文件是否通过UPDATE或DELETE行从数据库“删除”,问题是相同的 - 数据库+文件操作不是原子操作。 UPDATE或DELETE都不比另一个更安全,它们都是数据库中的事务,而文件操作则不是。

解决方案是,数据状态永远不会发生任何冲突。只有一个来源被认为是“真相”而另一个被认为是真相。这样,如果两者之间存在不一致,你就会知道“真相”是什么。实际上,从来没有“逻辑”不一致,只有磁盘上的物理伪像表现出的后果。

在大多数情况下,数据库更能代表真理。

这是真相表:

File Exists -- DB Record exists -- Truth
    Yes             No             File does not exist
    Yes             Yes            File does exist
    No              Yes            File does exist, but its in error.
    No              No             File does not exist

在操作上,这是如何工作的。

要创建文件,请将文件复制到最终目的地,然后在数据库中输入一个条目。

如果文件复制失败,则不更新数据库。 如果文件复制成功,但DB未更新,则文件“不存在”,因此返回第一步。 如果文件复制成功并且数据库更新成功,那么一切都是A-OK

要删除文件,请先更新数据库以显示文件已删除。 如果数据库更新成功,则删除实际文件。 如果数据库更新没有,则不要删除该文件。 如果文件删除失败,没问题 - 文件仍然被“删除”,因为数据库是这样说的。

如果您遵循工作流程,那么当数据库说它存在时,文件应该“丢失”。如果文件丢失,您将有一个未定义的状态,您需要解决该问题。但是,除非有人走在您的文件系统上,否则不会发生这种情况。

数据库交易有助于保持诚实。

有时候,正如Jonathan所提到的,你应该运行某种清理,同步过程以确保没有任何恶意文件。但即便如此,除文件空间外,这确实不是问题,特别是如果实际文件的文件名与原始文件名无关。 (即它们是合成文件名)这样你就不用担心覆盖等了。

答案 2 :(得分:2)

您可以在File表中创建一个Status列(或“is_active”列),其中包含两个值:0 = Active,1 = Deleted。

  • 当用户删除文件时,仅更改“状态”字段,文件保持不变。
  • 当用户浏览文件时,只显示Status = 0的文件。
  • 管理员可以查看/删除Status = 1的文件。