为什么带NOLOCK的查询语句还会造成阻塞

news2024/11/27 10:24:04
背景
客户反映HIS数据库在11点出现了长时间的阻塞,直到手动KILL掉阻塞的源头。请我们协助分析原因,最终定位到.NET程序中使用的SqlDataReader未正常关闭导致。

现象


登录SQL专家云,进入趋势分析,在活动会话中回溯11点一个小时内的运行情况,从11:28开始出现阻塞情况,一直持续到11:57。

转到活动会话原始数据,看到ID为418的会话是阻塞源头,阻塞了会话722,会话722又阻塞了其它大量的会话。

分析


首先分析阻塞的成因,会话418执行的是一个查询语句,在表上都加了NOLOCK查询提示,也就是说不加共享锁,不会阻塞其它会话对该表的INSERT、UPDATE、DELETE操作,但是还是要加架构共享锁的,而会话722执行的是TRUNCATE TABLE SYS_KSDMK,是要对表加架构排他锁的,产生互斥,从而造成阻塞。

接下来再分析为什么会造成这么长时间的阻塞,在不同时间点看会话418的运行情况,每个时间点的等待资源都是ASYNC_NETWORK_IO,CPU时间和逻辑读次数都非常小,而且一直不变。

ASYNC_NETWORK_IO从字面上有很强的迷惑性,第一反应是网络环境的问题,通过微软官方文档看到,客户端程序因为各种原因无法快速接收使用查询返回的数据也是很重要的原因。和客户进行确认,这个语句查询的都是字典表,数据量非常小,因此判断该查询语句在SQL Server端很快就执行完了,客户端程序在接收查询结果时出现异常。

根据推断,在客户端程序中果然找程序的错误日志。查看代码,程序用SqlDataReader逐行接收并处理查询结果,在数据类型转换时有报错。

为了更好的说明这个现象,特地写了一段演示代码。用SqlDataReader循环逐行接收查询返回的结果,当接收到ID>500的数据行时抛出异常。报错后程序无法运行到reader.Close()和connection.Close()来关闭SqlDataReader和SqlConnection。

privatevoidDemo(string connectionString){  SqlConnection conn = new SqlConnection(connectionString);  conn.Open();  SqlCommand command = conn.CreateCommand();  command.CommandText = "SELECT id, a, b FROM [dbo].[Table_2] WITH(nolock) ORDER BY id";  SqlDataReader reader = command.ExecuteReader();while (reader.Read())  {int id = Convert.ToInt32(reader["id"]);string a = reader["a"].ToString();if (id > 500)      {thrownew Exception("故意抛出异常");      }  }  reader.Close();  conn.Close();}

因为程序没有异常处理机制,该连接(会话)已经被泄露,所以该会话和请求会一直存在,状态如下图。其它会话对表进行TRUNCATE TABLE操作时就会被阻塞。

解决


要修改应用程序,增加程序的健壮性。可以在异常处理时检查并关闭SqlDataReader和SqlConnection,也可以利用using的特性自动关闭。

//利用using特性,即使有异常也可以关闭SqlDataReader和SqlConnectionprivatevoidDemo(string connectionString){using (SqlConnection conn = new SqlConnection(connectionString))    {        conn.Open();        SqlCommand command = conn.CreateCommand();        command.CommandText = "SELECT id, a, b FROM [dbo].[Table_2] WITH(nolock) ORDER BY id";using (SqlDataReader reader = command.ExecuteReader())        {while (reader.Read())            {int id = Convert.ToInt32(reader["id"]);string a = reader["a"].ToString();if (id > 500)                {thrownew Exception("故意抛出异常");                }            }            reader.Close();        }        conn.Close();    }}

自动查杀会话


因为很多客户是购买软件厂商的产品,修改程序不容易实施。因此只能在数据库端进行补偿性的措施,例如配置一个定期运行的自动查杀会话的作业,根据这种会话的特征KILL掉。也可以在SQL专家云中启用自动查杀会话的功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/177516.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Ajax】防抖和节流

一、防抖什么是防抖防抖策略(debounce)是当事件被触发后,延迟 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。如果事件被频繁触发,防抖能保证只有最有一次触发生效!前面 N 多次的触…

【Linux IO】文件描述符、重定向、缓冲区

1.open函数1.1第二个参数的解释;O_RDONLY: 只读打开 O_WRONLY: 只写打开 O_RDWR : 读,写打开上面三个常量,必须指定一个且只能指定一个 O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限 O_…

MyBatis 连接数据库与增删改查

❤️作者主页:微凉秋意 ✅作者简介:后端领域优质创作者🏆,CSDN内容合伙人🏆,阿里云专家博主🏆 ✨精品专栏:数据结构与课程设计 🔥系列专栏:javaweb 文章目录前…

C++设计模式(8)——命令模式

命令模式 亦称:动作、事务、Action、Transaction、Command 意图 命令模式是一种行为设计模式, 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中, 且能…

linux基本功系列之-lsattr命令实战

文章目录一. lsattr命令实战二. 语法格式及常用选项三. 参考案例3.1 查看指定文件上的隐藏属性:3.2 查看目录的隐藏属性3.3 查看目录中全部文件的隐藏属性总结前言🚀🚀🚀 想要学好Linux,命令是基本功,企业中…

英语学习打卡day4

2023.1.24 1.out of curiosity 出于好奇 out of necessity 出于必要 out of interest 出于利益 out of sympathy 出于同情 out of respect 出于尊敬 out of’ fear 出于害怕 out of desperation 出于不得已/绝望 2.ashore adv.向(或在)岸上;上岸 a在… …的 shore岸- >在…

