如何保证跨两个数据库(文件系统和您的RDBMS)的原子性?

时间:2010-03-26 18:40:08

标签: database-design

我正在开发一个在线文件管理项目。我们在其中存储对数据库(sql server)的引用和文件系统上的文件数据;。我们面临着文件系统和数据库之间协调的问题当我们上传文件时,如果要删除文件,首先我们在数据库中创建引用或在文件系统上存储文件;;问题是如果先在数据库中创建引用然后存储文件文件system.bur在文件系统上存储文件时发生任何类型的错误。然后在数据库中创建该文件的引用,但文件系统上没有文件数据;请给我一些解决方法如何处理这种情况;我非常需要它;; 原因是什么?

3 个答案:

答案 0 :(得分:1)

这实际上比你想象的要容易一些。

首先,你需要决定“单一的事实来源”。

也就是说,文件系统或数据库在任何给定的时间点都是正确的,哪一个是它?

这样做的原因是它可以更容易地解决冲突。

您应该假设数据库是您的Source,并且文件系统是数据库的阴影。这似乎是反直觉的,因为如果数据库不在文件系统中,那么数据库中如何存在。显然它不能。但是,基本上,如果文件不在数据库中,那么“它就不存在”了。因此,文件系统反映了DB的状态,而不是反过来。

鉴于这些假设,您最终会得到这些冲突解决规则。

对于任何给定的文件:

File Exists    DB Entry Exists   Action
   Yes            Yes            No action, normal state
   No             Yes            Error -- missing file, "should never happen"
   No             No             No action, normal state
   Yes            No             Delete the file, but no error.

上传文件时,存在灰色区域 - 即文件上传但尚未得到DB确认。

解决此问题的方法是,您需要以分段模式上传文件。

执行此操作的简单方法是将文件上载到其他目录,但在同一物理文件系统上,或使用临时文件名将其上载到最终位置。无论哪种方式,文件都可以通过它的名称或位置轻松识别为“正在处理”。

您希望在同一文件系统上“暂存”此文件有两个原因。一,磁盘空间。如果在上传时磁盘没有填满,那么你就知道它将适合它的最终安放位置(它已经“保留”了空间)。二,当你最终放置文件时,该操作必须是原子的。在同一文件系统上的文件重命名操作在现代文件系统上是原子的。基本上,即使它不可避免地“覆盖”现有文件(原始文件在重命名操作期间被删除),也不能将文件“重命名为一半”。

上演后,您的操作将变为:

Start DB transaction
Rename file
Add DB record
Commit transaction

如果重命名文件操作失败,则中止并回滚数据库事务,即条目。如果重命名成功,则DB失败?然后你有上面列出的#4州。重试上传,直到成功为止。

要删除文件,请执行以下操作:

Start DB Transaction
Delete DB record
Commit transaction
Delete file from file system

如果数据库删除失败,则不删除该文件。如果数据库删除成功,文件删除失败,那么我们将返回状态#4。

最后,你有一个收割者流程,定期(每天,每周,无论如何)将数据库与文件系统进行比较,删除数据库中没有的任何文件。由于数据库是“单一事实来源”,两个商店最终会同步。

如果缺少具有DB记录的文件,则会出现“数据损坏”。不要那样做。这是一个错误,或者有人走过你的文件系统。

上传过程的重试特性和删除过程的快速失败为您提供了伪两阶段提交过程,可以轻松检查哪些是对错,并且易于纠正到正确的状态。

答案 1 :(得分:0)

您需要一个支持数据库和文件系统事务的事务协调器,以使two phase commit像这样工作。

您没有指定数据库,编程语言或平台,所以这是我可以回答的问题。

答案 2 :(得分:0)

在Windows Vista,Windows Server 2008或更高版本的Windows操作系统中,您可以use transactions to govern access to the NTFS

使用此工具,如果您要在.NET中编程,则可以使用System.Transactions命名空间作为一个原子单元执行对文件系统的更新以及对数据库的更新。

我不知道其他操作系统上是否有事务性文件系统。这并不意味着它们不存在。