擦亮自己的眼睛去看SQL Server之谈谈锁机制

在谈谈SQL Server的锁机制之前,来思考以下这个场景:当你在酷暑的时候骑着自己的小车往目的地行走时,路上连续遇到几个时间很长的红灯,是不是很郁闷?有时候 你可能实在受不了闯了个红灯,其实在大部分情况下问题不大,如果通行的汽车很多那就不好说了。因为不遵守规则的人太多,都为了达到目的去走捷径,不愿意等 待。这样才有了交警。交警的作用就是维护这些红绿灯的规则。这些红绿灯就像锁一样,锁住或延长你去目的地的时间。但是如果没有交警大家又不自由遵守红绿灯 规则会导致什么呢?大家想想都知道。

这个系列的一篇文章中提供的事务管理器中有个锁管理器就是这里的交警。它维护着SQLServer中的锁。前段提到的大部分情况指的就是在系统事务 量不大的时候,这时候的锁永远不会是什么大问题。除非你知道你的系统永远就给几个人用,否则考虑到避免系统以后的并发量上升引起数据安全与效率问题,那你 得深入了解锁机制。在研究锁之前,假定你已经了解事务的ACID概念,它是整个SQL Server的精髓所在。如果没有事务那就不用谈锁了,除了事务需要锁以外其他任何东西都需要这个让SQL不自由的机制。说到底锁是一个平衡并发与数据安 全的机制,如果没有锁,任何SQL都能覆盖其他SQL执行的数据,那么数据会出现不一致的情况。如果锁得太狠,那将影响数据库系统的并发性以及效率(包括 锁本身带来的额外开销)。这时候就需要去权衡,SQLServer锁管理器就充当权衡这两者关系的角色,如下图所示:

SQL Server中锁的知识点实在太多,比如锁从模式上分为:共享锁(S)、更新锁(U)、排他锁(X)、架构锁(Sch-S、Sch-M)、意向锁(IS、 IU、IX)、转换锁(SIX、SIU、UIX)、大容量更新锁(BU);锁从粒度上分为:数据库锁、文件锁、表锁、堆锁、索引锁、页锁、键锁、区锁、行 锁、应用程序锁、元数据锁;锁之间存在兼容性问题;锁会根据情况进行升级;锁控制不好会出现死锁;悲观锁的隔离性:未提交读、已提交读、可重复读、可序列 化;乐观锁的隔离性:读提交快照隔离、快照隔离;闩(shuan)锁。。。随便列下就一大堆问题要说清楚需要花很大篇幅。还是抱着与前几篇文章的风格,仔 细分析一个具体的问题——锁升级。

1、准备

有一个动态管理视图可以查看所有锁:sys.dm_tran_locks,还有一个动态管理视图可以查看哪些请求正在阻塞其他的请求:sys.dm_os_waiting_tasks

2、什么是锁升级

锁升级是指锁的粒度由细向粗转换。如:由行锁转成表锁。

3、需要锁升级吗?

一般来说,锁的粒度越小,并发性越好但是如果去锁定的东西多就需要的锁越多,这样会消耗SQLServer的cpu与内存。一个锁占用内存约为96 字节,你算算如果用行锁去锁定百万千万的表需要多少内存。而且管理锁(创建锁、维护锁、销毁锁等)也是有代价的,会消耗cpu。 如果用一个大点的锁就将这些百万千万的锁合并成一个锁了,管理起来也方便消耗资源也小。

4、什么时候出现锁升级

SQLServer意识到锁定的页面或行数过大的时候发生。怎么意识到过大呢?由两种方法识别:请求用于的锁的数目超过锁数目临界值;锁管理器为单 独一个查询消耗过多的内存超过内存临界值。有其他一个超过临界值,SQLServer就会试图升级。注意这里说的锁数据以及内存是值由同一个查询发生的, 而不是总共的。这里说的临界值并不是固定的,SQLServer采用启发式算法去动态调整。

5、控制锁升级

SQLServer提供一些可以让我们控制锁升级的入口。在SQLServer2008中可以通过:

alter table test

set (lock_escalation = auto|table|disable)

我们还可以通过在代码中显示指定pagelock、tablock提示,会强制SQLServer使用更粗的锁。不过这个设置不合理的话会导致并发降低。建议一般情况下不用,除非你很清楚这样带来的影响。

6、举例说明

6.1建库建表:

create database Test

create table test

ID identity(1,1) primary key,

[Name] varchar(50) not null default ‘’,

CreatedTime datetime not null default getdate();

查看当前锁情况:

默认某个连接对整个数据库有个共享锁。

6.2循环插入几十万条记录:

while 1 = 1

insert into test(Name) values (‘kk’)

插入时的锁快照 :

从上图中看出这个快照中有:三个数据库共享锁、一个页级意向排他锁、一个表级意向排他锁、两个行级排他锁。

三个数据库共享锁:前面已经提过,默认某个连接对整个数据库有个共享锁;

一个页级意向排他锁、一个表级意向排他锁:在页以及表级表示资源的一部分实际已经有锁进行保护,这样的好处允许其他请求锁在表页级别上进行检查,减 少不必要的更细的锁请求,提高性能。比如在这种情况下,如果允许alter操作那么这个操作就会等待因为这里有表级排他锁,它提示alter操作该表有活 动。

6.3 跟踪Lock:Escalation事件

在profiler中设置只跟踪Lock:Escalation事件,锁升级事件。

6.4更新表中记录:

update test set name = ‘name’ where name = ‘kk’

在profiler中看到了Lock:Escalation事件被触发:

更新时的快照为(按顺序):

如上图:此时update操作以排他锁定它更新的行。

如上图:此时update操作以排他锁锁定了整个表,以架构稳定锁(Sch-S)锁定它相关的元数据表。

