`
itsoul
  • 浏览: 217795 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

sqlServer锁机制研究

阅读更多
对锁机制的研究要具备两个条件:
1.数据量大
2.多个用户同时并发
如果缺少这两个条件,数据库不容易产生死锁问题。研究起来可能会事倍功半。如果这两个条件都有,但你还是按数据库缺省设置来处理数据,则会带来很多的问题,比如:
1)丢失更新
A,B两个用户读同一数据并进行修改,其中一个用户的修改结果破坏了另一个修改的结果
2)脏读
A用户修改了数据时,B用户也在读该数据,但A用户因为某些原因取消了对数据的修改,数据恢复原值,此时B得到的数据就与数据库内的数据产生了不一致
3)不可重复读
B用户读出该数据并修改,同时,A用户也在读取数据,此时A用户再读取数据时发现前后两次的值不一致
SQL SERVER 作为多用户数据库系统,以事务为单位,使用锁来实现并发控制。SQLSERVER使用“锁”确保事务完整性和数据一致性。

一、锁的概念
锁(LOCKING)是最常用的并发控制机构。是防止其他事务访问指定的资源控制、实现并发控制的一种主要手段。锁是事务对某个数据库中的资源(如表和记录)存取前,先向系统提出请求,封锁该资源,事务获得锁后,即取得对数据的控制权,在事务释放它的锁之前,其他事务不能更新此数据。当事务撤消后,释放被锁定的资源。
当一个用户锁住数据库中的某个对象时,其他用户就不能再访问该对象

二、锁的粒度
SQL Server 2000 具有多粒度锁定,允许一个事务锁定不同类型的的资源。为了使锁定的成本减至最少,SQL Server 自动将资源锁定在适合任务的级别。锁定在较小的粒度(例如行)可以增加并发但需要较大的开销,因为如果锁定了许多行,则需要控制更多的锁。锁定在较大的粒度(例如表)就并发而言是相当昂贵的,因为锁定整个表限制了其它事务对表中任意部分进行访问,但要求的开销较低,因为需要维护的锁较少。SQL Server 可以锁定行、页、扩展盘区、表、库等资源。

资源 级别 描述
RID 行锁 表中的单个行
Key 行级锁 索引中的行
Page 页级锁 一个数据页或者索引页
Extent 页级锁 一组数据页或者索引页
Table 表级锁 整个表
Database 数据库级锁 整个数据库

选择多大的粒度,根据对数据的操作而定。如果是更新表中所有的行,则用表级锁;如果是更新表中的某一行,则用行级锁。
行级锁是一种最优锁,因为行级锁不可能出现数据既被占用又没有使用的浪费现象。但是,如果用户事务中频繁对某个表中的多条记录操作,将导致对该表的许多记录行都加上了行级锁,数据库系统中锁的数目会急剧增加,这样就加重了系统负荷,影响系统性能。因此,在SQL Server中,还支持锁升级(lock escalation)。
所谓锁升级是指调整锁的粒度,将多个低粒度的锁替换成少数的更高粒度的锁,以此来降低系统负荷。在SQL Server中当一个事务中的锁较多,达到锁升级门限时,系统自动将行级锁和页面锁升级为表级锁。
特别值得注意的是,在SQL Server中,锁的升级门限以及锁升级是由系统自动来确定的,不需要用户设置。

三、锁的模式
锁模式以及描述表


锁模式 描述
共享(S) 用于不更改或不更新数据(只读操作),如SELECT语句
更新(U) 用于可更新的资源中。防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁。
排它(X) 用于数据修改操作,例如 INSERT、UPDATE或DELETE。确保不会同时对同一资源进行多重更新
意向 当 Microsoft SQL Server 数据库引擎获取低级别的锁时,它还将在包含更低级别对象的对象上放置意向锁.例如: 当锁定行或索引键范围时,数据库引擎将在包含行或键的页上放置意向锁。当锁定页时,数据库引擎将在包含页的更高级别的对象上放置意向锁。
意向锁的类型为:意向共享(IS)、意向排它(IX)以及意向排它共享(SIX)
架构 在执行依赖于表架构的操作时使用。架构锁的类型为:架构修改(Sch-M)和架构稳定(Sch-S)
大容量更新(BU) 向表中大容量复制数据并指定了TABLOCK提示时使用



四 SQL Server 中锁的设置
1 处理死锁和设置死锁优先级
死锁就是多个用户申请不同封锁,由于申请者均拥有一部分封锁权而又等待其他用户拥有的部分封锁而引起的无休止的等待
可以使用SET DEADLOCK_PRIORITY控制在发生死锁情况时会话的反应方式。
Syntax:
SET DEADLOCK_PRIORITY { LOW | NORMAL}
其中LOW说明该进程会话的优先级较低,在出现死锁时,可以首先中断该进程的事务。
2 处理超时和设置锁超时持续时间。
@@LOCK_TIMEOUT 返回当前会话的当前锁超时设置,单位为毫秒
SET LOCK_TIMEOUT 设置允许应用程序设置语句等待阻塞资源的最长时间。当语句等待的时间大于 LOCK_TIMEOUT 设置时,系统将自动取消阻塞的语句,并给应用程序返回"已超过了锁请求超时时段"的 1222 号错误信息
示例
1)将锁超时期限设置为 1,800 毫秒。
SET LOCK_TIMEOUT 1800
2) 配置索引的锁定粒度
可以使用 sp_indexoption 系统存储过程来设置用于索引的锁定粒度
3)设置事务隔离级别
SET   TRANSACTION   ISOLATION   LEVEL

五 查看锁的信息
1 执行 EXEC SP_LOCK 报告有关锁的信息
2 查询分析器中按Ctrl+2可以看到锁的信息

六、奇怪的sql语句
Java代码
begin tran  
update titles set title_idid=title_id  where 1=2 
if (selectavg(price)fromtitles)>$15 
begin  
update titles set price=price*1.10 
where price<(select avg(price)from titles)  
end  
commit tran 

begin tran
update titles set title_idid=title_id  where 1=2
if (selectavg(price)fromtitles)>$15
begin
update titles set price=price*1.10
where price<(select avg(price)from titles)
end
commit tran

update titles set title_idid=title_id  where 1=2,这个条件是永远也不会成立的,如此写的含义是什么呢?
这里的where子句看起来很奇怪,尽管计算出的结果总是false。当优化器处理此查询时,因为它找不到任何有效的SARG,它的查询规划就会强制使用一个独占锁定来进行表扫描。此事务执行时,where子句立即得到一个false值,于是不会执行实际上的扫描,但此进程仍得到了一个独占的表锁定。
因为此进程现在已有一个独占的表锁,所以可以保证没有其他事务会修改任何数据行,能进行重复读,且避免了由于holdlock所引起的潜在性死锁。
但是,在使用表锁定来尽可能地减少死锁的同时,也增加了对表锁定的争用。因此,在实现这种方法之前,你需要权衡一下:避免死锁是否比允许并发地对表进行访问更重要。
所以,在这个事务中,没有其他进程修改表中任何行的price。

七 如何避免死锁
1 使用事务时,尽量缩短事务的逻辑处理过程,及早提交或回滚事务;
2 设置死锁超时参数为合理范围,如:3分钟-10分种;超过时间,自动放弃本次操作,避免进程悬挂;
3 所有的SP都要有错误处理(通过@error)
4 一般不要修改SQL SERVER事务的默认级别。不推荐强行加锁
5 优化程序,检查并避免死锁现象出现;
1)合理安排表访问顺序
2)在事务中尽量避免用户干预,尽量使一个事务处理的任务少些。
3)采用脏读技术。脏读由于不对被访问的表加锁,而避免了锁冲突。在客户机/服务器应用环境中,有些事务往往不允许读脏数据,但在特定的条件下,我们可以用脏读。
4)数据访问时域离散法。数据访问时域离散法是指在客户机/服务器结构中,采取各种控制手段控制对数据库或数据库中的对象访问时间段。主要通过以下方式实现: 合理安排后台事务的执行时间,采用工作流对后台事务进行统一管理。工作流在管理任务时,一方面限制同一类任务的线程数(往往限制为1个),防止资源过多占用; 另一方面合理安排不同任务执行时序、时间,尽量避免多个后台任务同时执行,另外,避免在前台交易高峰时间运行后台任务
5)数据存储空间离散法。数据存储空间离散法是指采取各种手段,将逻辑上在一个表中的数据分散到若干离散的空间上去,以便改善对表的访问性能。主要通过以下方法实现: 第一,将大表按行或列分解为若干小表; 第二,按不同的用户群分解。
6)使用尽可能低的隔离性级别。隔离性级别是指为保证数据库数据的完整性和一致性而使多用户事务隔离的程度,SQL92定义了4种隔离性级别:未提交读、提交读、可重复读和可串行。如果选择过高的隔离性级别,如可串行,虽然系统可以因实现更好隔离性而更大程度上保证数据的完整性和一致性,但各事务间冲突而死锁的机会大大增加,大大影响了系统性能。
7)使用Bound Connections。Bound connections 允许两个或多个事务连接共享事务和锁,而且任何一个事务连接要申请锁如同另外一个事务要申请锁一样,因此可以允许这些事务共享数据而不会有加锁的冲突。
8)考虑使用乐观锁定或使事务首先获得一个独占锁定。 

八如何对行、 表、数据库加锁
1 如何锁一个表的某一行
Java代码
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED  
SELECT * FROM table1 ROWLOCK WHERE A = 'a1' 

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM table1 ROWLOCK WHERE A = 'a1'
2 锁定数据库的一个表
select col1 from 表 (tablockx) where 1=1 ;
加锁后其它人不可操作,直到加锁用户解锁,用commit或rollback解锁
3.实例
建表
Java代码
create table table1(A varchar(50)  not  null, B varchar(50) ,C varchar(50));  
create table table2(D varchar(50),E varchar(50))  
insert table1 (A,B,C) values(‘a1’,’b1’,’c1’);  
insert table1 (A,B,C) values(‘a2’,’b2’,’c2’);  
insert table1 (A,B,C) values(‘a3’,’b3’,’c3’);  
insert table2 (D,E) values(‘d1’,’e1’);  
insert table2 (D,E) values(‘d2’,’e2’); 

create table table1(A varchar(50)  not  null, B varchar(50) ,C varchar(50));
create table table2(D varchar(50),E varchar(50))
insert table1 (A,B,C) values(‘a1’,’b1’,’c1’);
insert table1 (A,B,C) values(‘a2’,’b2’,’c2’);
insert table1 (A,B,C) values(‘a3’,’b3’,’c3’);
insert table2 (D,E) values(‘d1’,’e1’);
insert table2 (D,E) values(‘d2’,’e2’);
1)排它锁
Java代码
-- A事务先更新table1表,在更新时,对其他事务进行排他  
begin tran  
update table1 set A='aa' where B='b2';  
waitfor delay '00:00:30'; --等待30秒  
commit tran  
-- A事务先更新table2表  
begin tran  
select * from table1 where B='b2';  
commit tran 

-- A事务先更新table1表,在更新时,对其他事务进行排他
begin tran
update table1 set A='aa' where B='b2';
waitfor delay '00:00:30'; --等待30秒
commit tran
-- A事务先更新table2表
begin tran
select * from table1 where B='b2';
commit tran若同时执行上述两个事务,则select查询必须等待update执行完毕才能执行即要等待30秒
2)共享锁
Java代码
-- A事务先查询table1表,在查询时,加共享锁,防止其他事务对该表进行修改操作  
begin tran  
select * from table1 holdlock where B='b2' ;  
-holdlock人为加锁  
waitfor delay '00:00:30';--等待30秒  
commit tran  
-- A事务先查询table1表,后更改table1表  
begin tran  
select A,C from table1 where B='b2';  
update table1 set A='aa' where B='b2';  
commit tran 

-- A事务先查询table1表,在查询时,加共享锁,防止其他事务对该表进行修改操作
begin tran
select * from table1 holdlock where B='b2' ;
-holdlock人为加锁
waitfor delay '00:00:30';--等待30秒
commit tran
-- A事务先查询table1表,后更改table1表
begin tran
select A,C from table1 where B='b2';
update table1 set A='aa' where B='b2';
commit tran若并发执行上述两个事务,则B事务中的select查询可以执行,而update必须等待第一个事务释放共享锁转为排它锁后才能执行即要等待30秒
3)死锁
Java代码
-- A事务先更新table1表,然后延时30秒,再更新table2表;  
begin tran  
update table1 set A='aa' where B='b2';  
--这将在 Table1 中生成排他行锁,直到事务完成后才会释放该锁。  
waitfor delay '00:00:30';  
--进入延时  
update table2 set D='d5' where E='e1' ;  
commit tran  
-- B事务先更新table2表,然后延时10秒,再更新table1表;  
begin tran  
update table2 set D='d5' where E='e1';  
--这将在 Table2 中生成排他行锁,直到事务完成后才会释放该锁  
waitfor delay '00:00:10' 
--进入延时  
update table1 set A='aa' where B='b2' ;  
commit tran 

-- A事务先更新table1表,然后延时30秒,再更新table2表;
begin tran
update table1 set A='aa' where B='b2';
--这将在 Table1 中生成排他行锁,直到事务完成后才会释放该锁。
waitfor delay '00:00:30';
--进入延时
update table2 set D='d5' where E='e1' ;
commit tran
-- B事务先更新table2表,然后延时10秒,再更新table1表;
begin tran
update table2 set D='d5' where E='e1';
--这将在 Table2 中生成排他行锁,直到事务完成后才会释放该锁
waitfor delay '00:00:10'
--进入延时
update table1 set A='aa' where B='b2' ;
commit tran若并发执行上述两个事务,A,B两事务都要等待对方释放排他锁,这样便形成了死锁。

九、sqlserver提供的表级锁
sqlserver所指定的表级锁定提示有如下几种
1. HOLDLOCK: 在该表上保持共享锁,直到整个事务结束,而不是在语句执行完立即释放所添加的锁。 
2. NOLOCK:不添加共享锁和排它锁,当这个选项生效后,可能读到未提交读的数据或“脏数据”,这个选项仅仅应用于SELECT语句。  
3. PAGLOCK:指定添加页锁(否则通常可能添加表锁)
4. READCOMMITTED用与运行在提交读隔离级别的事务相同的锁语义执行扫描。默认情况下,SQL Server 2000 在此隔离级别上操作。
5. READPAST: 跳过已经加锁的数据行,这个选项将使事务读取数据时跳过那些已经被其他事务锁定的数据行,而不是阻塞直到其他事务释放锁,READPAST仅仅应用于READ COMMITTED隔离性级别下事务操作中的SELECT语句操作
6. READUNCOMMITTED:等同于NOLOCK。   
7. REPEATABLEREAD:设置事务为可重复读隔离性级别。 
8. ROWLOCK:使用行级锁,而不使用粒度更粗的页级锁和表级锁。
9. SERIALIZABLE:用与运行在可串行读隔离级别的事务相同的锁语义执行扫描。等同于 HOLDLOCK。
  10. TABLOCK:指定使用表级锁,而不是使用行级或页面级的锁,SQL Server在该语句执行完后释放这个锁,而如果同时指定了HOLDLOCK,该锁一直保持到这个事务结束。
11. TABLOCKX:指定在表上使用排它锁,这个锁可以阻止其他事务读或更新这个表的数据,直到这个语句或整个事务结束。
12. UPDLOCK :指定在读表中数据时设置更新锁(update lock)而不是设置共享锁,该锁一直保持到这个语句或整个事务结束,使用UPDLOCK的作用是允许用户先读取数据(而且不阻塞其他用户读数据),并且保证在后来再更新数据时,这一段时间内这些数据没有被其他用户修改
SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除
SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除

十、应用程序锁

应用程序锁就是客户端代码生成的锁,而不是sql server本身生成的锁处理应用程序锁的两个系统存储过程
sp_getapplock: 锁定应用程序资源
sp_releaseapplock: 为应用程序资源解锁
分享到:
评论

相关推荐

    sqlserver锁机制研究

    SQL Server的锁机制是数据库管理系统中用于控制并发访问和维护数据一致性的关键机制。通过深入理解锁的概念和工作原理,数据库管理员和开发人员能够更好地优化应用程序的性能,并避免潜在的并发问题,如丢失更新、脏...

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

    MS SQL Server 提供了多种锁机制,包括行锁、页锁、表锁等,每种锁机制都有其特点和应用场景。 在 MS SQL Server 中,锁机制可以分为两种:自动锁和手动锁。自动锁是由系统自动分配的锁,用于确保数据库的安全和...

    Microsoft SQL Server 2008 Internals (PDF 高清版)

    2. **锁和并发控制**:深入分析SQL Server的锁定机制,包括不同的锁定类型、死锁处理、事务隔离级别等内容。 3. **存储引擎**:解析SQL Server如何存储数据,涉及页结构、索引类型及其维护机制。 4. **查询优化器**...

    SqlServer存储过程及调试指南

    SqlServer存储过程及调试指南的知识点如下: 1. 存储过程概念:存储过程是一...通过掌握这些知识点,初学者以及希望深入研究的开发人员将能够更有效地编写和调试SqlServer存储过程,提升数据库应用程序的质量和性能。

    基于SYBASE SQL Server的页锁表锁及死锁研究.pdf

    在SYBASE SQL Server中,锁机制是数据库管理系统中非常重要的一部分。锁机制的主要作用是解决多用户同时访问同一个数据的冲突问题。SYBASE SQL Server提供了多种锁机制,包括共享锁、更新锁和排它锁等。 共享锁...

    MSSQLServer数据库事务锁机制分析.docx

    ### MSSQLServer数据库事务锁机制分析 #### 一、引言 锁机制是数据库系统中一个...通过这些资料的学习,开发者们可以更全面地掌握SQL Server锁机制的细节,并将其应用于实际项目中,以提高数据库应用的性能和可靠性。

    ORACLE,sql server笔试题目,答案

    8. **并发控制**:事务处理、锁机制以及乐观锁和悲观锁的概念。 9. **分区与分片**:如何利用Oracle和SQL Server的分区功能提高查询性能? 10. **故障诊断与解决**:如何识别和解决常见的数据库问题,如死锁、性能...

    SQL Server示例数据库

    8. **事务和并发控制**:学习事务的ACID属性(原子性、一致性、隔离性和持久性),并了解SQL Server中的锁机制和死锁问题。 9. **安全性**:设置用户权限,理解角色和登录的概念,以及如何实现对数据库对象的访问...

    SQL Server 2008 Transact SQL Receipe

    - **锁和并发控制**: 探讨 SQL Server 如何处理多个用户同时访问同一资源的情况,以避免数据冲突。 - **性能优化**: 提供一系列提高查询效率的方法,包括索引的创建与使用、查询优化技巧等。 - **安全性**: 介绍 SQL...

    《SQL Server数据库原理及应用》

    SQL Server数据库原理部分主要讲解了关系型数据库的基础知识,包括数据库模型(如实体-关系模型),数据存储结构(如页、槽、记录),事务处理和并发控制(如锁、多版本并发控制MVCC),以及数据库的备份与恢复策略...

    SQL Server数据库封锁及死锁研究.pdf

    SQL Server提供了多种锁模式,如共享锁(只读操作)、排他锁(数据修改)、更新锁(修改前的临时状态)、意向锁(表示低层次锁定意向)、模式锁(数据定义语言操作和查询编译)以及批量更新锁(批量复制数据时使用)...

    SQLServer精华技巧集(chm)

    - 学习锁机制和死锁避免,以优化多用户环境下的并发性能。 5. **性能优化** - 使用SQL Server的内置工具(如动态管理视图和性能计数器)进行性能监控。 - 学习查询优化器的工作原理,理解执行计划,以及如何通过...

    SQL Server 2005高级教程(PDF).rar

    6. **事务与锁机制**:理解事务的概念和ACID属性,掌握不同级别的锁定机制,以及死锁的预防和解决方法,确保数据的一致性。 7. **存储过程与触发器**:深入研究存储过程的编写和调用,利用触发器实现自动化的业务...

    Professional SQL Server 2008 Programming

    通过以上章节的详细讲解,《专业SQL Server 2008编程》不仅为读者提供了全面而深入的SQL Server 2008编程知识,还涵盖了大量实用的案例研究和最佳实践,是SQL Server开发和管理领域的一本权威指南。

    SQL SERVER中的事务处理教学研究.pdf

    掌握事务的ACID原则和锁机制对于任何使用SQL SERVER的开发人员和数据库管理员来说都是必不可少的。在实际开发过程中,合理运用事务可以极大提高数据处理的效率和安全性。在教学中,事务处理也是数据库理论教学中不可...

    SQLSERVER事务隔离级别的实验研究.pdf

    本研究为中国工程物理研究院工学院的课题研究提供了参考和指导,通过对SQL Server事务隔离级别的实验研究,有助于理解和掌握多用户并发数据库系统中的事务隔离机制,为数据库设计和应用开发提供了科学依据。...

    SQL Server 2008编程入门经典(第3版)

    - **数据库引擎**:深入解析SQL Server的架构,包括缓存机制、锁机制和并发控制。 - **业务智能**:介绍SQL Server集成服务(SSIS)、SQL Server报告服务(SSRS)和SQL Server分析服务(SSAS)等BI组件。 - **性能...

Global site tag (gtag.js) - Google Analytics