SQL server 2005中的锁(1)

在之前的一片随笔中,简单的说了一下SQL Server中的隔离级别。而SQL Server的隔离级别是通过锁的机制来实现的。现在深入一下,谈谈SQL
Server中的锁。

开始之前,先要定义一下前提:

1.隔离级别的实现其实就是在不同的资源上加锁。
2.对数据库的每一次访问(CRUD)我们称其为一个事务(在begin
tran,commit tran|rollback
tran中的语句块,或者即席查询--单条SQL)。不同的事务如果同时访问同一个数据库资源,会产生一系列的问题(见Sql Server隔离级别(1)
)。
3.大多数的事务在访问资源之前都会尝试对资源加上对应的锁(acquire lock,请求一个锁)。只有在Read
Uncommitted隔离级别以及在表上加了WITH(No Lock)
hint的Select语句不会请求锁。
3.读锁(共享锁S)不会阻塞读锁,读锁会阻塞写锁(独占锁X),写锁会阻塞读锁。
4.在一个事务中,只有在Repeatable
Read或更高的隔离级别下,会将select语句的读锁一直保持到事务结束(提交或回滚),Read
Committed隔离级别会造成不可重复读的原因就是在事务中的select语句执行完成后(事务没有执行完)读锁就直接释放了。

5.当前事务中的锁可以通过SELECT * FROM sys.dm_tran_locks 这个查询查看

====================================开始的分割线=========================================================

Server中存在不同粒度的锁:行锁,键锁,页锁,表锁等等,之所以要存在这些锁,是为了在并发性与系统开销间做一个平衡。粒度更小的锁将带了更好的并发性和更大的系统开销例如行锁的并发性好于表锁,不过系统的开销却大于表锁。

a.获取表锁时:整张表包括未被查询使用的行将会被锁住,其他试图请求表上不兼容锁的查询都将等待。此时系统中只需要维护一个表锁即可。

b.获取行锁时:只有查询使用到的行会被锁住,请求其他行的查询可以顺利的进行。此时并发性好于a,但是对于每一个被使用的行系统都要维护一个锁,系统开销增加。

一下是一些锁的资源,这里先大概了解下就好























资源

说明

RID

行标识,用于锁住整个表的其中一行

KEY

通过在索引来锁住行,用于在序列化的隔离级别中锁住一个行的范围。

PAGE

8kb大小的数据页或者索引页

EXTENT

一组连续的八页,例如数据页或索引页。

TABLE

包括所有数据和索引的整个表。

DATABASE

数据库。

在一个SQL执行的时候,或多或少都会请求上述的资源,而对这些资源的请求可以看成是对这些资源上的锁的请求。只有成功的请求到这些资源上的锁或者说成功的在当前的事务中对这些资源加锁,才能对这些资源进行CRUD的操作。

对于不同的资源请求,SQL Server会应用不同的锁模式来试图在资源上加锁。经常接触到的锁模式如下:

共享锁(S):
请求到共享锁(读锁)允许事务可以读取某一个资源,此时其他的事务将请求不到该资源的独占锁(写锁),但是可以请求到共享锁。在资源读取完成后,共享锁将会释放(即使此时事务还没有结束)。除非事务在read
repeatable或者更高的隔离级别下执行,或者通过使用sql
hint在事务执行时一直持有锁(例如WITH(HOLDLOCK)),共享锁将持续到事务结束。

更新锁(U):
更新锁的存在是为了避免在并发环境下不同事务的Update语句造成死锁。

一个典型的Update操作将经过以下两步:
步骤1.获取将要更新的资源的共享锁将数据读出
步骤2.将共享锁转换成独占锁并将更新的数据写入到资源中

考虑到并发环境,两个事务同时到达步骤1,获取到同一资源的共享锁(共享锁之间不会阻塞)。然后两个事务都开始将试图共享锁转换成独占锁,发现无法转换,因为此时两个事务同时还保留了对资源的共享锁,而共享锁是会阻塞独占锁的。两个事务都等待对方的共享锁释放,于是就产生了死锁。

上述的Update模式中,一个Update操作将不再是原子操作,因为在步骤1到步骤2之间会被其他的事务影响。所以需要引入更新锁来替换步骤1中获取的共享锁,更新锁是互斥的,所以将不会出现两个Update操作同时获取到更新锁的情况。只可能是一个事务获取到了更新锁,而另一个事务只好等待更新锁的释放。

在Update用更新锁来替代共享锁来查找资源将防止并发更新产生死锁,并且由于更新锁可以和共享锁兼容,所以其他的事务依然可以在资源上放置共享锁。

独占锁(X)
独占锁阻塞其他的所有锁,无法读取或者修改加了独占锁的资源。

意向锁(IS,IX,SIX)
一个意向锁表明Sql
Server希望获取当前资源的层次更低的共享锁或者独占锁。例如,表上的IS锁(意向共享锁)表明事务将要表中的页或者行(粒度比表更小的资源)上放置共享锁,而放置意向锁将避免随后的其他事务在表上获取到独占锁。意向锁能够提高性能,因为当一个事务要获取一个表的锁的时候不用再去检查表的资资源(页或行)是否被锁住了,
而只需要检查表上是否有意向锁就行了。

时间: 2024-10-10 14:35:09

SQL server 2005中的锁(1)的相关文章

SQL Server 2005中的分区表(六):将已分区表转换成普通表