Java 23种设计模式(5.结构型模式-代理模式)

结构型模式 代理模式 结构型模式描述如何将类或对象按某种布局组成更大的结构。 它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。 由于组合关系或聚合关系比继承关系耦合度低,满足“合成…

分享127个ASP源码,总有一款适合您

ASP源码 分享127个ASP源码,总有一款适合您 下面是文件的名字,我放了一些图片,文章里不是所有的图主要是放不下..., 127个ASP源码下载链接:https://pan.baidu.com/s/1JpOFmxkovbScxmz0_MhUWg?pwd758t 提取码&#x…

算法:一维与二维最大连续子序列和(子矩阵和,c++实现 动态规划)

文章目录一维最大连续子序列和代码示例二维最大连续子序列和、代码示例一维最大连续子序列和 给你一个序列 【-1,-2,3,6,4,-9】的最大的连续的子序列和的值。 什么是最大连续子序列和,首先要满足两个条件…

Java基础 Stream流方法引用异常

Stream流 引例 需求&#xff1a;按照下面要求完成集合的创建和遍历 创建一个集合&#xff0c;存储多个字符串元素 1. 把所有以“曹”开头的元素存储到新集合中 2. 把曹开头&#xff0c;长度为3的元素存储到新集合中 List<String> list List.of("曹操", "…

19.2、Javaweb案例_Servlet代码抽取优化分页数据redis缓存优化分页数据展示

优化Servlet 目的 减少Servlet的数量&#xff0c;现在是一个功能一个Servlet&#xff0c;将其优化为一个模块一个Servlet&#xff0c;相当于在数据库中一张表对应一个Servlet&#xff0c;在Servlet中提供不同的方法&#xff0c;完成用户的请求。 Idea控制台中文乱码解决&…

线性代数复习——行列式

文章目录第一章 行列式1.1 克拉默法则1.2 n阶行列式1.3 特殊行列式1.4 行列式的性质和推论1.5 余子式和代数余子式1.6 范德蒙德行列式第一章 行列式 1.1 克拉默法则 举例&#xff1a; 对于三元线性方程组 {a11x1a12x2a13x3b1a21x1a22x2a23x3b2a31x1a32x2a33x3b3(1)\begin{cas…

Allegro如何自动导弧操作指导

Allegro如何自动导弧操作指导 在做PCB设计的时候,经常会需要给信号线导弧,如果有大量的走线,导弧线是个比较费时间的工作,Allegro可以自动给信号线导弧,如下图 具体操作如下 选择Route选择Unsupported Prototypes

金融帝国实验室(Capitalism Lab)官方正版游戏『优惠活动政策』

「金融帝国实验室」&#xff08;Capitalism Lab&#xff09;Enlight 官方正版游戏「2023春节特卖」 ■时间&#xff1a;2023.01.21&#xff5e;2023.02.28 ■游戏开发商&#xff1a;Enlight Software Ltd. 请您认准以下官方正版游戏购买链接&#xff1a;支持“支付宝&a…

使用ebpf 监控mysqld 内核

一、开发思路分析 我们使用ebpf 监控mysql的话有两个思路去做这件事情 1、kprobe -> hook 掉tcp_sendmsg 和 tcp_recvmsg 一类的内核函数去分析网络协议 2、uprobe -> hook 掉 mysqld 的api函数&#xff0c;然后在此基础上进行统计 我使用的是uprobe 去hook 掉mysql内…

24. 面向对象的思想

1. 面向对象 类似于c/c#/java等高级语言&#xff0c;python从设计之初就已经是一门面向对象的语言&#xff0c;正因为如此&#xff0c;在python中创建一个类和对象是很容易的。关于面向对象的思想及基础&#xff0c;此处不再赘述。 2. 类对象 (1) 类变量&#xff1a;类变量在…

计算机毕业设计选题推荐基于nodejs+Vue360学生宿舍系统

管理员&#xff1b;首页、个人中心、宿舍信息管理、学生管理、宿舍报修管理、访客信息管理、水电费管理、管理员管理、交流论坛、系统管理&#xff0c;学生&#xff1b;首页、个人中心、宿舍报修管理、水电费管理&#xff0c; 前台首页&#xff1b;首页、交流论坛、通知公告、个…

STM32之HAL源码阅读(GPIO章节)

前言 说明 本文只针对于软件层面的阅读&#xff0c;详细操作请查阅对应的手册,使用过标准库的朋友更好的能理解本文针对的是STM32F10x系列&#xff0c;其他的类似 参考资料 STM32F10x中文参考手册 工具 stm32cubemx6.5clion最新版 HAL源码之GPIO的阅读 步骤一&#xff…

Cesium:Indexed 3D Scene Layers (I3S)加载

点击此处,查看完整的OGC标准列表项。Indexed 3D Scene Layers(I3S)标准官网介绍地址为:I3S,相关的GitHub主页地址为:Esri/i3s-spec,其详细介绍文档地址可点击此处查阅。我们的核心点在于介绍如何通过Cesium.js开发框架加载I3S三维场景服务。 目录 Cesium.js:I3S支持情…

JUC面试(九)——Synchronized和Lock的区别

Synchronized和Lock的区别 前言 对象锁&#xff08;synchronized method{}&#xff09;和类锁&#xff08;static sychronized method{}的区别 对象锁也叫实例锁&#xff0c;对应synchronized关键字&#xff0c;当多个线程访问多个实例时&#xff0c;它们互不干扰&#xff0…