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

2010年10月13日 12:46 来源:部松昌的博客 作者:部松昌 编辑:胡铭娅

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

  1. Shared locks (S) 共享锁

USE AdventureWorks2008

BEGIN TRAN
select * from Sales.SalesOrderHeader WITH(HOLDLOCK)
where SalesOrderID=‘43662‘ 

SELECT resource_type, request_mode, resource_description,request_session_id, DB_NAME(resource_database_id)as resource_database
FROM   sys.dm_tran_locks
WHERE  resource_type <> ‘DATABASE‘

--ROLLBACK TRAN

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

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

select * from Sales.SalesOrderHeader  where SalesOrderID=‘43662‘

go
update Sales.SalesOrderHeader set OrderDate=GETDATE() where SalesOrderID=‘43662‘

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

  

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

USE AdventureWorks2008

BEGIN TRAN
select * from Sales.SalesOrderHeader WITH(UPDLOCK)
where SalesOrderID=‘43662‘ 

SELECT resource_type, request_mode, resource_description,request_session_id,DB_NAME(resource_database_id)as resource_database
FROM   sys.dm_tran_locks
WHERE  resource_type <> ‘DATABASE‘

ROLLBACK TRAN

  查看到锁的信息:

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

USE AdventureWorks2008

BEGIN TRAN

update Sales.SalesOrderHeader set ShipDate=GETDATE() where SalesOrderID=‘43662‘

SELECT resource_type, request_mode, resource_description,request_session_id,DB_NAME(resource_database_id)as resource_database--,*
FROM   sys.dm_tran_locks
WHERE  resource_type <> ‘DATABASE‘

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操作时.当架构正在被改变时, 阻止对对象数据的访问.

USE AdventureWorks2008

BEGIN TRAN
CREATE TABLE MyTable (ID INT, NAME VARCHAR(20),COUNTRY VARCHAR(15))

SELECT resource_type, request_mode, resource_description
FROM   sys.dm_tran_locks
WHERE  resource_type <> ‘DATABASE‘ order by request_mode

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 语句时, 数据库引擎查询处理器会决定将要访问哪些资源. 查询处理器根据访问类型和事务隔离级别设置来确定保护每一资源所需的锁的类型. 然后, 查询处理器将向锁管理器请求适当的锁. 如果与其他事务所持有的锁不会发生冲突, 锁管理器将授予该锁.

时间: 2024-12-29 07:33:51

[转]SQL Server表锁定原理以及如何解除锁定的相关文章

[转]如何将SQL Server表驻留内存和检测

注意这个功能在SQL2005后已经废弃,因为SQL2005会自动管理哪些表常驻内存. 将SQL Server数据表驻留内存是SQL Server提供的一项功能,在一般小型系统的开发过程中估计很少会涉及到.这里整理了相关文档资料,演示如何把SQL Server中一个表的所有数据都放入内存中,实现内存数据库,提高实时性. 1, DBCC PINTABLE Marks a table to be pinned, which means Microsoft SQL Server does not flu

在一个SQL Server表中的多个列找出最大值

在一个SQL Server表中一行的多个列找出最大值 有时候我们需要从多个相同的列里(这些列的数据类型相同)找出最大的那个值,并显示 这里给出一个例子 IF (OBJECT_ID('tempdb..##TestTable') IS NOT NULL) DROP TABLE ##TestTable CREATE TABLE ##TestTable ( ID INT IDENTITY(1,1) PRIMARY KEY, Name NVARCHAR(40), UpdateByApp1Date DATE

SQL Server表分区详解

原文:SQL Server表分区详解 什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里. 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这些小文件放在不同的磁盘下由多个cpu进行处理.这样文件的大小随着拆分而减小,还得到硬件系统的加强,自然对我们操作数据是大大有利的. 所以大数据量的数据表,对分区的需要还是必要的,因为它可以提高select效率,还可以对历史数据经行区分存档等.但是数据量少的数据就不要凑这个热

[转载]在SQL Server 中,如何实现DBF文件和SQL Server表之间的导入或者导出?

原来使用SQL Server 2000数据库,通过DTS工具很方便地在SQL Server和DBF文件之间进行数据的导入和导出,现在安装了SQL Server2005之后,发现其提供的“SQL Server导入导出向导”中的数据源没有原来的丰富,缺少对DBF文件的支持. 1.右击数据库,选择“任务”>“导入数据”,打开“SQL Server导入和导出向导”对话框.2.在“数据源”中选择Microsoft OLE DB Provider for Visual FoxPro,单击“属性”按钮,打开“

导出 SQL SERVER 表中数据为脚本

ALTER PROCEDURE [dbo].[Usp_OutputData] @tablename sysname, @outputIdentitycolumn int AS declare @column varchar(3000) declare @columndata varchar(8000) declare @sql varchar(8000) declare @xtype tinyint declare @name sysname declare @objectId int decl

SQL Server 2012内部原理及故障排除(专栏)

PROFESSIONAL SQL SERVER? 2012 INTERNALS AND TROUBLESHOOTING一书(可从这里下载),觉得内容很不错.自己也想对SQL Server 2012有个较全面的理解,于是边看边翻译,并将重点内容发表在博客中.下面是相关博客的链接,希望能够给大家带来一点帮助.因个人能力有限,若有翻译不妥之处,欢迎指正和交流! 第一部分  内部原理(INTERNALS) 第一章 SQL Server 架构 数据库事务:          http://blog.csd

SQL SERVER表不能修改表结构的处理方法

SQL SERVER表提示不能修改表结构,这究竟是什么原因呢?下面就为您介绍处理该问题的方法,如果您在SQL SERVER表修改方面遇到过问题,不妨一看. 新装的SQL SERVER 2008,打开原来SQL SERVER 2008中建立的表,现在想增加一些字段,在保存时提示错误,无法保存. 刚开始以为是SQL SERVER 2008与2005的不兼容,后来发现在SQL SERVER 2008中新建的SQL SERVER表也存在无法修改表结构,也就是无法修改字段名和增加字段名. 提示是:不允许保

sql server 表变量存储临时查询数据

对于使用sql server 编写存储过程或者类似的sql 查询的时候我们使用表变量进行临时数据的存储,可以方便我们进行下来的数据处理 表变量的使用类似如下: declare @userinfo table(id nvarchar(50),name nvarchar(50)); insert into @userinfo(id,name) select classid,classname from classfirstselect * from @userinfo 以上的操作就是进行查询clas

SQL SERVER 表分区

一 .SQL SERVER 表分区介绍: SQL Server  引入的表分区技术,让用户能够把数据分散存放到不同的物理磁盘中,提高这些磁盘的并行处理性能以优化查询性能…… 二 .SQL SERVER 数据库表分区由三个步骤来完成: 1.创建分区函数 2.创建分区架构 3.对表进行分区 基于缓存更新机制,我使用时间来进行分区,这里大家根据业务的要求使用合适的字段来作为分区 创建数据库分区文件数量,这里存储一年的数据分成十二个分区,需要现在D盘建立好Data 的文件夹 里面包含Primary 文件