Sql server 如果行过期,如何只允许对表进行一次更新/插入

Sql server 如果行过期,如何只允许对表进行一次更新/插入,sql-server,Sql Server,我有一个存储在磁盘上的文件,可以跨web场中的多个服务器访问该文件。此文件将根据数据库中的数据更改进行必要的更新。我有一个数据库表,其中存储了一行,其中包含该文件的URI和一些基于某些数据库表的哈希值。如果散列与各自的表不匹配,则需要重新生成文件并插入新行 如何使只有一个客户端重新生成此文件并插入一行 最简单但最糟糕的解决方案(因为锁)是: 但是,如果有多个客户机执行此代码,则在“使用文件执行某些操作”过程中,所有后续客户机都会占用很长时间 有没有更好的方法来处理这个问题?也许在提交之前改变我处

我有一个存储在磁盘上的文件,可以跨web场中的多个服务器访问该文件。此文件将根据数据库中的数据更改进行必要的更新。我有一个数据库表,其中存储了一行,其中包含该文件的URI和一些基于某些数据库表的哈希值。如果散列与各自的表不匹配,则需要重新生成文件并插入新行

如何使只有一个客户端重新生成此文件并插入一行

最简单但最糟糕的解决方案(因为锁)是:

但是,如果有多个客户机执行此代码,则在“使用文件执行某些操作”过程中,所有后续客户机都会占用很长时间


有没有更好的方法来处理这个问题?也许在提交之前改变我处理文件的方式,使其更快?这件事已经困扰了我好几天了。

答案取决于文件级处理的细节

如果您只是交换数据库和文件操作,则可能会导致文件损坏或忙着等待(具体取决于您打开它的方式,以及当并发打开被拒绝时您的代码所做的操作)。从吞吐量(或任何其他)的角度来看,忙碌等待肯定比等待数据库锁更糟糕

如果您的文件处理真的需要很长时间才能频繁导致请求排队,那么唯一的解决方案就是添加更强大的硬件或优化文件级处理


例如,如果文件仅反映数据库中的数据,则可能根本不更新它,并且有一个后台进程根据数据库中的数据定期重新生成其内容。您可能需要添加版本控制,以确保读取文件的人不会收到过时的数据。如果URL指向的文件每次都有一个新名称,您可能需要一个错误处理程序,以确保
GET
请求不会经常收到有关新文件的
404
响应。

答案取决于文件级处理的详细信息

如果您只是交换数据库和文件操作,则可能会导致文件损坏或忙着等待(具体取决于您打开它的方式,以及当并发打开被拒绝时您的代码所做的操作)。从吞吐量(或任何其他)的角度来看,忙碌等待肯定比等待数据库锁更糟糕

如果您的文件处理真的需要很长时间才能频繁导致请求排队,那么唯一的解决方案就是添加更强大的硬件或优化文件级处理


例如,如果文件仅反映数据库中的数据,则可能根本不更新它,并且有一个后台进程根据数据库中的数据定期重新生成其内容。您可能需要添加版本控制,以确保读取文件的人不会收到过时的数据。如果URL指向的文件每次都有一个新名称,那么您可能需要一个错误处理程序来确保
GET
请求不会经常收到新文件的
404
响应。

听起来您需要异步处理文件,因此,文件过程被剥离,事务及时完成。有几种方法可以做到这一点,但最简单的方法可能是用“在需要更新此文件的表中插入一条记录,然后每隔几分钟运行一次作业,更新该表中的每条记录。”。或者是一些动态生成作业的代码。或者,请参阅堆栈溢出问题。

听起来您需要异步处理文件,因此文件进程将被剥离,事务将及时完成。有几种方法可以做到这一点,但最简单的方法可能是用“在需要更新此文件的表中插入一条记录,然后每隔几分钟运行一次作业,更新该表中的每条记录。”。或者是一些动态生成作业的代码。或者参阅堆栈溢出问题。

im不擅长触发器,但可能有用4uim不擅长触发器,但可能有用4uAs您提到的文件反映数据库中的数据,因此每次数据更改时都会重新生成该文件。我基本上使用数据库行作为一种版本控制系统来跟踪文件的状态。我最后只是确保文件处理不会花费太长时间。对此行的请求量足够低,因此锁定1-2秒(在修复处理部件之后)并不是什么大问题。数据库中的数据不会经常更改,因此文件不会经常更新。我受到应用程序设计的限制,所以我可能会坚持这一点。正如您提到的,文件反映了数据库中的数据,因此每次相应的数据更改时都会重新生成。我基本上使用数据库行作为一种版本控制系统来跟踪文件的状态。我最后只是确保文件处理不会花费太长时间。对此行的请求量足够低,因此锁定1-2秒(在修复处理部件之后)并不是什么大问题。数据库中的数据不会经常更改,因此文件不会经常更新。我受到应用程序设计的限制,所以我可能会坚持这一点。实际执行数据库操作的代码部分只是偶尔出现,因此异步操作可能对我没有好处。对不起,我应该在我的伪代码中更具体一些。“重新生成文件”的频率不足以处理异步操作。我能够减少“使用文件做一些事情”的执行时间,从而保留当前的锁定方案。如果应用程序设计更好或者有更好的方法,我会的,但目前的解决方案应该是
BEGIN TRANSACTION
SELECT ROW FROM TABLE (lock the table for the remainder of the transaction)
IF ROW IS OUT OF DATE:
    REGENERATE FILE
    INSERT ROW INTO TABLE
DO SOME STUFF WITH FILE (30s)
COMMIT TRANSACTION