在前面,我们介绍过怎么样直接创建一个分区表,也介绍过怎么将一个普通表转换成一个分区表.那么,这两种方式创建的表有什么区别呢?现在,我又最新地创建了两个表: 第一个表名为Sale,这个表使用的是<SQL Server 2005中的分区表(一):什么是分区表?为什么要用分区表?如何创建分区表?>中的方法创建的,在创建完之后,还为该表添加了一个主键. 第二个表名Sale1,这个表使用的是<SQL Server 2005中的分区表(三):将普通表转换成分区表>中的方法创建的,也就是先创建了

SQL Server 2005中更改sa的用户名和密码

修改数据库SA账号名称的代码如下: 代码如下: Alter LOGIN sa DISABLE Alter LOGIN sa WITH NAME = [systemAccount] "systemAccount" 为SA的新名称,执行完成后刷新一下右侧登录名即可看到修改成功的账号名称. SQL Server 2005修改sa用户密码的方法图文版 一.修改SQL Server 2005中sa用户密码的方法 1. 点击"开始 - 所有程序 - Microsoft SQL Serve

SQL Server 2005中的分区表(四):删除(合并)一个分区

在前面我们介绍过如何创建和使用一个分区表,并举了一个例子,将不 同年份的数据放在不同的物理分区表里.具体的分区方式为: 第1个小表:2010-1-1以前的数据(不包含2010-1-1). 第2个小表:2010-1-1(包含2010-1-1)到2010-12-31之间的数据. 第3个小表:2011-1-1(包含2011-1-1)到2011-12-31之间的数据. 第4个小表:2012-1-1(包含2012-1-1)到2012-12-31之间的数据. 第5个小表:2013-1-1(包含2013-1-

SQL Server 2005中的分区表(一):什么是分区表?为什么要用分区表?如何创建分区表?(转)

如果你的数据库中某一个表中的数据满足以下几个条件,那么你就要考虑创建分区表了. 1.数据库中某个表中的数据很多.很多是什么概念?一万条?两万条?还是十万条.一百万条?这个,我觉得是仁者见仁.智者见智的问题.当然数据表中的数据多到查询时明显感觉到数据很慢了,那么,你就可以考虑使用分区表了.如果非要我说一个数值的话,我认为是100万条. 2.但是,数据多了并不是创建分区表的惟一条件,哪怕你有一千万条记录,但是这一千万条记录都是常用的记录,那么最好也不要使用分区表,说不定会得不偿失.只有你的数据是分段

SQL Server 2005中的分区表(五):添加一个分区(转)

所谓天下大事,分久必合,合久必分,对于分区表而言也一样.前面我们介绍过如何删除(合并)分区表中的一个分区,下面我们介绍一下如何为分区表添加一个分区. 为分区表添加一个分区,这种情况是时常会 发生的.比如,最初在数据库设计时,只预计了存放3年的数据,可是到了第4天怎么办?这样的话,我们就可以为分区表添加一个分区,让它把新的数据放在新的分区里.再比如,最初设计时,一个分区用于存放一年的数据,结果在使用的时候才发现,一年的数据太多,想将一个分区中的数据分为两个分区来存放. 遇到这种情况,就必须要为分区

SQL Server 2005中的分区表(三):将普通表转换成分区表(转)

在设计数据库时,经常没有考虑到表分区的问题,往往在数据表承重的负担越来越重时,才会考虑到分区方式,这时,就涉及到如何将普通表转换成分区表的问题了. 那么,如何将一个普通表转换成一个分区表 呢?说到底,只要将该表创建一个聚集索引,并在聚集索引上使用分区方案即可. 不过,这回说起来简单,做起来就复杂了一点.还是接着上面的例子,我们先使用以下SQL语句将原有的Sale表删除. --删除原来的数据表 drop table Sale 然后使用以下SQL语句创建一个新的普通表,并在这个表里插入一些数据. -

SQL Server 2005中的分区表(四):删除(合并)一个分区(转)

在前面我们介绍过如何创建和使用一个分区表,并举了一个例子,将不 同年份的数据放在不同的物理分区表里.具体的分区方式为: 第1个小表:2010-1-1以前的数据(不包含2010-1-1). 第2个小表:2010-1-1(包含2010-1-1)到2010-12-31之间的数据. 第3个小表:2011-1-1(包含2011-1-1)到2011-12-31之间的数据. 第4个小表:2012-1-1(包含2012-1-1)到2012-12-31之间的数据. 第5个小表:2013-1-1(包含2013-1-

SQL Server 2005中的分区表(五):添加一个分区

所谓天下大事,分久必合,合久必分,对于分区表而言也一样.前面我们介绍过如何删除(合并)分区表中的一个分区,下面我们介绍一下如何为分区表添加一个分区. 为分区表添加一个分区,这种情况是时常会 发生的.比如,最初在数据库设计时,只预计了存放3年的数据,可是到了第4天怎么办?这样的话,我们就可以为分区表添加一个分区,让它把新的数据放在新的分区里.再比如,最初设计时,一个分区用于存放一年的数据,结果在使用的时候才发现,一年的数据太多,想将一个分区中的数据分为两个分区来存放. 遇到这种情况,就必须要为分区

SQL Server 2005中的分区表(二):如何添加、查询、修改分区表中的数据

在创建完分区表后,可以向分区表中直接插入数据,而不用去管它这些数据放在哪个物理上的数据表中.接上篇文章,我们在创建好的分区表中插入几条数据: 从以上代码中可以看出,我们一共在数据表中插入了13条数据,其中第1至3条数据是插入到第1个物理分区表中的:第4.5条数据是插入到第2个物理分区表中的:第6至8条数据是插入到第3个物理分区表中的:第9至11条数据是插入到第4个物理分区表中的:第12.13条数据是插入到第5个物理分区表中的. 从SQL语句中可以看出,在向分区表中插入数据方法和在普遍表中插入数据