探讨SQL Server并发处理队列数据不阻塞解决方案
前言
之前对于并发这一块确实接触的比较少,自从遇到现在的老大,每写完一块老大都会过目一下然后给出意见,期间确实收获不少,接下来有几篇会来讲解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中如何不处于阻塞并且得到较好的性能,对于那种秒杀情况,这种方案不失为一种解决方案,请问你有何高见?
探讨SQL Server并发处理队列数据不阻塞解决方案的更多相关文章
- 探讨SQL Server并发处理存在就更新七种解决方案
前言 本节我们来讲讲并发中最常见的情况存在即更新,在并发中若未存在行记录则插入,此时未处理好极容易出现插入重复键情况,本文我们来介绍对并发中存在就更新行记录的七种方案并且我们来综合分析最合适的解决方案 ...
- SQL Server中SELECT会真的阻塞SELECT吗?
在SQL Server中,我们知道一个SELECT语句执行过程中只会申请一些意向共享锁(IS) 与共享锁(S), 例如我使用SQL Profile跟踪会话86执行SELECT * FROM dbo.T ...
- SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Temporal Table(历史表)
原文:SQL Server ->> 深入探讨SQL Server 2016新特性之 --- Temporal Table(历史表) 作为SQL Server 2016(CTP3.x)的另一 ...
- Sql Server系列:数据表操作
表是用来存储数据和操作数据的逻辑结构,用来组织和存储数据,关系数据库中的所有数据都表现为表的形式,数据表由行和列组成.SQL Server中的数据表分为临时表和永久表,临时表存储在tempdb系统数据 ...
- 一个有趣的SQL Server 层级汇总数据问题
看SQL Server大V宋大侠的博客文章,发现了一个有趣的sql server层级汇总数据问题. 具体的问题如下: parent_id emp_id emp_nam ...
- sql server 随机读取数据
--sql server 随机读取数据 * FROM [tablename] ORDER BY NEWID() pk from [tablename] ORDER BY NEWID()) --这两个方 ...
- sql server 与oracle数据互导的一种思路--sql server链接服务器
思路:通过在sql server数据库中添加链接服务器,可以远程查询oracle数据库的表环境准备,安装sql server数据库,并安装好oracle驱动,在配置好tnsname文件中配置好orac ...
- 如何用asp.net MVC框架、highChart库从sql server数据库获取数据动态生成柱状图
如何用asp.net MVC框架.highChart库从sql server数据库获取数据动态生成柱状图?效果大概是这样的,如图: 请问大侠这个这么实现呢?
- 最简单删除SQL Server中所有数据的方法
最简单删除SQL Server中所有数据的方法 编写人:CC阿爸 2014-3-14 其实删除数据库中数据的方法并不复杂,为什么我还要多此一举呢,一是我这里介绍的是删除数据库的所有数据,因为数据之间 ...
随机推荐
- asp.net core源码飘香:Options组件
简介: Options组件是一个小组件,但用的地方很多.它本质是将一个POCO类注册到容器中(主要在Startup中作为其他组件的配置功能提供),后续使用的时候就可以通过比如构造函数注入等获取到POC ...
- 【R.转载】apply函数族的使用方法
为什么用apply 因为我是一个程序员,所以在最初学习R的时候,当成"又一门编程语言"来学习,但是怎么学都觉得别扭.现在我的看法倾向于,R不是一种通用型的编程语言,而是一种统计领域 ...
- [UWP]了解模板化控件(4):TemplatePart
1. TemplatePart TemplatePart(部件)是指ControlTemplate中的命名元素.控件逻辑预期这些部分存在于ControlTemplate中,并且使用protected ...
- java集合基础
集合概念与作用 1现实生活中把很多事物凑在一起就是集合.java中的集合类:是一种工具,就像是容器,存储任意数量的有共同属性的对象. 2在类的内部,对数据进行组织: 简单而快速的搜索大数量的条目 有的 ...
- 浅谈echo、print、var_dump()、print_r()的区别
1.echo 和 print 的区别 共同点:首先echo 和 print 都不是严格意义上的函数,他们都是语言结构;他们都只能输出 字符串,整型跟int型浮点型数据.不能打印复合型和资源型数据: 而 ...
- jQuery扩展函数设置所有对象只读
jQuery(function ($) { $.fn.disable = function () { return this.each(func ...
- 【shell编程基础0】bash shell编程的基本配置
前面一篇“shell编程之变量篇”主要讲述下shell编程的变量的基本知识:设置变量的方式,自定义变量和环境变量的差别,变量的替换.删除.测试等. 这一篇主要是讲述在bash shell下的一些基本配 ...
- MySQL最常用数值函数
数值函数: 用来处理很多数值方面的运算,使用数值函数,可以免去很多繁杂的判断求值的过程,能够大大提高用户的工作效率. 1.ABS(x):返回 x 的绝对值 mysql> select abs(- ...
- _getch() 函数,应用于输入密码敲入回车前修改
body,table { font-family: 微软雅黑; font-size: 10pt } table { border-collapse: collapse; border: solid g ...
- Java命名默认规范
学习java的时候,命名的大小写经常弄混,所以在此总结一下java命名规范 1.project(项目名) 说法不一,暂定小写,eg:arraytest 2.包名 小写,eg:package array ...