有几个朋友留言建议结合例子来演示一下, 上篇已经说过锁的几种类型, 可以利用系统动态视图sys.dm_tran_locks查看到,重要的栏位如下:

resource_type 被锁的资源类型(Database, FILE, Object,PAGE,KEY,EXTENT,RID,APPLICATION,METADATA,HOBT,APPOCATION_UNIT)
request_mode 锁的类型(共享锁,更新锁,排它锁, 架构锁等)
resource_description 资源描述
request_session_id Request session ID

一: 下面以AdventureWorks2008为示例数据库做简要的说明,

过滤掉一般的数据库的共享锁, 作为示例必须要看到锁, 所以用WITH(HOLDLOCK)来保持锁.

1. Shared locks (S) 共享锁

  1. USE AdventureWorks2008
  2. BEGIN TRAN
  3. select * from Sales.SalesOrderHeader WITH(HOLDLOCK)
  4. where SalesOrderID='43662'
  5. SELECT resource_type, request_mode, resource_description,
  6. request_session_id, DB_NAME(resource_database_id)as resource_database
  7. FROM   sys.dm_tran_locks
  8. WHERE  resource_type <> 'DATABASE'
  9. --ROLLBACK TRAN

在事务回滚之前, 查看锁的类型:

其他session对Table只读, 不能更新, 在开一个新的session测试:

  1. select * from Sales.SalesOrderHeader  where SalesOrderID='43662'
  2. go
  3. update Sales.SalesOrderHeader set OrderDate=GETDATE() where SalesOrderID='43662'

select可以正常执行, update语句一直处于等待状态, 等待上面的session释放锁.

2. Update locks (U): 更新锁是共享锁和独占锁的组合.用UPDLOCK保持更新锁

  1. USE AdventureWorks2008
  2. BEGIN TRAN
  3. select * from Sales.SalesOrderHeader WITH(UPDLOCK)
  4. where SalesOrderID='43662'
  5. SELECT resource_type, request_mode, resource_description,
  6. request_session_id,DB_NAME(resource_database_id)as resource_database
  7. FROM   sys.dm_tran_locks
  8. WHERE  resource_type <> 'DATABASE'
  9. ROLLBACK TRAN

查看到锁的信息:

3.Exclusive locks (X): 独占锁是为了锁定数据被一个session修改的数据, 而不能够被另外的session修改. 只能指定NOLOCK来读取.

  1. USE AdventureWorks2008
  2. BEGIN TRAN
  3. update Sales.SalesOrderHeader set ShipDate=GETDATE()
  4. where SalesOrderID='43662'
  5. SELECT resource_type, request_mode, resource_description,
  6. request_session_id,DB_NAME(resource_database_id)as resource_database--,*
  7. FROM   sys.dm_tran_locks
  8. WHERE  resource_type <> 'DATABASE'
  9. ROLLBACK TRAN

查看锁:

4.Intent locks (I): 意向锁用于建立锁的层次结构. 意向锁包含三种类型:意向共享 (IS)、意向排他 (IX) 和意向排他共享 (SIX)。

数据库引擎使用意向锁来保护共享锁(S 锁)或排他锁(X 锁)放置在锁层次结构的底层资源上。 意向锁之所以命名为意向锁,是因为在较低级别锁前可获取它们,因此会通知意向将锁放置在较低级别上。

意向锁有两种用途:

防止其他事务以会使较低级别的锁无效的方式修改较高级别资源。

提高数据库引擎在较高的粒度级别检测锁冲突的效率。

5. Schema locks (Sch): 架构锁

Schema stability lock(Sch-S): 保持架构稳定性,用在生成执行计划时,不会阻止对数据的访问.

Schema modification lock (Sch-M):用在DDL操作时.当架构正在被改变时, 阻止对对象数据的访问.

  1. USE AdventureWorks2008
  2. BEGIN TRAN
  3. CREATE TABLE MyTable (ID INT, NAME VARCHAR(20),COUNTRY VARCHAR(15))
  4. SELECT resource_type, request_mode, resource_description
  5. FROM   sys.dm_tran_locks
  6. WHERE  resource_type <> 'DATABASE' order by request_mode
  7. ROLLBACK TRAN

6. Bulk Update locks (BU)

数据库引擎在将数据大容量复制到表中时使用了大容量更新 (BU) 锁, 并指定了 TABLOCK 提示或使用 sp_tableoption 设置了 table lock on bulk load 表选项. 大容量更新锁(BU 锁)允许多个线程将数据并发地大容量加载到同一表, 同时防止其他不进行大容量加载数据的进程访问该表.

