探讨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
目录
相关文章
|
4天前
|
SQL 监控 数据库
【SQLserver】常见问题和解决方案
【SQLserver】常见问题和解决方案
17 0
|
1天前
|
SQL 数据库
Sql中如何添加数据
Sql中如何添加数据
5 0
|
1天前
|
SQL 存储 数据库连接
LabVIEW与SQL Server 2919 Express通讯
LabVIEW与SQL Server 2919 Express通讯
|
2天前
|
SQL Windows
安装SQL Server 2005时出现对性能监视器计数器注册表值执行系统配置检查失败的解决办法...
安装SQL Server 2005时出现对性能监视器计数器注册表值执行系统配置检查失败的解决办法...
12 4
|
3天前
|
SQL 数据可视化 Oracle
这篇文章教会你:从 SQL Server 移植到 DM(上)
这篇文章教会你:从 SQL Server 移植到 DM(上)
|
3天前
|
SQL 关系型数据库 数据库
SQL Server语法基础:入门到精通
SQL Server语法基础:入门到精通
SQL Server语法基础:入门到精通
|
3天前
|
SQL 存储 网络协议
SQL Server详细使用教程
SQL Server详细使用教程
23 2
|
3天前
|
SQL 存储 数据库连接
C#SQL Server数据库基本操作(增、删、改、查)
C#SQL Server数据库基本操作(增、删、改、查)
7 0
|
3天前
|
SQL 存储 小程序
数据库数据恢复—Sql Server数据库文件丢失的数据恢复案例
数据库数据恢复环境: 5块硬盘组建一组RAID5阵列,划分LUN供windows系统服务器使用。windows系统服务器内运行了Sql Server数据库,存储空间在操作系统层面划分了三个逻辑分区。 数据库故障: 数据库文件丢失,主要涉及3个数据库,数千张表。数据库文件丢失原因未知,不能确定丢失的数据库文件的存放位置。数据库文件丢失后,服务器仍处于开机状态,所幸未写入大量数据。
数据库数据恢复—Sql Server数据库文件丢失的数据恢复案例
|
4天前
|
SQL 存储 关系型数据库
SQL Server详细使用教程及常见问题解决
SQL Server详细使用教程及常见问题解决