防止多个线程/实例在 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 数据库中选择和处理相同的行的主要内容,如果未能解决你的问题,请参考以下文章
最新的Azure SQL数据库实例中的Azure搜索服务与全文搜索?
修复或避免在 SSDT 引用 Azure 托管实例中的主数据库时出现 SQL71501 和 SQL71561 构建错误?