探讨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 其实删除数据库中数据的方法并不复杂,为什么我还要多此一举呢,一是我这里介绍的是删除数据库的所有数据,因为数据之间 ...
随机推荐
- TCP/IP笔记(五)IP协议相关技术
IP旨在让最终目标主机收到数据包,但是在这一过程中仅仅有IP时无法实现通信的.必须还要又能够解析主机名称和MACdivide功能,以技术包在发送过程中异常情况处理的功能. 这篇主要介绍下DNS.ARP ...
- XMLHttpRequest API 使用指南
一.实例化 XMLHttpRequest 对象 使用 Ajax API 的第一件事情就是实例化 XMLHttpRequest 对象. var xhr = new XMLHttpRequest(); 二 ...
- 自定义一个EL函数
自定义一个EL函数 一般就是一下几个步骤,顺便提供一个工作常用的 案例: 1.编写一个java类,并编写一个静态方法(必需是静态方法),如下所示: public class DateTag { pri ...
- Java关于e.printStackTrace()介绍
public void printStackTrace()将此 throwable 及其追踪输出至标准错误流.此方法将此 Throwable 对象的堆栈跟踪输出至错误输出流,作为字段 System.e ...
- Elasticsearch搜索之explain评分分析
Lucene的IndexSearcher提供一个explain方法,能够解释Document的Score是怎么得来的,具体每一部分的得分都可以详细地打印出来.这里用一个中文实例来纯手工验算一遍Luce ...
- 使用JSONObject生成和解析json
1. json数据类型 类型 描述 Number 数字型 String 字符串型 Boolean 布尔型 Array 数组,以"[]"括起来 Object 对象,类似于C中的结构体 ...
- Python科学计算—numpy模块总结(1)
作为一个本科学数学专业,目前研究非线性物理领域的研究僧.用什么软件进行纯科学计算好,Fortran永远是第一位的:matlab虽然很强大,可以很容易的处理大量的大矩阵,但是求解我们的模型(有时可能是几 ...
- Docker 架构详解 - 每天5分钟玩转容器技术(7)
Docker 的核心组件包括: Docker 客户端 - Client Docker 服务器 - Docker daemon Docker 镜像 - Image Registry Docker 容器 ...
- 【外文翻译】使用Timer类去调度任务 ——java
使用Timer类去调度任务 --java 原文地址:https://dzone.com/articles/using-timer-class-to-schedule-tasks 原文作者:Jay Sr ...
- HTML5 拖放(Drag 和 Drop)功能开发——浅谈dataTransfer对象
[前言] 之前我已经为大家介绍过一篇有关HTML5中原生拖拽的相关知识了.今天为大家介绍HTML5拖拽中的其他一些关于dataTransfer对象的知识和应用. dataTransfer对象 之前的一 ...