数据库中有表[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 幻读 的真实案例的更多相关文章

  1. SQL Server一个特殊的阻塞案例分析2

    最近发现一个非常奇怪的阻塞问题,如下截图所示(来自监控工具DPA),会话583被会话1036阻塞,而且阻塞发生在tempdb,被阻塞的SQL如下截图所示,会话等待类型为LCK_M_S 因为DPA工具不 ...

  2. 初谈SQL Server逻辑读、物理读、预读

    前言 本文涉及的内容均不是原创,是记录自己在学习IO.执行计划的过程中学习其他大牛的博客和心得并记录下来,之所以想写下来是为了记录自己在追溯的过程遇到的几个问题,并把这些问题弄清楚. 本章最后已贴出原 ...

  3. SQL Server逻辑读、预读和物理读

    SQL Server数据存储的形式 预读:用估计信息,去硬盘读取数据到缓存.预读100次,也就是估计将要从硬盘中读取了100页数据到缓存. 物理读:查询计划生成好以后,如果缓存缺少所需要的数据,让缓存 ...

  4. 初谈SQL Server逻辑读、物理读、预读【转】

    前言 本文涉及的内容均不是原创,是记录自己在学习IO.执行计划的过程中学习其他大牛的博客和心得并记录下来,之所以想写下来是为了记录自己在追溯的过程遇到的几个问题,并把这些问题弄清楚. 本章最后已贴出原 ...

  5. SQL Server服务没有自动启动原因案例分析

    这个案例是前两天出现的,一直没有时间总结,25号凌晨4点去处理数据库的故障问题.远程连上公司的局域网,psping检查发现服务器的1433端口不通,数据库连接不上,但是主机又能ping通,登录服务器检 ...

  6. SQL Server数据库邮件发送异常案例

      最近遇到两起关于SQL Server数据库邮件发送异常的案例,这些问题也有点意思,顺便记录一下.方便以后遇到类似问题的人参考,不要被这些问题弄得抓狂! 案例1:我们一台数据库服务器突然发送邮件都不 ...

  7. SQL Server 一致性读

    我们在Oracle和MySQL数据库中已经对一致性读的概念比较熟悉了,但是在SQL Server中却鲜少提及,但SQL Server自2005版本以来其实也实现了一致性读,几乎所有关系型数据库产品的一 ...

  8. 应对黑客攻击SQL SERVER数据库中的一个案例

    最近发现挂在网上server不知怎的,重新启动,那server现在主要是开始IIS服务,SQL SERVER 服务. 远程登录.发现系统响应十分缓慢.一个明显的停滞感,打开任务管理器,CPU在基本用法 ...

  9. SQL Server作业报错特殊案例

    一个作业报错,报错信息如下,从错误信息根本看不出为什么出错,手工运行作业又成功了.一时不清楚什么原因导致作业出错. Message Executed as user: NT SERVICE\SQLSE ...

随机推荐

  1. Spring中ClassPathXmlApplication与FileSystemXmlApplicationContext的区别

    Spring中ClassPathXmlApplication与FileSystemXmlApplicationContext的区别 一.概述 在项目中遇到加载不到Spring配置文件,简单分析后,写此 ...

  2. 自己封装myLocalStorage,使其有有效期

    项目中遇见 cookie 值存不上,what fuck?什么情况,不知道.用$.cookie 和原生的 cookie 都不行,存上值,就被删了一样.找不见地方.考虑到项目比较大,去找得代价,还不如换种 ...

  3. [原]jsbsim 自动驾驶c310ap文件改写

    <?xml version="1.0"?> <!-- Author: 南水之源 Date: 1 January 2019 Function: A-320 auto ...

  4. VUE本身是不支持IE的,可用babel-polyfill解决

    一般来说VUE本身是不支持IE的,但是可以用特殊的方法来解决,亲测可用第一步:下载插件 cnpm install --save babel-polyfill第二步:入口文件main.js引入( imp ...

  5. postman(一):主界面模块解析

    在做接口测试时经常会用到postman,但是一直没有总结过,太过零散,这次找了一些好的资料,结合自己平时所用到的功能,总结一波 打开postman,主界面如下 左侧菜单 1.History标签 里面存 ...

  6. windows 和linux 文件互传

    1.sz +  文件   [拷贝到windows上] 2.rz + 文件 [拷贝到linux上]

  7. selenium java ,执行js改变页面

    1.面对页面一些页面上的限制而导致某些选择按钮无法选中的问题 很多时候由于页面上的一些限制会导致我们无法无法正常用webdriver来实现我们手动的正常操作,这时候我们可以通过执行js来适当的改变页面 ...

  8. Hadoop 2.7.4 HDFS+YRAN HA部署

    实验环境 主机名称 IP地址 角色 统一安装目录 统一安装用户 sht-sgmhadoopnn-01 172.16.101.55 namenode,resourcemanager /usr/local ...

  9. 单机器搭建 zk 集群

    在一台机器上配置 2 节点的 zk 集群,zk1 和 zk2 的 serverid 分别为 1 和 2,本机 ip 是 192.168.40.1 zk1 相关配置: dataDir=E:/test/z ...

  10. C++使用: C++中map的基本操作和用法

    在阅读SSD代码中发现作者使用了C++中的map方法,因此搜索该关联式容器的使用方法,在这里一并总结. 一.Map 簡介 Map是STL的一個容器,它提供一對一的hash. 第一個可以稱為關鍵字(ke ...