如上图:此时释放了对元数据表的架构稳定锁(Sch-S)锁,剩下对整个表的排他锁。

从上面的分析中,发现SQLServer锁机制是有点复杂的,不过也是很有意思的。研究后,你会发现它真的很智能。今天分析就到此结束,文中如有描述不当的地方,欢迎指出。共同进步才是硬道理。(来源:博客园)

时间: 2024-10-18 15:11:26

擦亮自己的眼睛去看SQL Server之谈谈锁机制的相关文章

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

server|数据|数据库 锁是网络数据库中的一个非常重要的概念,它主要用于多用户环境下保证数据库完整性和一致性.各种大型数据库所采用的锁的基本理论是一致的,但在具体实现上各有差别.目前,大多数数据库管理系统都或多或少具有自我调节.自我管理的功能,因此很多用户实际上不清楚锁的理论和所用数据库中锁的具体实现. Microsoft SQL Server(以下简称SQL Server)作为一种中小型数据库管理系统,已经得到了广泛的应用,该系统更强调由系统来管理锁.在用户有SQL请求时,系统分析请求,自

无法使用SQL login去登陆SQL Server - 'Password did not match'

原文:无法使用SQL login去登陆SQL Server - 'Password did not match' 出自:http://blogs.msdn.com/b/apgcdsd/archive/2011/02/01/sql-login-sql-server-password-did-not-match.aspx 问题描述: 在某一台机器上的management studio,始终无法使用SQL login去登陆SQL Server.但是如果在其他的机器上,使用同样的SQL login是可以

MSSQL - 架构分析 - 从SQL Server 2017发布看SQL Server架构的演变

title: MSSQL - 架构分析 - 从SQL Server 2017发布看SQL Server架构的演变 author: 风移 摘要 美国时间2017年10月2日,微软正式发布了最新一代可以运行在Linux平台的数据库SQL Server 2017.SQL Server 2017给用户带来了一系列的新功能特性的同时,也体现了微软关于自家关系型数据库平台建设方面的最新设计与思考.这篇文章旨在介绍SQL Server 2017新特性,以及微软是如何从架构层面的演进来快速实现Linux平台的S

SQL Server中的锁的简单学习

原文:SQL Server中的锁的简单学习 简介     在SQL Server中,每一个查询都会找到最短路径实现自己的目标.如果数据库只接受一个连接一次只执行一个查询.那么查询当然是要多快好省的完成工作.但对于大多数数据库来说是需要同时处理多个查询的.这些查询并不会像绅士那样排队等待执行,而是会找最短的路径执行.因此,就像十字路口需要一个红绿灯那样,SQL Server也需要一个红绿灯来告诉查询:什么时候走,什么时候不可以走.这个红绿灯就是锁.     图1.查询可不会像绅士们那样按照次序进行

为什么我们需要在SQL Server里更新锁_MsSql

每次讲解SQL Server里的锁和阻塞(Locking & Blocking)都会碰到的问题:在SQL Server里,为什么我们需要更新锁?在我们讲解具体需要的原因前,首先我想给你介绍下当更新锁(Update(U)Lock)获得时,根据它的兼容性锁本身是如何应对的. 一般来说,当执行UPDATE语句时,SQL Server会用到更新锁(Update Lock).如果你查看对应的执行计划,你会看到它包含3个部分: 读取数据 计算新值 写入数据 在查询计划的第1部分,SQL Server初始读取

为什么我们需要在SQL Server里更新锁

每次讲解SQL Server里的锁和阻塞(Locking & Blocking)都会碰到的问题:在SQL Server里,为什么我们需要更新锁?在我们讲解具体需要的原因前,首先我想给你介绍下当更新锁(Update(U)Lock)获得时,根据它的兼容性锁本身是如何应对的. 一般来说,当执行UPDATE语句时,SQL Server会用到更新锁(Update Lock).如果你查看对应的执行计划,你会看到它包含3个部分: 读取数据 计算新值 写入数据 在查询计划的第1部分,SQL Server初始读取

MSSQL · 架构分析 · 从SQL Server 2017发布看SQL Server架构的演变

摘要 美国时间2017年10月2日,微软正式发布了最新一代可以运行在Linux平台的数据库SQL Server 2017.SQL Server 2017给用户带来了一系列的新功能特性的同时,也体现了微软关于自家关系型数据库平台建设方面的最新设计与思考.这篇文章旨在介绍SQL Server 2017新特性,以及微软是如何从架构层面的演进来快速实现Linux平台的SQL Server 2017产品. SQL Server 2017发布 早在2016年,当微软宣布SQL Server将很快在Linux

SQL Server 事务和锁详解

最近在项目中进行压力测试遇到了数据库的死锁问题,简言之,如下的代码在 SERIALIZABLE 隔离级别造成了死锁:  代码如下 复制代码 SELECT @findCount=COUNT(id) FROM MyTable WHERE [fk_related_id]=@Argument IF (@findCount > 0) BEGIN ROLLBACK TRANSACTION RETURN ERROR_CODE END INSERT INTO MyTable ([fk_related_id],-

基于SQL Server OS的任务调度机制详解_MsSql

简介      SQL Server OS是在Windows之上,用于服务SQL Server的一个用户级别的操作系统层次.它将操作系统部分的功能从整个SQL Server引擎中抽象出来,单独形成一层,以便为存储引擎提供服务.SQL Server OS主要提供了任务调度.内存分配.死锁检测.资源检测.锁管理.Buffer Pool管理等多种功能.本篇文章主要是谈一谈SQL OS中所提供的任务调度机制. 抢占式(Preemptive)调度与非抢占式(non-Preemptive)调度     数据