探讨SQL Server并发处理队列数据不阻塞解决方案

本文涉及的产品
云数据库 RDS SQL Server,独享型 2核4GB
简介:

前言

之前对于并发这一块确实接触的比较少,自从遇到现在的老大,每写完一块老大都会过目一下然后给出意见,期间确实收获不少,接下来有几篇会来讲解SQL Server中关于并发这一块的内容,有的是总结,有的是学习,若有错误见解请批评性指出。

SQL Server并发处理队列数据问题

在我们的项目中对于购买产品的用户会对应分配卡密,同时会更新其卡密的状态为已使用,所以当出现并发时此时我们不加以控制会导致同一个卡号和密码被不同的用户所使用,这样的情况是不能允许的,此时我们迫切需要解决对卡密使用后的更新和产生的并发。所以有了此文的产生。我们接下来来创建测试表。

CREATE TABLE Test ( 
  Id    INT IDENTITY(1, 1) NOT NULL PRIMARY KEY, 
  Other VARCHAR(100)) 

GO 

接下来我们插入十条测试数据

复制代码
DECLARE  @counter INT 

SELECT @counter = 1 

WHILE (@counter <= 10) 
  BEGIN 
    INSERT INTO Test
               (Other) 
    SELECT 'other action' + CAST(@counter AS VARCHAR) 
     
    SELECT @counter = @counter + 1 
  END
复制代码

接下来我们打开两个会话运行如下SQL语句:

复制代码
DECLARE @queueid INT 

BEGIN TRAN TRAN1 

SELECT TOP 1 @queueid = Id 
FROM Test

PRINT 'processing queueid # ' + CAST(@queueid AS VARCHAR) 

WAITFOR DELAY '00:00:10' 

DELETE FROM Test 
WHERE Id = @queueid 

COMMIT
复制代码

此时我们看到打开的两个会话会同时处理相同的行。

如上则不是我们想要的结果,此时我们再来在如上基础上加一个更新锁,然后SQL Server查询引擎会不允许其他读取者来获取更新锁,此时将能够有效的处理对应对应的行记录,但是会造成阻塞,如下:

复制代码
DECLARE @queueid INT 

BEGIN TRAN TRAN1 

SELECT TOP 1 @queueid = Id 
FROM Test WITH (updlock) 

PRINT 'processing queueid # ' + CAST(@queueid AS VARCHAR) 

WAITFOR DELAY '00:00:10' 

DELETE FROM Test 
WHERE Id = @queueid 

COMMIT
复制代码

 

上述虽然能解决更新问题,但是此时会造成阻塞,一旦并发量比较大此时将造成长时间阻塞,当前正在执行的更新会话必须等待另外一个更新会话执行完毕同时释放更新锁。此时为了解决阻塞问题,在SQL Server中通过添加READPAST关键字来告诉SQL Server引擎一旦遇到被锁住的行,你就跳过吧不用理会,所以不会再造成阻塞问题。此时最终的代码将变成如下:

复制代码
DECLARE @queueid INT 

BEGIN TRAN TRAN1 

SELECT TOP 1 @queueid = Id 
FROM Test WITH (updlock) 

BEGIN TRAN TRAN1 

SELECT TOP 1 @queueid = Id 
FROM Test WITH (UPDLOCK, READPAST) 

PRINT 'processing queueid # ' + CAST(@queueid AS VARCHAR) 

WAITFOR DELAY '00:00:10' 

DELETE FROM Test 
WHERE Id = @queueid 

COMMIT

PRINT 'processing queueid # ' + CAST(@queueid AS VARCHAR) 

WAITFOR DELAY '00:00:10' 

DELETE FROM Test 
WHERE Id = @queueid 

COMMIT
复制代码

通过UPDLOCK+READPAST结合使用将对于处理并发更新时,就像处理队列数据一样,但是不会造成阻塞,此时将给予我们最好的性能。我们结合上述所讲,来查询出数据并删除对应数据且,不会出现重复删除情况且不会导致阻塞,此时代码将变成如下:

复制代码
SET NOCOUNT ON 
DECLARE @queueid INT  

