您的位置:首页 > 数据库

SQL Server数据库表锁定原理以及如何解除表的锁定--示例演示

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

resource_type被锁的资源类型(Database,FILE,Object,PAGE,KEY,EXTENT,RID,APPLICATION,METADATA,HOBT,APPOCATION_UNIT)
request_mode锁的类型(共享锁,更新锁,排它锁,架构锁等)
resource_description资源描述
request_session_idRequestsessionID
一:下面以AdventureWorks2008为示例数据库做简要的说明,过滤掉一般的数据库的共享锁,作为示例必须要看到锁,所以用WITH(HOLDLOCK)来保持锁.

1.Sharedlocks(S)共享锁

USEAdventureWorks2008

BEGINTRAN
select*fromSales.SalesOrderHeaderWITH(HOLDLOCK)
whereSalesOrderID='43662'

SELECTresource_type,request_mode,resource_description,request_session_id,DB_NAME(resource_database_id)asresource_database
FROMsys.dm_tran_locks
WHEREresource_type<>'DATABASE'

--ROLLBACKTRAN


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





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

select*fromSales.SalesOrderHeaderwhereSalesOrderID='43662'

go
updateSales.SalesOrderHeadersetOrderDate=GETDATE()whereSalesOrderID='43662'


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

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

USEAdventureWorks2008

BEGINTRAN
select*fromSales.SalesOrderHeaderWITH(UPDLOCK)
whereSalesOrderID='43662'

SELECTresource_type,request_mode,resource_description,request_session_id,DB_NAME(resource_database_id)asresource_database
FROMsys.dm_tran_locks
WHEREresource_type<>'DATABASE'

ROLLBACKTRAN


查看到锁的信息:





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

USEAdventureWorks2008

BEGINTRAN

updateSales.SalesOrderHeadersetShipDate=GETDATE()whereSalesOrderID='43662'

SELECTresource_type,request_mode,resource_description,request_session_id,DB_NAME(resource_database_id)asresource_database--,*
FROMsys.dm_tran_locks
WHEREresource_type<>'DATABASE'

ROLLBACKTRAN


查看锁:





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

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

意向锁有两种用途:

防止其他事务以会使较低级别的锁无效的方式修改较高级别资源。
提高数据库引擎在较高的粒度级别检测锁冲突的效率。

5.Schemalocks(Sch):架构锁

Schemastabilitylock(Sch-S):保持架构稳定性,用在生成执行计划时,不会阻止对数据的访问.
Schemamodificationlock(Sch-M):用在DDL操作时.当架构正在被改变时,阻止对对象数据的访问.

USEAdventureWorks2008

BEGINTRAN
CREATETABLEMyTable(IDINT,NAMEVARCHAR(20),COUNTRYVARCHAR(15))

SELECTresource_type,request_mode,resource_description
FROMsys.dm_tran_locks
WHEREresource_type<>'DATABASE'orderbyrequest_mode

ROLLBACKTRAN



6.BulkUpdatelocks(BU)

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

7.Key-Rangelocks

在使用可序列化事务隔离级别时,对于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的依赖关系关闭循环。

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

2.死锁检测

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

2.2查看DMV:sys.dm_tran_locks

2.3SQLServerProfiler能够直观的显示死锁的图形事件.





三:锁兼容性

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













四:总结

锁的原理比较抽象,对用户来说是透明的,不用过多的关注.应用程序一般不直接请求锁.锁由数据库引擎的一个部件(称为“锁管理器”)在内部管理.当数据库引擎实例处理Transact-SQL语句时,数据库引擎查询处理器会决定将要访问哪些资源.查询处理器根据访问类型和事务隔离级别设置来确定保护每一资源所需的锁的类型.然后,查询处理器将向锁管理器请求适当的锁.如果与其他事务所持有的锁不会发生冲突,锁管理器将授予该锁.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