7. Key - Range locks

在使用可序列化事务隔离级别时, 对于 Transact-SQL 语句读取的记录集, 键范围锁可以隐式保护该记录集中包含的行范围. 键范围锁可防止幻读. 通过保护行之间键的范围, 它还防止对事务访问的记录集进行幻像插入或删除.

二: 死锁与死锁解除

1. 死锁

使用或管理数据库都不可避免的涉及到死锁. 一旦发生死锁, 数据相互等待对方资源的释放,会阻止对数据的访问, 严重会造成DB挂掉. 当资源被锁定, 无法被访问时, 可以终止访问DB的那个session来达到解锁的目的(即 Kill掉造成锁的那个进程).

在两个或多个任务中,如果每个任务锁定了其他任务试图锁定的资源,此时会造成这些任务永久阻塞,从而出现死锁。 例如:

事务 A 获取了行 1 的共享锁。

事务 B 获取了行 2 的共享锁。

现在,事务 A 请求行 2 的排他锁,但在事务 B 完成并释放其对行 2 持有的共享锁之前被阻塞。

现在,事务 B 请求行 1 的排他锁,但在事务 A 完成并释放其对行 1 持有的共享锁之前被阻塞。

事务 B 完成之后事务 A 才能完成,但是事务 B 由事务 A 阻塞。该条件也称为循环依赖关系: 事务 A 依赖于事务 B,事务 B 通过对事务 A 的依赖关系关闭循环。

除非某个外部进程断开死锁,否则死锁中的两个事务都将无限期等待下去。 Microsoft SQL Server 数据库引擎死锁监视器定期检查陷入死锁的任务。 如果监视器检测到循环依赖关系,将选择其中一个任务作为牺牲品,然后终止其事务并提示错误。 这样,其他任务就可以完成其事务。 对于事务以错误终止的应用程序,它还可以重试该事务,但通常要等到与它一起陷入死锁的其他事务完成后执行。

2. 死锁检测

2.1 SQL Server 数据库引擎自动检测 SQL Server 中的死锁循环。数据库引擎选择一个会话作为死锁牺牲品,然后终止当前事务(出现错误)来打断死锁。

2.2 查看DMV: sys.dm_tran_locks

2.3 SQL Server Profiler能够直观的显示死锁的图形事件.

三: 锁兼容性

锁兼容性控制多个事务能否同时获取同一资源上的锁。 如果资源已被另一事务锁定,则仅当请求锁的模式与现有锁的模式相兼容时,才会授予新的锁请求。 如果请求锁的模式与现有锁的模式不兼容,则请求新锁的事务将等待释放现有锁或等待锁超时间隔过期。 例如,没有与排他锁兼容的锁模式。 如果具有排他锁(X 锁),则在释放排他锁(X 锁)之前,其他事务均无法获取该资源的任何类型(共享、更新或排他)的锁。 另一种情况是,如果共享锁(S 锁)已应用到资源,则即使第一个事务尚未完成,其他事务也可以获取该项的共享锁或更新锁(U 锁)。 但是,在释放共享锁之前,其他事务无法获取排他锁。

点击查看大图

四: 总结

锁的原理比较抽象,对用户来说是透明的,不用过多的关注. 应用程序一般不直接请求锁. 锁由数据库引擎的一个部件(称为“锁管理器”)在内部管理. 当数据库引擎实例处理Transact-SQL 语句时, 数据库引擎查询处理器会决定将要访问哪些资源. 查询处理器根据访问类型和事务隔离级别设置来确定保护每一资源所需的锁的类型. 然后, 查询处理器将向锁管理器请求适当的锁. 如果与其他事务所持有的锁不会发生冲突, 锁管理器将授予该锁.

原文:http://www.poluoluo.com/jzxy/201011/98759.html

