【问题标题】:Deleting files and corresponding entries from database从数据库中删除文件和相应的条目
【发布时间】:2010-12-16 21:39:32
【问题描述】:
我有一个处理文件管理的网站。用户可以上传文件、添加描述、编辑和删除。这种场景的最佳实践是什么?
我将文件存储在文件系统中。
我应该如何处理删除文件?在这种情况下,我必须删除实体:数据库中的文件和条目。第一种情况是我删除文件,如果没有错误,我从数据库中删除条目。但是,如果无法删除数据库中的条目,我将无法恢复我的文件。所以第二种情况是相反的:首先从数据库中输入,然后是文件。但是同样,当文件无法删除时,我无法恢复数据库中的条目。哪种方法更好?还是有其他的?
我认为这个问题对于所有 Web 编程语言和所有数据库引擎都是通用的。但是假设我有 MySQL 和 PHP,所以从数据库存储过程级别删除文件是不可能的。
【问题讨论】:
标签:
database
web-applications
file
【解决方案1】:
Vista 引入了事务性 NTFS,它允许您将文件系统操作与数据库操作一起包装到一个事务中,如果其中一个失败,该事务可以回滚。这不在 .Net 3.5 中,我不知道它是否会成为 .Net 4.0 的一部分,但有证据表明它现在需要一些腿部工作,即通过使用 Win32 调用(请参阅this article)。
我对 PHP 中的事务管理一无所知。
【解决方案2】:
这是一种可能性。
您可以先将文件移动到“已删除”文件夹,然后删除数据库中的条目。如果失败,请从“已删除”文件夹中恢复文件。
要删除“已删除”文件夹中的文件,请在删除数据库中的条目后立即执行此操作。如果失败,那么您最终会在“已删除”文件夹中留下孤立文件...根据您的要求,这可能不是问题。
另一种选择是调用(可能在 SessionEnd 或服务上)来清理数据库。
【解决方案3】:
通常有一个垃圾收集阶段,实际上您的数据库有类似的东西,称为“事务日志”,它可以用来回退或播放事务。
在删除文件的情况下,您将有一个定期运行的清理过程(可能是在发生崩溃时手动运行,或者每隔一段时间自动运行一次),它将磁盘上的内容与数据库中的内容进行比较并做出适当的修正。
为了使任何操作成为“原子”操作,必须有一种在发生崩溃时进行清理的方法。关键是找到一种持续清理的方法,这样“原子”操作中任何一点的故障都不会导致系统无法恢复。
【解决方案4】:
我个人会确保数据库获得优先级,因为它对系统来说更为基础。所以我会确保数据库行被删除,然后删除文件。如果文件删除失败,我会让它静默失败。然后,如果所有文件都有对应的 db,我将使用 cronjob 检查所有文件,如果没有,则将它们标记为删除,以便系统保持干净和连贯。
【解决方案5】:
我通常发现最好使用soft deletes,尤其是对于数据库中的数据。
这样做,您只需将文件放在新位置以将其表示为已删除,并将数据库中的条目标记为已删除。这样,如果由于某种原因数据库删除失败,您仍然可以使用该文件。
将文件放在新位置后,您可以将该位置备份到另一个位置,或者设置一些东西以定期从该位置删除项目。