阻塞与死锁(一)——基础知识

原文:阻塞与死锁(一)——基础知识

阻塞与死锁是除内存、CPU、IO外另一个影响性能的因素。对OLTP系统尤为严重

一般以下问题是死锁的征兆:

1、  并发用户少的时候,一切正常,但是随着用户数量增多,性能越来越慢。

2、  客户端经常收到以下错误:

Error 1222:Lock request time out period exceeded.(已超过锁请求超时时段)

Error 1205:Your transaction(process ID #XX) was deadlocked on{lock|communication buffer|thread} resources with another process and has beenchosen as the deadlock victim.Rerun your transaction.(事务(进程ID XX)与另一个进程被死锁在XX资源上,并且已被选作死锁牺牲品。请重新运行该事务。)

超时错误:Timeout expired.The timeout period elapsed prior to completion ofthe operation or the server is not responding.

3、  应用程序运行很慢,但是SQL Server 硬盘、CPU利用率很低。运行sp_who命令很快返回。

4、  有些查询能经行,但是有些特定查询或者修改总是不能返回。

5、  重启SQLServer就能解决。但是有可能跑一段时间以后又出现问题。

堵塞和死锁是性能问题,更是设计问题。而不是数据库服务器自身的问题。从根本上解决死锁问题必须从设计本身着手。

在了解死锁和堵塞原因之前,先要了解关系数据库中的一个概念:事务

堵塞和死锁的3大因素:连续持有锁时间过长,数目过多,粒度过大产生的原因

锁产生的背景:

1、  事务是单个逻辑工作单元执行的一系列操作。必须具有:原子性、一致性、隔离性和持久性(ACID):

l  一致性:事务完成时,数据必须保持一致状态。事务结束时,所有内部数据结构必须都是正确的。

l  隔离性:与其他并发事务所做的修改必须隔离。虽然用户在并发操作,但是事务是串行执行的。

l  持久性:事务完成后,影响是永久的。

l  原子性:事务要么做、要么不做。

2、  从业务逻辑上实现ACID,有两方面:

2.1、程序员要负责启动和结束事务,确定一个事务的范围。并要控制好合适的结束时间。

2.2、SQL Server数据库引擎强制该事务的物理完整性:

2.2.1、锁定资源,使事务保持隔离。

2.2.2、先写入日志方式,保证事务的持久性。

2.2.3、事务管理特性,强制保证事务的原子性和一致性。如果事务完成不了,数据库引擎会撤销所做的操作。

所以,锁是SQLServer实现事务隔离的一部分,阻塞也是事务隔离的体现。是用户使用事务所要付出的代价。开发者和DBA的工作不是去消除阻塞,而是把阻塞时间和范围控制在合理的范围内。完全消除阻塞是不可能的。

为了减少大范围阻塞,建议做到以下几点:

1、  申请资源的互斥度:如果不同的连接申请的锁都是互相兼容的,那么不会产生阻塞。

2、  锁的范围和数目多少:良好的设计可以使申请的锁的粒度和数目控制在最小范围内。

3、  事务持有锁资源的时间长短:对共同所需的锁,持有时间越短越好。

锁资源模式和兼容性:

数据库引擎可以锁定的资源:


资       源


说        明


RID


用于锁定堆(Heap)中的某一行,没有聚集索引的表为“堆”。


Key


用于锁定索引上的某一行,或者某个索引键。


Page


锁定数据库的一个8K页,例如数据页或者索引页。


Extent


一组连续的8页


HoBT


锁定整个堆或者B树的锁。


Table


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


File


数据库文件。


Application


应用程序专用的资源。


MetaData


元数据锁。


Application_Unit


分配单元。


Database


整个数据库。

数据库引擎使用的资源锁模式:


锁模式


说        明


共享(S)


用于不更改或者不更新数据的读取操作,如SELECT 语句


更新(U)


用于可更新的资源中,防止多会话读取、锁定及随后可能更新的资源更新时发生常见形式的死锁。


排他(X)


用于数据修改,确保不会同时对同一资源进行多重更新。


意向


用于建立锁的层次结构,包含:意向共享(IS),意向排他(IX),意向排他共享(SIX)


架构


执行依赖于表架构的操作时使用。架构修改(Sch-M)和架构稳定性(Sch-S)


大容量更新(BU)


在向表进行大容量数据复制且指定了TABLOCK提示时使用。


键范围


当使用可序列化事务隔离级别时保护查询读取的行的范围。确保再次运行查询时其他事务无法插入符合可序列化事务的查询的行。

下面是对表格的说明:

共享锁(S锁):

允许并发事务在封闭式并发控制下读取资源。此时其他事务不能修改数据。

更新锁(U锁):

可重复读可序列化事务中(避免幻读),一个修改操作需要先【读取数据即添加共享锁】,然后【修改数据即从共享锁转换成排他锁(X锁)】。如果此时有另外一个事务做同样的操作,就有可能形成死锁。为避免这个情况,SQL Server使用了更新锁(U锁)。一次只有一个事务可以获得更新锁。当事务真正需要修改数据时,就会把U锁转成X锁。

排它锁(X锁):

防止并发事务对资源进行访问。此时无法读写资源,除非使用NOLOCK提示或者未提交读隔离级别时才可以进行读操作。修改语句(insert/update/delete)合并了读、改操作。因为首先要读出来才能改。所以通常修改数据需要申请共享锁和排它锁。

意向锁:

数据库引擎使用意向锁来保护锁层次结构的底层资源。添加了意向锁后,可以防止其他排它锁对该资源的控制。意向锁可以提高性能,因为数据库引擎仅在表级检查意向锁。而不需要检查表中的每行每页

架构锁:

在表的DDL操作是会使用架构修改锁(Sch-M),防止其他用户对这个表的访问。在编译和执行查询时会使用架构稳定性锁(Sch-S),此锁不会阻止其他事务访问数据,但是会阻止DDL和DML操作。

大容量更新锁(BU):

对大容量复制数据时使用大容量更新锁(BU),并指定TABLOCK提示或使用sp_tableoption设置table lock on bulk load表选项。允许多线程将数据并发地加载到同一个表。防止其他不惊醒大容量加载数据的进程访问该表。

键范围锁:

在使用可序列化(serializable)事务隔离级别时,对T-SQL读取的记录集,键范围锁可以隐式保护该记录集中包含的行范围。可以防止幻读。

如果请求锁的模式和现有模式不兼容,则请求新锁就会被迫进入等待状态。阻塞也就随之而来。

常见锁模式兼容性:不能修改


现有授予模式


请求模式


IS


S


U


IX


SIX


X


意向共享(IS)


Y


Y


Y


Y


Y


N


共享(S)


Y


Y


Y


N


N


N


更新(U)


Y


Y


N


N


N


N


意向排他(IX)


Y


N


N


Y


N


N


意向排他共享(SIX)


Y


N


N


N


N


N


排他(X)


N


N


N


N


N


N

申请锁的粒度越小,产生阻塞的几率就越小。

锁的释放速度越快,产生阻塞的几率越低。

影响锁的粒度:

1、  一个事务内部要访问或修改的数据量越大,索要申请的锁的数目就会越多,粒度也就可能越大。

2、  一个事务做的事情越复杂,它要申请的锁的范围就会越大。

3、  一个事务延续时间越长,它持有的锁的时间也会越长。

总结:事务的隔离级别影响锁的申请及释放的时间;而语句的执行计划,也会影响到锁的粒度和申请数量。

事务隔离级别与锁的申请和释放:

没有并发控制会出现以下情况:

l  丢失更新

l  未提交的依赖关系(脏读)

l  不一致的分析(不可重复读)

l  幻读

SQL Server数据库引擎支持的隔离级别:

l  未提交读(隔离事务的最低级别,只能保证不读物理上损坏的数据)

l  已提交读(默认级别,可防止脏读)

l  可重复读。

l  可序列化(最高级别,可防止幻影,事务之间完全隔离)

不同隔离级别允许的并发副作用:


隔离级别


脏读


不可重复读


幻读


未提交读





已提交读





可重复读





可序列化




未提交读(read uncommitted):

可以读取由其他事务修改但未提交的数据,允许脏读。不会被其他锁阻塞。该选项和使用nolock设置相同。是隔离级别中限制最少的级别。

已提交读(read committed):

指定语句不能读取由其他事务修改但未提交的数据。避免脏读。但会产生不可重复读和幻象数据。是默认设置。此时会使用共享锁防止其他事务修改数据。语句运行完就会释放共享锁,而不是等到事务提交才释放。

可重复读(repeatable read):

指定语句不能读取由其他事务修改但未提交的数据,并且其他事务不能在当前事务完成之前修改由该事务读取的数据。此级别对事务中每个语句所涉及的所有数据设置了共享锁,并且一直持续到事务完毕。可以防止其他事务修改当前事务读取的任何行。

其他事务可以插入与当前事务语句中匹配的新行,如果当前事务重新执行该语句,会检索到新行,从而产生幻读。

由于并发性比默认设置低,所以只有在必要的时候才使用。

可序列化(serializable):

要求:

1、  语句不能读取已由其他事务修改但未提交的数据。

2、  任何其他事务都不能在当前事务完成前修改当前事务读取的数据。

3、  在当前事务完成前,其他事务不能使用当前事务中任何语句读取的键值插入新行。

通过加范围锁的方式来实现可序列化。范围锁会锁住当前事务的语句中搜索条件相匹配的键值范围,使得其他事务不可更新或插入任何行。直到事务结束。并发性最低。只有必要时才使用。该选项与select语句中的HOLDLOCK提示相同。


隔离级别


是否申请共享锁


何时释放


有无范围锁


未提交读





已提交读



当前语句完成时



可重复读



事务提交时



可序列化



事务提交时


隔离的级别越高,共享锁持有时间越长,粒度越大。

如果阻塞发生在【共享锁】上,可以通过降低事务隔离级别得到缓解。

对于排它锁,所以隔离级别都是一样,要等到【事务结束】后才释放。此时不能通过降低事务隔离级别来实现。

时间: 2024-07-30 00:25:38

阻塞与死锁(一)——基础知识的相关文章

java基础知识回顾之java Thread类学习(七)--java多线程安全问题(死锁)

死锁:是两个或者两个以上的线程被无限的阻塞,线程之间互相等待所需资源. 线程死锁产生的条件: 当两个线程相互调用Join()方法. 当两个线程使用嵌套的同步代码块的时候,一个线程占用了另一个线程的锁,互相等待阻塞,就有可能产生死锁. 下面看代码: 代码1:死锁的案例 package com.lp.ecjtu.Thread; /* 死锁:常见情景之一:同步的嵌套. */ class Ticket implements Runnable { private int num = 100; Object

Java多线程完整版基础知识

Java多线程完整版基础知识 (翟开顺由厚到薄系列) 1.前言 线程是现代操作系统中一个很重要的概念,多线程功能很强大,java语言对线程提供了很好的支持,我们可以使用java提供的thread类很容易的创建多个线程.线程很不难,我对之前学习过的基础,在这做了一个整理,本文主要参考的是Java研究组织出版的j2se进阶和张孝祥-java就业培训教材这两本书 2.概述 2.1线程是什么 主要是线程与进程的区别,这里不再阐述,自行网上搜索 为什么使用线程:操作系统切换多个线程要比调度进程在速度上快很

Java语言的基础知识9

第十一章(线程) 1.通过String name=Thread.currentThread().getName();来获取当前线程的名称. 2.多次启动一个线程或者启动一个已经运行的线程是非法的,会抛出IllegalThreadStateException异常对象. Thread.sleep((int)Math.random()*10000); 3.java提供了Runnable接口使继承了其他类之后同样可以实现该接口达到创建线程的目的Runabble接口同样定义了Run方法. 实现Runnab

java基础知识小小结

java基础知识小总结 在一个独立的原始程序里,只能有一个 public 类,却可以有许多 non-public 类.此外,若是在一个 Java 程序中没有一个类是 public,那么该 Java 程序的文件名就可以随意命名了. 文档注释,是以单斜线加两个星形标记( /**)开头,并以一个星形标记加单斜线( */)结束.用这种方法注释的内容会被解释成程序的正式文档,并能包含进如 javadoc之类的工具生成的文档里,用以说明该程序的层次结构及其方法. Java 把整数常量的数据类型均视为 int

JavaSe基础知识总结

Java基础知识总结 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java语言代码把思路体现出来. 学习新技术的四点: 1,该技术是什么? 2,该技术有什么特点(使用注意): 3,该技术怎么使用.demo 4,该技术什么时候用?test. -------------------------------------------------------------------------

【RAC】RAC相关基础知识

[RAC]RAC相关基础知识 1.CRS简介    从Oracle 10G开始,oracle引进一套完整的集群管理解决方案—-Cluster-Ready Services,它包括集群连通性.消息和锁.负载管理等框架.从而使得RAC可以脱离第三方集群件,当然,CRS与第三方集群件可以共同使用. (1).CRS进程 CRS主要由三部分组成,三部分都作为守护进程出现 <1>CRSD:资源可用性维护的主要引擎.它用来执行高可用性恢复及管理操作,诸如维护OCR及管理应用资源,它保存着集群的信息状态和OC

C#复习笔记(5)--C#5:简化的异步编程(异步编程的基础知识)

异步编程的基础知识 C#5推出的async和await关键字使异步编程从表面上来说变得简单了许多,我们只需要了解不多的知识就可以编写出有效的异步代码. 在介绍async和await之前,先介绍一些基础的概念: 并发:同时做很多事情. 这个解释直接表明了并发的作用.终端用户程序利用并发功能,在输入数据库的同时响应用户输入.服务器应用利用并发,在处理第一个请求的同时响应第二个请求.只要你希望程序同时做多件事情,你就需要并发.几乎每个软件程序 都会受益于并发. 多线程:并发的一种形式,它采用多个线程来

毕向东—Java基础知识总结(超级经典)

Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java语言代码把思路体现出来. 学习新技术的四点: 1,该技术是什么? 2,该技术有什么特点(使用注意): 3,该技术怎么使用.demo 4,该技术什么时候用?test. ------------------------------------------------------ 一:java概述: 19

Java基础知识总结(超级经典)

Java基础知识总结(超级经典) 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部分用到哪些语句,方法,和对象. 4,代码实现.用具体的java语言代码把思路体现出来. 学习新技术的四点: 1,该技术是什么? 2,该技术有什么特点(使用注意): 3,该技术怎么使用.demo 4,该技术什么时候用?test. —————————————————————————————————————————————————————— 一:java概述: 19