`

MS SQL的锁

    博客分类:
  • SQL
 
阅读更多

 

锁是网络数据库中的一个非常重要的概念,它主要用于多用户环境下保证数据库完整性和一致性。各种大型数据库所采用的锁的基本理论是一致的,但在具体实现上 各有差别。目前,大多数数据库管理系统都或多或少具有自我调节、自我管理的功能,因此很多用户实际上不清楚锁的理论和所用数据库中锁的具体实现。  

Microsoft SQL Server(以下简称SQL Server)作为一种中小型数据库管理系统,已经得到了广泛的应用,该系统更强调由系统来管理锁。在用户有SQL请求时,系统分析请求,自动在满足锁定 条件和系统性能之间为数据库加上适当的锁,同时系统在运行期间常常自动进行优化处理,实行动态加锁。对于一般的用户而言,通过系统的自动锁定管理机制基本 可以满足使用要求,但如果对数据安全、数据库完整性和一致性有特殊要求,就必须自己控制数据库的锁定和解锁,这就需要了解SQL Server的锁机制,掌握数据库锁定方法。  

锁的多粒度性以及锁升级  

数据库中的锁是指一种软件机制,用来指示某 个用户(也即进程会话,下同)已经占用了某种资源,从而防止其他用户做出影响本用户的数据修改或导致数据库数据的非完整性和非一致性。这儿所谓资源,主要 指用户可以操作的数据行、索引以及数据表等。根据资源的不同,锁有多粒度(multigranular)的概念,也就是指可以锁定的资源的层次。SQL Server中能够锁定的资源粒度包括:数据库、表、区域、页面、键值(指带有索引的行数据)、行标识符(RID,即表中的单行数据)。  

采 用多粒度锁的重要用途是用来支持并发操作和保证数据的完整性。SQL Server根据用户的请求,做出分析后自动给数据库加上合适的锁。假设某用户只操作一个表中的部分行数据,系统可能会只添加几个行锁(RID)或页面 锁,这样可以尽可能多地支持多用户的并发操作。但是,如果用户事务中频繁对某个表中的多条记录操作,将导致对该表的许多记录行都加上了行级锁,数据库系统 中锁的数目会急剧增加,这样就加重了系统负荷,影响系统性能。因此,在数据库系统中,一般都支持锁升级(lock escalation)。所谓锁升级是指调整锁的粒度,将多个低粒度的锁替换成少数的更高粒度的锁,以此来降低系统负荷。在SQL Server中当一个事务中的锁较多,达到锁升级门限时,系统自动将行级锁和页面锁升级为表级锁。特别值得注意的是,在SQL Server中,锁的升级门限以及锁升级是由系统自动来确定的,不需要用户设置。  

锁的模式和兼容性  

在数据库中加锁时,除了可以对不同的资源加锁,还可以使用不同程度的加锁方式,即锁有多种模式,SQL Server中锁模式包括:  

1.共享锁  

SQL Server中,共享锁用于所有的只读数据操作。共享锁是非独占的,允许多个并发事务读取其锁定的资源。默认情况下,数据被读取后,SQL Server立即释放共享锁。例如,执行查询“SELECT * FROM my_table”时,首先锁定第一页,读取之后,释放对第一页的锁定,然后锁定第二页。这样,就允许在读操作过程中,修改未被锁定的第一页。但是,事务 隔离级别连接选项设置和SELECT语句中的锁定设置都可以改变SQL Server的这种默认设置。例如,“ SELECT * FROM my_table HOLDLOCK”就要求在整个查询过程中,保持对表的锁定,直到查询完成才释放锁定。  

2.修改锁  

修 改锁在修改操作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象。因为使用共享锁时,修改数据的操作分为两步,首先获得一 个共享锁,读取数据,然后将共享锁升级为独占锁,然后再执行修改操作。这样如果同时有两个或多个事务同时对一个事务申请了共享锁,在修改数据的时候,这些 事务都要将共享锁升级为独占锁。这时,这些事务都不会释放共享锁而是一直等待对方释放,这样就造成了死锁。如果一个数据在修改前直接申请修改锁,在数据修 改的时候再升级为独占锁,就可以避免死锁。修改锁与共享锁是兼容的,也就是说一个资源用共享锁锁定后,允许再用修改锁锁定。  

3.独占锁  

独占锁是为修改数据而保留的。它所锁定的资源,其他事务不能读取也不能修改。独占锁不能和其他锁兼容。  

4.结构锁  

结构锁分为结构修改锁(Sch-M)和结构稳定锁(Sch-S)。执行表定义语言操作时,SQL Server采用Sch-M锁,编译查询时,SQL Server采用Sch-S锁。  

5.意向锁  

意 向锁说明SQL Server有在资源的低层获得共享锁或独占锁的意向。例如,表级的共享意向锁说明事务意图将独占锁释放到表中的页或者行。意向锁又可以分为共享意向锁、 独占意向锁和共享式独占意向锁。共享意向锁说明事务意图在共享意向锁所锁定的低层资源上放置共享锁来读取数据。独占意向锁说明事务意图在共享意向锁所锁定 的低层资源上放置独占锁来修改数据。共享式独占锁说明事务允许其他事务使用共享锁来读取顶层资源,并意图在该资源低层上放置独占锁。  

6.批量修改锁  

批量复制数据时使用批量修改锁。可以通过表的TabLock提示或者使用系统存储过程sp_tableoption“table lock on bulk load”选项设定批量修改锁。  

另外,SQL Server命令语句操作会影响锁定的方式,语句的组合也同样能产生不同的锁定,详情如下表:   

锁冲突及其防止办法  

在数据库系统中,死锁是指多个用户(进程)分别锁定了一个资源,并又试图请求锁定对方已经锁定的资源,这就产生了一个锁定请求环,导致多个用户(进程)都处于等待对方释放所锁定资源的状态。  

SQL Server中,系统能够自动定期搜索和处理死锁问题。系统在每次搜索中标识所有等待锁定请求的进程会话,如果在下一次搜索中该被标识的进程仍处于等待状态,SQL Server就开始递归死锁搜索。  

(上接第D21当搜索检测到锁定请求环时,系统将根据各进程会话的死锁优先级别来结束一个优先级最低的事务,此后,系统回滚该事务,并向该进程发出1205号错误信息。这样,其他事务就有可能继续运行了。死锁优先级的设置语句为:  

SET DEADLOCK_PRIORITY { LOW | NORMAL}  
 

其中LOW说明该进程会话的优先级较低,在出现死锁时,可以首先中断该进程的事务。另外,各进程中通过设置LOCK_TIMEOUT选项能够设置进程处于锁定请求状态的最长等待时间。该设置的语句:  

SET LOCK_TIMEOUT { timeout_period }  
 

其中,timeout_period以毫秒为单位。  

理解了死锁的概念,在应用程序中就可以采用下面的一些方法来尽量避免死锁了:  

1)合理安排表访问顺序。  

2)在事务中尽量避免用户干预,尽量使一个事务处理的任务少些。  

3)采用脏读技术。脏读由于不对被访问的表加锁,而避免了锁冲突。在客户机/服务器应用环境中,有些事务往往不允许读脏数据,但在特定的条件下,我们可以用脏读。  

4) 数据访问时域离散法。数据访问时域离散法是指在客户机/服务器结构中,采取各种控制手段控制对数据库或数据库中的对象访问时间段。主要通过以下方式实现合理安排后台事务的执行时间,采用工作流对后台事务进行统一管理。工作流在管理任务时,一方面限制同一类任务的线程数(往往限制为1个),防止资源过多占 用另一方面合理安排不同任务执行时序、时间,尽量避免多个后台任务同时执行,另外, 避免在前台交易高峰时间运行后台任务。  

5)数据存储空间离散法。数据存储空间离散法是指采取各种手段,将逻辑上在一个表中的数据分散到若干离散的空间上去,以便改善对表的访问性能。主要通过以下方法实现第一,将大表按行或列分解为若干小表第二,按不同的用户群分解。  

6) 使用尽可能低的隔离性级别。隔离性级别是指为保证数据库数据的完整性和一致性而使多用户事务隔离的程度,SQL92定义了4种隔离性级别:未提交读、提交 读、可重复读和可串行。如果选择过高的隔离性级别,如可串行,虽然系统可以因实现更好隔离性而更大程度上保证数据的完整性和一致性,但各事务间冲突而死锁 的机会大大增加,大大影响了系统性能。  

7)使用Bound ConnectionsBound connections 允许两个或多个事务连接共享事务和锁,而且任何一个事务连接要申请锁如同另外一个事务要申请锁一样,因此可以允许这些事务共享数据而不会有加锁的冲突。  

8)考虑使用乐观锁定或使事务首先获得一个独占锁定。一个最常见的死锁情况发生在系列号生成器中,它们通常是这样编写的:  

begin tran  

select new_id from keytab holdlock  

update keytab set new_id=new_id+l  

commit tran  
 
如果有两个用户在同时运行这一事务,他们都会得到共享锁定并保持它。当两个用户都试图得到keytab表的独占锁定时,就会进入死锁。为了避免这种情况的发生,应将上述事务重写成如下形式:  

begin tran  

update keytab set new_id=new_id+l  

select new_id from keytab  

commit tran  
 

以这种方式改写后,只有一个事务能得到keytab的独占锁定,其他进程必须等到第一个事务的完成,这样虽增加了执行时间,但避免了死锁。  

如 果要求在一个事务中具有读取的可重复能力,就要考虑以这种方式来编写事务,以获得资源的独占锁定,然后再去读数据。例如,如果一个事务需要检索出 titles表中所有书的平均价格,并保证在update被应用前,结果不会改变,优化器就会分配一个独占的表锁定。考虑如下的SQL代码:  

begin tran  

update titles set title_idid=title_id .  

where 1=2  

if (selectavg(price)fromtitles)>$15  

begin  

/* perform some additional processing */  

end  

update titles set price=price*1.10  

where price<(select avg(price)from titles)  

commit tran  
 

在 这个事务中,重要的是没有其他进程修改表中任何行的price,或者说在事务结束时检索的值与事务开始时检索的值不同。这里的where子句看起来很奇 怪,但是不管你相信与否,这是迄今为止优化器所遇到的最完美有效的where子句,尽管计算出的结果总是false。当优化器处理此查询时,因为它找不到 任何有效的SARG,它的查询规划就会强制使用一个独占锁定来进行表扫描。此事务执行时,where子句立即得到一个false值,于是不会执行实际上的 扫描,但此进程仍得到了一个独占的表锁定。  

因为此进程现在已有一个独占的表锁,所以可以保证没有其他事务会修改任何数据行,能进行重 复读,且避免了由于holdlock所引起的潜在性死锁。但是,要避免死锁,不可能不付出代价。在使用表锁定来尽可能地减少死锁的同时,也增加了对表锁定 的争用。因此,在实现这种方法之前,你需要权衡一下:避免死锁是否比允许并发地对表进行访问更重要。  

手工加锁  

SQL Server系统中建议让系统自动管理锁,该系统会分析用户的SQL语句要求,自动为该请求加上合适的锁,而且在锁的数目太多时,系统会自动进行锁升级。如前所述,升级的门限由系统自动配置,并不需要用户配置。  

在 实际应用中,有时为了应用程序正确运行和保持数据的一致性,必须人为地给数据库的某个表加锁。比如,在某应用程序的一个事务操作中,需要根据一编号对几个 数据表做统计操作,为保证统计数据时间的一致性和正确性,从统计第一个表开始到全部表结束,其他应用程序或事务不能再对这几个表写入数据,这个时候,该应 用程序希望在从统计第一个数据表开始或在整个事务开始时能够由程序人为地(显式地)锁定这几个表,这就需要用到手工加锁(也称显式加锁)技术。  

SQL Server SQL语句(SELECTINSERTDELETEUPDATE)支持显式加锁。这4个语句在显式加锁的语法上类似,下面仅以SELECT语句为例给出语法:  

SELECT FROM [ WITH ]  
 

其中,指需要在该语句执行时添加在该表上的锁类型。所指定的锁类型有如下几种:  

1HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁。  

2NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可能读到未提交读的数据或脏数据,这个选项仅仅应用于SELECT语句。  

3. PAGLOCK:指定添加页面锁(否则通常可能添加表锁)。  

4READCOMMITTED:设置事务为读提交隔离性级别。  

5READPAST: 跳过已经加锁的数据行,这个选项将使事务读取数据时跳过那些已经被其他事务锁定的数据行,而不是阻塞直到其他事务释放锁,READPAST仅仅应用于READ COMMITTED隔离性级别下事务操作中的SELECT语句操作。  

6READUNCOMMITTED:等同于NOLOCK  

7REPEATABLEREAD:设置事务为可重复读隔离性级别。  

8ROWLOCK:指定使用行级锁。  

9SERIALIZABLE:设置事务为可串行的隔离性级别。  

10TABLOCK:指定使用表级锁,而不是使用行级或页面级的锁,SQL Server在该语句执行完后释放这个锁,而如果同时指定了HOLDLOCK,该锁一直保持到这个事务结束。  

11TABLOCKX:指定在表上使用排它锁,这个锁可以阻止其他事务读或更新这个表的数据,直到这个语句或整个事务结束。  

12. UPDLOCK :指定在读表中数据时设置修改锁(update lock)而不是设置共享锁,该锁一直保持到这个语句或整个事务结束,使用UPDLOCK的作用是允许用户先读取数据(而且不阻塞其他用户读数据),并且 保证在后来再更新数据时,这一段时间内这些数据没有被其他用户修改。  

由上可见,在SQL Server中可以灵活多样地为SQL语句显式加锁,若适当使用,我们完全可以完成一些程序的特殊要求,保证数据的一致性和完整性。对于一般使用者而言, 了解锁机制并不意味着必须使用它。事实上,SQL Server建议让系统自动管理数据库中的锁,而且一些关于锁的设置选项也没有提供给用户和数据库管理人员,对于特殊用户,通过给数据库中的资源显式加 锁,可以满足很高的数据一致性和可靠性要求,只是需要特别注意避免死锁现象的出现。

 

分享到:
评论

相关推荐

    MS SQL Server数据库锁技术研究.pdf

    MS SQL Server 数据库锁技术研究 MS SQL Server 数据库锁技术是数据库管理系统中的一种重要机制,用于确保数据库的安全、完整性和一致性。在多用户环境下,数据库锁机制可以防止用户之间的冲突,并确保数据的一致性...

    MS-SQL.rar_SQL 锁

    本文将深入探讨MS SQL中的几种锁类型、它们的概念、应用及操作方法。 一、锁的基本概念 锁是用来防止多个事务同时修改同一资源,从而避免数据不一致性的工具。在MS SQL中,锁有共享(S)和排他(X)两种基本模式。...

    MS-SQL 锁机制

    ### MS-SQL 锁机制详解 #### 一、锁的概述 锁是在多用户数据库系统中用于实现并发控制的关键机制之一。它可以帮助防止多个用户同时访问相同的数据时导致的数据不一致性问题。MS-SQL Server通过不同的锁机制来确保...

    浅谈MS-SQL锁机制

    MS-SQL锁机制是数据库管理系统中用于控制并发访问数据的关键技术。它确保了在多用户环境中数据的一致性和完整性,防止了数据的不一致性和死锁情况。在SQL Server中,锁机制通过不同类型的锁来实现对数据的不同级别的...

    MS SQLSERVER游标和锁的课件

    **MS SQL SERVER 游标和锁详解** 在MS SQL SERVER中,游标和锁是数据库管理中的重要概念,它们在处理复杂数据操作和确保数据一致性方面发挥着关键作用。 **游标** 游标,顾名思义,就像指针一样在结果集上移动,...

    MS SQL SERVER动态锁分析与应用.pdf

    【MS SQL SERVER动态锁分析与应用】 SQL SERVER是一款广泛应用的关系型数据库管理系统,其动态锁机制是确保多用户环境下数据一致性和安全性的关键技术。动态锁在SQL SERVER中扮演着至关重要的角色,它能够自动选择...

    MS SQL Server查询优化方法

    ### MS SQL Server 查询优化方法详解 #### 一、引言 在数据库管理与维护中,查询性能优化是一项至关重要的工作。对于使用MS SQL Server的企业和个人来说,了解并掌握查询优化技巧能够显著提升系统的响应速度与整体...

    10分钟学会MS SQL (2005)

    在十分钟内掌握MS SQL Server 2005可能听起来有些挑战,但别担心,我们会逐步讲解这个强大的数据库管理系统的关键概念和操作。SQL Server 2005是Microsoft公司推出的一款企业级数据库解决方案,广泛应用于数据存储、...

    MS SQL Server数据库事务锁机制分析

    MS SQL Server 数据库的事务锁机制是确保数据库完整性和一致性的关键组成部分,它涉及到多用户环境下的并发控制和数据安全。锁是一种软件机制,用于防止多个用户在同一时间对同一资源进行冲突操作,确保数据的一致性...

    自动检测并解锁的程序(FOR MS SQL SERVER 7/2000及以后的版本)

    曾有网友在CGI论坛发表过类似的程序,...因为调用的系统存储过程是属于ms sql server的,因此本程序只在ms sql server上测试过( 也许能用在sybase sql server上,熟悉其他数据库系统的人员可以根据此原理自行修改源码)

    MS SQL SERVER 数据库技巧总结

    在IT行业中,MS SQL Server是微软公司开发的关系型数据库管理系统,广泛应用于企业级数据存储、管理和分析。本篇文章将深入探讨一些MS SQL Server的关键数据库技巧,帮助你优化工作流程,提高效率。 一、查询优化 ...

    MS SQL Server语句追踪器

    MS SQL Server语句追踪器是数据库管理员和开发者用于优化数据库性能、排查问题的重要工具。它允许用户实时监控SQL Server数据库的活动,记录并分析执行的SQL语句和存储过程,以便找出性能瓶颈或异常行为。在本文中,...

    基于Power Builder与MS SQL Server集成开发环境的若干问题.pdf

    MS SQL Server中有两种锁机制,即页级锁和表级锁。页级锁包括共享锁、排它锁和修改锁等,表级锁包括意向锁和排它锁等。 避免错误 在并发存取数据时,需要避免以下错误: 1. 当使用Update语句修改某一表时,在事务...

    MS SQL全系列教程

    【MS SQL全系列教程】 本教程全面覆盖了Microsoft SQL Server(简称MS SQL)的各种核心概念和技术,旨在帮助学习者从入门到精通,掌握数据库管理和开发的必备技能。SQL(Structured Query Language)是用于管理和...

    SQL server 自旋锁争用专题

    针对自旋锁争用问题,MS SQL Server团队专门开发了一套方法论,并在2011年通过这篇论文公布。他们针对SQL Server 2008和SQL Server 2008 R2应用程序,在高并发系统上的自旋锁争用问题进行了深入分析。这篇文档为...

    双机热备配置MS SQLSERVER方法

    ### 双机热备配置MS SQLSERVER方法 #### 第一章 安装篇 ##### (一)安装环境要求 在进行双机热备环境下的MS SQLSERVER配置之前,需要满足一定的环境要求,主要包括: 1. **操作系统要求**: - Windows 2000 ...

    MS-SQL Server热点话题30问

    13. SQL Server频繁锁死表:可能由于锁策略设置不当,需要检查并优化锁的粒度和超时设置。 14. SQL Server 2005容灾与高可用方案:可以考虑使用数据库镜像、故障转移群集等技术。 15. 创建DBLink连接SQL Server ...

    MS sql-server培训教程

    MS SQL Server是一款由微软公司开发的关系型数据库管理系统(RDBMS),广泛应用于企业级数据存储、管理和分析。本培训教程将全面深入地介绍SQL Server的关键概念、功能和使用技巧,帮助学习者掌握这一强大工具。 一...

    MS SQL Server7系统表

    MS SQL Server 7是微软公司推出的数据库管理系统,它在数据库管理、数据存储和查询优化等方面提供了强大的功能。系统表是MS SQL Server的核心组成部分,它们存储了关于数据库服务器、数据库、对象以及各种系统信息的...

    [MS SQL Server 2000] 或者 [数据库原理] 考试样卷

    【MS SQL Server 2000】是微软公司推出的一款关系型数据库管理系统,它在20世纪90年代末发布,是SQL Server系列中的一个重要版本。这个系统为开发者提供了强大的数据存储、管理和分析功能,广泛应用于企业级的数据...

Global site tag (gtag.js) - Google Analytics