解决session阻塞的问题

简介

    对于数据库运维人员来说创建session或者查询时产生问题是常规情况,下面介绍一种很有效且不借助第三方工具的方式来解决类似问题。

最近开始接触运维工作,所以自己总结一些方案便于不懂数据库的同事解决一些不太紧要的数据库问题。类似方法很多理论也很多,我就不做深究,就是简单写一个方案,便于菜鸟使用的。

阻塞理解

Sql Server 中当一个数据库会话中的事务正锁定一个或多个其他会话事务想要读取或修改的资源时,会产生阻塞(Blocking)。通常短时间的阻塞没有问题,且是较忙的应用程序所需要的。然而,设计糟糕的应用程序会导致长时间的阻塞,这就不必要地锁定了资源,而且阻塞了其他会话读取和更新它们。

例子

   为了更好说明,下面用一个例子来介绍。创建一个表并插入数据,然后创建不同的session,同事阻塞session。具体的代码截图如下:

1.创建表Employee

2.插入测试数据

现在我们有了测试表,表中有12条数据,打开另一个查询对话框在SSMS中(意味着重新创建了一个session)

3.在新的查询窗口中首先要开启事务,然后写一个插入语句

在这个地方,我们能看到开启了一个事务。但是没有end tran 来终止事务,因此事务状态为“open”,现在运行脚本来看一下当前看起的运行处于“open”状态的session。

    现在能够看到如上图展示一样,运行的查询正在open状态的session。我们执行了这个命令但是没有完结它,DBA会联系这个session的创建者来完成事务,或者回滚事务。

现在让我们创建另一个session,更新一条记录并且不提交,即让查询session的状态为“open”。因此在新的查询窗口中 写一个语句来执行如下:

这里会看到系统正在运行后没有完成语句的状态(因为上一个事务没有关闭导致表锁,这个不能插入),现在可以在另外的窗口查询一下阻塞的情况,如下检查阻塞的session。

如上所示,阻塞的session ID是58,由于我们更新查询导致阻塞了54的执行,54就是我们插入数据未提交的批处理。

现在我们能搞清楚阻塞的原因,也就可以从容解决阻塞了。

解决

方案1

在了解业务的情况下,可以直接使用kill session ID的语句来终止某个阻塞的session。

方案2

在执行的事务的起始加入“set lock_timeout 1000” 语句,这表示如果阻塞超过1000毫秒,这个请求将被终止。

方案3

回滚或者提交事务。这个就不细说了。

下面是所有语句的代码:

/****Creating dummy table Employee ****/ 
CREATE TABLE Employee ( Empid int NOT NULL, Name nchar(10) NULL, City nchar(10) NULL ) ON [PRIMARY] GO 
/**** Insert dummy data in Employee table *****/ 
Insert into Employee Values(1245,'George','Jax'), (1045,'Peter','Anadale'), (1157,'John','Dallas'), (1175,'Pete','Topeka'), (875,'Petron','Vienna'), 
(2311,'Kohli','Mumbai'), (1547,'Peter','Kansas'), (3514,'Abian','KHI'), (4251,'Ghani','Alexandria'), (957,'Ahmed','Vienna'), (1084,'Bhanu','Manderin'), 
(2954,'Ganeshan','Mcclean')
 /***** Insert query in new session ****/ 
BEGIN TRAN Insert into Employee Values(1245,'George','Jax') 
/**** Query to check currently running sessions ****/ 
SELECT DISTINCT name AS database_name, session_id, host_name, login_time, login_name, reads, writes FROM sys.dm_exec_sessions 
LEFT OUTER JOIN sys.dm_tran_locks ON sys.dm_exec_sessions.session_id = sys.dm_tran_locks.request_session_id 
INNER JOIN sys.databases ON sys.dm_tran_locks.resource_database_id = sys.databases.database_id 
WHERE resource_type <> 'DATABASE' --AND name ='specific db name' 

总结

     自己也使用过多种不同的语句来查询定位阻塞甚至死锁,然后解决,这里也是介绍一种临时解决方式。万变不离其宗,归根结底还是因为代码甚至数据库设计上存在很多问题才导致的阻塞,比如缺失索引、事务中的查询性能和逻辑顺序存在问题、T-SQL语句性能引起的等等不一而足。对于一些常年解决类似问题的DBA人员来说没啥价值,但是对于不太理解数据库的人来说还是能暂时解决一些紧急问题,当然最后还是要把理论基础打好才能尽可能的杜绝类似情况。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏GreenLeaves

SET NOCOUNT ON

作用:阻止在结果集中返回显示受T-SQL语句或则usp影响的行计数信息。 当SET ONCOUNT ON时候,不返回计数,当SET NOCOUNT OFF时候,...

1977
来自专栏JAVA高级架构

关于 MySQL 的知识点与面试常见问题都在这里

img垂直拆分的优点: 可以使得行数据变小,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表的结构,易于维护。 垂直拆分的缺点: 主键会...

2093

在CentOS 6上使用Postfix,Dovecot和MySQL发送电子邮件

Postfix 邮件传输代理(MTA)是一种高性能的开源电子邮件服务器系统。本指南将帮助你在CentOS 6 Linode上运行 Postfix,使用 Dove...

3405
来自专栏JAVA高级架构

MySQL 调优/优化的 100 个建议

MySQL是一个强大的开源数据库。随着MySQL上的应用越来越多,MySQL逐渐遇到了瓶颈。这里提供 101 条优化 MySQL 的建议。有些技巧适合特定的安装...

3894
来自专栏用户2442861的专栏

MySQL学习笔记_如何选择合适的存储引擎

http://www.cnblogs.com/huligong1234/archive/2012/06/10/2544154.html

873
来自专栏跟着阿笨一起玩NET

SQL Server复制需要有实际的服务器名称才能连接到服务器

SQL Server 2005/2008 配置 Transactional  Replication 过程中,出现如下异常信息。

5481
来自专栏数据库

Java EE之旅07-数据库基础(1)

数据库概述 数据库(DataBase,简称DB):指长期保存在计算机的存储设备上,按照一定规则组织起来,可以被各种用户或应用共享的数据集合。(属于文件系统) 数...

22210
来自专栏CodingToDie

MySQL MVCC(多版本控制)

MySQL 提供了两种事务型的存储引擎:InnoDB 和 NDB Cluster 。另外还有一些第三方存储引擎也支持事务

3055
来自专栏Java架构师历程

MYSQL 浅谈MyISAM 存储引擎

       mysql中用的最多存储引擎就是innodb和myisam。做为Mysql的默认存储引擎,myisam值得我们学习一下,以下是我对《高性能MYSQ...

7962
来自专栏Danny的专栏

PL/SQL和SQLPLUS查询结果不一样——千万别忘记commit !

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

1722

扫码关注云+社区

领取腾讯云代金券