SQL Server 幻读 的真实案例
数据库中有表[01_SubjectiveScoreInfo],要实现表中的数据只被查出一次,此表数据量较大,有三四百万数据。表结构也确实不是很合理,无法修改表结构,即使是新增一个字段也会有相当大的修改量。
因之前代码中存在大量的insert into select *的语句,加一个字段什么也不做也会导致整个项目瘫痪,当然我不想去讨论前人的代码质量。
于是乎我加了一个新表[01_SubjectiveScoreInfoFlag]来进行记录取过的记录ID。于是就有了如下的代码:
BEGIN TRAN SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; INSERT INTO [01_SubjectiveScoreInfoFlag](ID)
SELECT TOP 100 SS.ID
FROM [01_SubjectiveScoreInfo] AS SSINNER JOIN SubjectiveItemInfo AS SI
ON SS.TestCode=SI.TestCode
AND SS.MajorQuestionID=SI.MajorQuestionID
AND SS.MinorQuestionID=SI.MinorQuestionID
WHERE SS.TestCode=''' + @TestCode + '''
AND SI.QuestionGroupCode=''' + @QuestionGroupCode + '''
AND (SI.MinorQuestionCount=0
OR SI.MinorQuestionID>0)
AND NOT EXISTS
(
SELECT TOP 1 1
FROM [01_SubjectiveScoreInfoFlag]
WHERE ID = SS.ID
) COMMIT TRAN
此处用到了事务,并且指定了隔离级别。这个是必须的,我们之前就是没有指定,单线程无论你怎么调用这段代码运行都非常可靠,但多线程模拟并发调用时就出现了非常严重的重复。
上面的代码也并没有解决问题,原因是锁用得不对,多线程直接就出现了死锁现象。因之前对于隔离级别没什么经验,我一度曾经以为这个问题是无解的,直到今天突然被解开了。
按照我自己的理解,是因为锁的级别不够,导致了资源争抢。
就相当于上厕所时,一定要获取完全的排它锁,关好门不让其它人进来;否则如果其它人进来了,虽然他没有占到位子,但他拿走了手纸。你占着位子却没有手纸,他拿着手纸却没有位子,双方互不相让,谁也无法完成上厕所的事务,相持不下,进而导致死锁。这时就需要厕所管理出面,要么强制让你让出位子走人,不管理你擦没擦屁股;要么抢来手纸赶走他,任他拉到裤子上。
于是乎就有了下面的代码:
BEGIN TRAN SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; INSERT INTO ['+@CourseID+'_SubjectiveScoreInfoFlag](ID)
SELECT TOP 100 SS.ID
FROM ['+@CourseID+'_SubjectiveScoreInfo] AS SS WITH(UPDLOCK)
INNER JOIN SubjectiveItemInfo AS SI WITH(UPDLOCK)
ON SS.TestCode=SI.TestCode
AND SS.MajorQuestionID=SI.MajorQuestionID
AND SS.MinorQuestionID=SI.MinorQuestionID
WHERE SS.TestCode=''' + @TestCode + '''
AND SI.QuestionGroupCode=''' + @QuestionGroupCode + '''
AND (SI.MinorQuestionCount=0
OR SI.MinorQuestionID>0)
AND NOT EXISTS
(
SELECT TOP 1 1
FROM ['+@CourseID+'_SubjectiveScoreInfoFlag] WITH(UPDLOCK)
WHERE ID = SS.ID
) COMMIT TRAN
UPLOCK是排它锁,这样就没有死锁了。
SQL Server 幻读 的真实案例的更多相关文章
- SQL Server一个特殊的阻塞案例分析2
最近发现一个非常奇怪的阻塞问题,如下截图所示(来自监控工具DPA),会话583被会话1036阻塞,而且阻塞发生在tempdb,被阻塞的SQL如下截图所示,会话等待类型为LCK_M_S 因为DPA工具不 ...
- 初谈SQL Server逻辑读、物理读、预读
前言 本文涉及的内容均不是原创,是记录自己在学习IO.执行计划的过程中学习其他大牛的博客和心得并记录下来,之所以想写下来是为了记录自己在追溯的过程遇到的几个问题,并把这些问题弄清楚. 本章最后已贴出原 ...
- SQL Server逻辑读、预读和物理读
SQL Server数据存储的形式 预读:用估计信息,去硬盘读取数据到缓存.预读100次,也就是估计将要从硬盘中读取了100页数据到缓存. 物理读:查询计划生成好以后,如果缓存缺少所需要的数据,让缓存 ...
- 初谈SQL Server逻辑读、物理读、预读【转】
前言 本文涉及的内容均不是原创,是记录自己在学习IO.执行计划的过程中学习其他大牛的博客和心得并记录下来,之所以想写下来是为了记录自己在追溯的过程遇到的几个问题,并把这些问题弄清楚. 本章最后已贴出原 ...
- SQL Server服务没有自动启动原因案例分析
这个案例是前两天出现的,一直没有时间总结,25号凌晨4点去处理数据库的故障问题.远程连上公司的局域网,psping检查发现服务器的1433端口不通,数据库连接不上,但是主机又能ping通,登录服务器检 ...
- SQL Server数据库邮件发送异常案例
最近遇到两起关于SQL Server数据库邮件发送异常的案例,这些问题也有点意思,顺便记录一下.方便以后遇到类似问题的人参考,不要被这些问题弄得抓狂! 案例1:我们一台数据库服务器突然发送邮件都不 ...
- SQL Server 一致性读
我们在Oracle和MySQL数据库中已经对一致性读的概念比较熟悉了,但是在SQL Server中却鲜少提及,但SQL Server自2005版本以来其实也实现了一致性读,几乎所有关系型数据库产品的一 ...
- 应对黑客攻击SQL SERVER数据库中的一个案例
最近发现挂在网上server不知怎的,重新启动,那server现在主要是开始IIS服务,SQL SERVER 服务. 远程登录.发现系统响应十分缓慢.一个明显的停滞感,打开任务管理器,CPU在基本用法 ...
- SQL Server作业报错特殊案例
一个作业报错,报错信息如下,从错误信息根本看不出为什么出错,手工运行作业又成功了.一时不清楚什么原因导致作业出错. Message Executed as user: NT SERVICE\SQLSE ...
随机推荐
- springboot热部署(二)——springboot热部署与发布
一.实现的方式概述 注意以下的热部署方式在IDEA是默认没有打开自动编译的,手动编译需要快捷键(Ctrl+Shift+F9),自动编译的修改配置如下:(注意刷新不要太快,会有1-2秒延迟) File- ...
- 本地构建:Gulp
Gulp中文网:https://www.gulpjs.com.cn/ Gulp英文网:https://gulpjs.com/ Gulp:工作流程自动化+强化 (一)安装初始化 (二)基础API及插件 ...
- js的缓存
无网络的情况下,使用静态资源呈现页面的方法,只有h5的manifest 有网的情况下(可以连接到服务器的情况下),有3种判断缓存的方式. ------------------------------- ...
- [HTML] HTML Lists
无序列表: 1. unordered list 以<ul>开头,以</ul>结果. 每个list item 以<li> tag开头. 2. 样式: bullet(小 ...
- winform 分页控件
http://www.cnblogs.com/liuyunsheng/p/4853387.html http://www.cnblogs.com/wuhuacong/archive/2011/07/0 ...
- hdu5421Victor and String 两端加点的pam
题意:要求维护两端加点的字符串,以及查询本质回文串个数和所有回文串个数 题解:pam,两端加点过程详见ioi2017国家集训队论文,维护一个最长回文前缀和最长回文后缀即可,fail不用两个,能前后共用 ...
- mongoengine 分页 切片与 skip + limit 的区别
首先要了解切片与 skip 的原理 切片原理是将 index(索引) 或 cursor(游标)移动到 start 位置再 进行切分: skip原理是跳过start条数据后再获取 1. 单纯的普通分页用 ...
- linux软件管理 YUM命令
yum的优点 将所有软件包放到官方服务器上,当进行yum在线安装时可以自动解决依赖性问题 yum源文件 [root@ssgao1987 yum.repos.d]# cd /etc/yum.repos. ...
- vue轮播图实现
1.先安装组件 cnpm install vue-awesome-swiper; 2.在main.js下引入文件: import VueAwsomeSwiper from 'vue-awesome-s ...
- 使用matlab生成用于ROM初始化的coe文件(转)
reference:https://www.cnblogs.com/chensimin1990/p/9759368.html t=0:2*pi/2^12:2*pi; y=0.5*sin(t)+0.5; ...