防止多个线程/实例在 Azure SQL 数据库中选择和处理相同的行

Posted

技术标签:

【中文标题】防止多个线程/实例在 Azure SQL 数据库中选择和处理相同的行【英文标题】:Prevent multiple threads/instances to select and process the same rows in Azure SQL-database 【发布时间】:2016-06-30 13:01:07 【问题描述】:

我有一个关于如何防止应用程序和/或线程的多个实例选择 MSSQL 表中的相同行的问题。

这是场景: 我有一个 ASP.net 站点,用户可以在其中输入他们的电子邮件。 然后该电子邮件将被插入到我的 MSSQL 数据库中的一个表中。

然后想法是有一个 WebJob(Azure WebJob) 每五秒选择一次所有新创建的行,然后向每个用户发送一封电子邮件,然后将该行标记为“已处理”..

然而.. 如果我出于某种原因决定将我的 WebJob 扩展到多个实例怎么办?... 我假设可能有一个小窗口,多个实例可能会在数据库中选择相同的行,然后处理这些行并向注册用户发送多封电子邮件? 有没有办法“锁定”另一个实例/线程当前正在处理的行?

还是我用错了方法?

兄弟, 英克斯

【问题讨论】:

看看service bus。我认为这比使用 SQL 数据库更好。 【参考方案1】:

我无法对 ASP.Net 发表评论,因为它已经很久没有使用它了。但是对于 SQL Server,您应该查看数据队列示例。下面的链接是一个很好的起点:

https://www.mssqltips.com/sqlservertip/1257/processing-data-queues-in-sql-server-with-readpast-and-updlock/

您可以使用查询提示(即链接中的 UPDLOCK、READPAST)和约束(强制唯一性等)来确保没有两个线程可以读取或写入相同的数据。

【讨论】:

【参考方案2】:

我宁愿将邮件的发送整合到与插入数据库等相同的过程中。例如,您可以有一个存储过程,将新记录插入数据库,然后使用 sp_send_dbmail 发送邮件。

您还可以使用 SQL Dependency。如果您在 SQL Server 中启用代理并使用 SQL 依赖项,那么对数据库的任何更改都将被推送到您的应用程序。 SQL Dependency 很容易使用,稍微搜索一下,你会发现很多教程。

在这两种解决方案中,您都不需要不断地轮询您的数据库。

如果您必须使用 webjobs,那么您可以使用Serialized 隔离级别将代码包装在TransactionScope 中。这将防止多个实例出现问题。

using(TransactionScope scope = new TransactionScope())
 
      /* Perform transactional work here */
      SomeMethod();
      scope.Complete();
 

我相信在使用 TransactionScope 时,隔离级别默认设置为可序列化。

【讨论】:

嗨,是的,使用相同的线程/实例直接发送电子邮件会很有意义,但是系统当前架构要求电子邮件被“排队”。此外,由于应用程序和数据库将托管在 Azure(Web 应用程序、WebJob 和 Azure SQL)中,因此我将无法使用 SQL 依赖关系.. 很抱歉有一个非常错误的主题标题.. 我将从 MSSQL 更改为Azure SQL。

以上是关于防止多个线程/实例在 Azure SQL 数据库中选择和处理相同的行的主要内容,如果未能解决你的问题,请参考以下文章

Java异步MySQL查询

最新的Azure SQL数据库实例中的Azure搜索服务与全文搜索?

如何在 Azure 的一个事务中执行多个 SQL 文件?

java多线程,如何防止脏读数据

修复或避免在 SSDT 引用 Azure 托管实例中的主数据库时出现 SQL71501 和 SQL71561 构建错误?

虚拟机的那个线程是不是需要每个线程有多个实例?