WHILE (SELECT COUNT(*) FROM Test WITH (updlock, readpast)) >= 1 

BEGIN 

   BEGIN TRAN TRAN1  

   SELECT TOP 1 @queueid = Id  
   FROM Test WITH (updlock, readpast)  

   PRINT 'processing queueid # ' + CAST(@queueid AS VARCHAR)  

   WAITFOR DELAY '00:00:10'  

   DELETE FROM Test 
   WHERE Id = @queueid 
   COMMIT 
END
复制代码

 

总结

本文我们探讨产生并发在SQL Server中如何不处于阻塞并且得到较好的性能,对于那种秒杀情况,这种方案不失为一种解决方案,请问你有何高见?






本文转自Jeffcky博客园博客,原文链接:http://www.cnblogs.com/CreateMyself/p/6906279.html,如需转载请自行联系原作者

相关实践学习
使用SQL语句管理索引
本次实验主要介绍如何在RDS-SQLServer数据库中,使用SQL语句管理索引。
SQL Server on Linux入门教程
SQL Server数据库一直只提供Windows下的版本。2016年微软宣布推出可运行在Linux系统下的SQL Server数据库,该版本目前还是早期预览版本。本课程主要介绍SQLServer On Linux的基本知识。 相关的阿里云产品:云数据库RDS&nbsp;SQL Server版 RDS SQL Server不仅拥有高可用架构和任意时间点的数据恢复功能,强力支撑各种企业应用,同时也包含了微软的License费用,减少额外支出。 了解产品详情:&nbsp;https://www.aliyun.com/product/rds/sqlserver
目录
相关文章
|
6天前
|
SQL API 流计算
实时计算 Flink版产品使用合集之在Mac M1下的Docker环境中开启SQL Server代理的操作步骤是什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
20 1
|
17小时前
|
SQL 关系型数据库 MySQL
简简单单 My SQL 学习笔记(2)——分组和简单数据的查询
简简单单 My SQL 学习笔记(2)——分组和简单数据的查询
|
17小时前
|
SQL 关系型数据库 MySQL
简简单单 My SQL 学习笔记(1)——表中数据的整删改查
简简单单 My SQL 学习笔记(1)——表中数据的整删改查
|
4天前
|
网络安全 流计算 Python
实时计算 Flink版操作报错合集之Flink sql-client 针对kafka的protobuf格式数据建表,报错:java.lang.ClassNotFoundException 如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
17 1
|
4天前
|
SQL Java 关系型数据库
实时计算 Flink版操作报错合集之通过flink sql形式同步数据到hudi中,本地启动mian方法报错如何解决
在使用实时计算Flink版过程中,可能会遇到各种错误,了解这些错误的原因及解决方法对于高效排错至关重要。针对具体问题,查看Flink的日志是关键,它们通常会提供更详细的错误信息和堆栈跟踪,有助于定位问题。此外,Flink社区文档和官方论坛也是寻求帮助的好去处。以下是一些常见的操作报错及其可能的原因与解决策略。
24 8
|
5天前
|
SQL 流计算 API
实时计算 Flink版产品使用合集之ClickHouse-JDBC 写入数据时,发现写入的目标表名称与 PreparedStatement 中 SQL 的表名不一致如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
12 0
|
5天前
|
SQL 数据处理 API
实时计算 Flink版产品使用合集之遇到SQL Server锁表问题如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
11 0
|
6天前
|
消息中间件 关系型数据库 网络安全
实时计算 Flink版操作报错合集之Flink sql-client 针对kafka的protobuf格式数据建表,报错:java.lang.ClassNotFoundException 如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
18 1
|
6天前
|
SQL 关系型数据库 MySQL
实时计算 Flink版产品使用合集之在使用Flink SQL向ClickHouse写入数据的过程中出现丢数据或重复数据的情况如何解决
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
20 1
|
6天前
|
SQL 关系型数据库 数据库
实时计算 Flink版产品使用合集之将数据写入Elasticsearch时,若Elasticsearch中的字段类型为date,对应的SQL类型应该是什么
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
27 0