SQL Server中表锁定的原理及解锁演示的更多相关文章

  1. SQL Server AlwaysOn架构及原理

    SQL Server AlwaysOn架构及原理 SQL Server2012所支持的AlwaysOn技术集中了故障转移群集.数据库镜像和日志传送三者的优点,但又不相同.故障转移群集的单位是SQL实例 ...

  2. SQL Server 的锁定和阻塞

    本帖提供两种做法,可避免在 SQL Server 事务锁定时产生的不正常或长时间阻塞,让用户和程序也无限期等待,甚至引起 connection pooling 连接数超过容量. 所谓的「阻塞」,是指当 ...

  3. [转]SQL Server表锁定原理以及如何解除锁定

    2010年10月13日 12:46 来源:部松昌的博客 作者:部松昌 编辑:胡铭娅 一: 下面以AdventureWorks2008为示例数据库做简要的说明,过滤掉一般的数据库的共享锁, 作为示例必须 ...

  4. 查看SQL Server中的锁表及解锁

    有时候系统很慢,有可能是SQL Server数据库中某些表被锁定 --查看被锁表(需查多几次,有些临时锁很快会自动解锁): SELECT request_session_id AS spid, OBJ ...

  5. 深入理解SQL Server数据库Select查询原理(一)

    使用SQL Server十年有余,但是一直对其Select查询机制原理一致不明,直到最近有个通讯录表,很简单的一张表(但因简单,所以当时并没有考虑按部门排序问题),结果想查询某个单位所有部门(不重复) ...

  6. 转!!sql server 数据库 索引的原理与应用

    索引的概念 索引的用途:我们对数据查询及处理速度已成为衡量应用系统成败的标准,而采用索引来加快数据处理速度通常是最普遍采用的优化方法. 索引是什么:数据库中的索引类似于一本书的目录,在一本书中使用目录 ...

  7. SQL Server 索引碎片产生原理重建索引和重新组织索引

    数据库存储本身是无序的,建立了聚集索引,会按照聚集索引物理顺序存入硬盘.既键值的逻辑顺序决定了表中相应行的物理顺序 多数情况下,数据库读取频率远高于写入频率,索引的存在 为了读取速度牺牲写入速度 页 ...

  8. 查看Sql Server被锁的表以及解锁

    查看被锁表: select spId from master..SysProcesses where db_Name(dbID) = '数据库名称' and spId <> @@SpId ...

  9. SQL Server被锁的表以及解锁

    select   request_session_id   spid,OBJECT_NAME(resource_associated_entity_id) tableName   from   sys ...

随机推荐

  1. adformsctl.sh 与 adformsrvctl.sh, 10.1.2 及10.1.3

    参考 http://blog.csdn.net/cai_xingyun/article/details/40393885 ,  adformsctl.sh 是开启forms oc4j ,  根据之后的 ...

  2. Android studio使用git-android学习之旅(79)

    首先我参考了hello_my_show和梦痕_sky的博客,表示感谢 android studio对于git的支持是很好的,这节课我们拉讲解怎么使用git可视化工具来clone project和提交修 ...

  3. 反对网抄,没有规则可以创建目标"install" 靠谱解答

    在ubuntu下遇到这个问题,原因其实很简单,你不能用WINDWOS下的方法用图形方式打开,然后点了一下按扭"解压缩",生成了一个文件夹. 的确,这个文件夹看起来和正常的没有什么区 ...

  4. Errors running builder 'Integrated External Tool Builder' on project xxx

    出现这样的提示,表明你的项目的Builder项出了问题. 解决方法是: 右键项目选择"Properties",再选择"Builders",删除丢失的builde ...

  5. Leetcode_141_Linked List Cycle

    本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/42833739 Given a linked list, d ...

  6. kettle简介(整体架构,运行方式,使用方法)

    项目负责人Matt的说法:把各种数据放到一个壶里,然后呢,以一种你希望的格式流出.呵呵,外国人都很有联想力.看了提供的文档,然后对发布程序的简单试用后,可以很清楚得看到Kettle的四大块: Chef ...

  7. 算法精解:最小二乘法C实现

    计量经济学研究的直接目的是确定总体回归函数Yi=B1+B2Xi+ui,然而能够得到的只是来自总体的若干样本的观测值,要用样本信息建立的样本回归函数尽可能"接近"地去估计总体回归函数 ...

  8. 一个简单的基于 DirectShow 的播放器 1(封装类)

    DirectShow最主要的功能就是播放视频,在这里介绍一个简单的基于DirectShow的播放器的例子,是用MFC做的,今后有机会可以基于该播放器开发更复杂的播放器软件. 注:该例子取自于<D ...

  9. CMake命令行添加编译参数

    CMake命令行添加编译参数 学习自 coroserver 例程: https://github.com/windoze/coroserver coroserver 是一个应用 Boost.Asio ...

  10. Effective STL 为包含指针的关联容器指定比较类型

    // 为包含指针的关联容器指定比较类型.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" #include <set> #incl ...