[转帖]【SQL SERVER】锁机制
https://www.cnblogs.com/WilsonPan/p/12618849.html
锁定是 SQL Server 数据库引擎用来同步多个用户同时对同一个数据块的访问的一种机制。
基本概念
数据库引擎隔离级别
| 隔离级别 | 定义 |
|---|---|
| 未提交的读取 | 隔离事务的最低级别,只能保证不读取物理上损坏的数据。 在此级别上,允许脏读,因此一个事务可能看见其他事务所做的尚未提交的更改 |
| 已提交的读取 | 允许事务读取另一个事务以前读取(未修改)的数据,而不必等待第一个事务完成。 SQL Server 数据库引擎保留写锁(在所选数据上获取)直到事务结束,但是一执行 SELECT 操作就释放读锁。 这是SQL Server 数据库引擎默认级别 |
| 可重复的读取 | SQL Server 数据库引擎保留在所选数据上获取的读锁和写锁,直到事务结束。 但是,因为不管理范围锁,可能发生虚拟读取 |
| 可序列化 | 隔离事务的最高级别,事务之间完全隔离。 SQL Server 数据库引擎保留在所选数据上获取的读锁和写锁,在事务结束时释放它们。 SELECT 操作使用分范围的 WHERE 子句时获取范围锁,主要为了避免虚拟读取 |
锁粒度
| 资源 | 说明 |
|---|---|
| RID | 用于锁定堆中的单个行的行标识符,也就是常说的行锁 |
| KEY | 索引中用于保护可序列化事务中的键范围的行锁 |
| PAGE | 数据库中的 8 KB 页,例如数据页或索引页,也就常说的业级锁 |
| EXTENT | 一组连续的八页,例如数据页或索引页 |
| HoBT | 堆或 B 树。 用于保护没有聚集索引的表中的 B 树(索引)或堆数据页的锁 |
| TABLE | 包括所有数据和索引的整个表 |
| FILE | 数据库文件 |
| APPLICATION | 应用程序专用的资源 |
| METADATA | 元数据锁 |
| ALLOCATION_UNIT | 分配单元 |
| DATABASE | 整个数据库 |
锁类型
| 锁 | 说明 |
|---|---|
| 共享 (S) | 用于不更改或不更新数据的读取操作,如 SELECT 语句 |
| 更新 (U) | 用于可更新的资源中。 防止当多个会话在读取、锁定以及随后可能进行的资源更新时发生常见形式的死锁 |
| 排他 (X) | 用于数据修改操作,例如 INSERT、UPDATE 或 DELETE。 确保不会同时对同一资源进行多重更新 |
| 意向 (I) | 用于建立锁的层次结构。 意向锁包含三种类型:意向共享 (IS)、意向排他 (IX) 和意向排他共享 (SIX) |
| 架构 (Sch-) | 在执行依赖于表架构的操作时使用。 架构锁包含两种类型:架构修改 (Sch-M) 和架构稳定性 (Sch-S) |
| 大容量更新 (BU) | 在将数据大容量复制到表中且指定了 TABLOCK 提示时使用 |
| 键范围 (Range) | 当使用可序列化事务隔离级别时保护查询读取的行的范围。 确保再次运行查询时其他事务无法插入符合可序列化事务的查询的行 |
利用SQL Server Profiler观察锁
1. 准备数据10条数据
2. 打开SQL Server Profiler选中锁事件,勾选type和mode,建议取消不需要观察的列,然后用列筛选器过滤要观察的DB

3. 查询数据

可以看到在页面级别加上意向共享锁,因为我们数据只有一页
4. 更新一条数据

1. 表上加上意向排它锁(IX),可以用select OBJECT_NAME(581577110) 查看objectid代表的东西
2. 页级别加上意向更新锁(IU),告诉SQL Server引擎这里有更新锁
3. 获取第一行的更新锁(U),这里条件匹配
4. 页级别升级为意向排他锁(IX), 告诉SQL Server引擎这里有排他锁
5. 第一个行更新锁 升级为排它锁(X)
6. 释放锁
7. 随条扫描后面的记录,只是条件不符合,也就不会升级锁级别
可以看到是全表扫描,因为没聚集索引(堆表),我们也没做一个主键,下面将Id添加主键然后再更新试试
alter table DataTable add constraint PK_DataTable primary key(Id asc)

可以看出,直接在表,页级别加上意向排它锁(IX),然后在键上加上排它锁(X)
因为这里我们用主键更新,而且SQL Server主键默认是聚集索引,如果指定是非聚集索引主键,这里也会经历更新锁 到 排他锁,有兴趣的可以自行验证
5. 删除一条数据

这次我们没用主键删除,过程和更新的第一种情况差不多,就不列了。
因为加了聚集索引,索引定位器执行聚集索引Key的hash,要验证是否那条记录,可以在删除前加上%%lockres%%去查
死锁产生的原因及避免
死锁产生的原因
微软文档是这样说
在两个或多个任务中,如果每个任务锁定了其他任务试图锁定的资源,此时会造成这些任务永久阻塞,从而出现死锁
我理解就是有2个事务循环依赖对方的资源导致产生死锁。
例如
1. 事务A 获取 Row1 资源
2. 事务B 获取 Row2 资源
3. 事务A获取Row2资源,由于这时Row2是被事务B占有,所以必须等事务B完成
4. 事务B获取Row1资源,由于这时Row1是被事务A占有,所以必须等事务A完成
SQL Server处理死锁策略
1. 定期检查陷入死锁的任务
2. 若检查到循环依赖
3. 选择其中一个作为牺牲品,然后终止事务,然另外一个得以完成
模拟死锁
分别在两个不同的会话执行下面语句

begin tran; update DataTable set Address = '上海市' where Id = 2;
--延迟5秒执行
WAITFOR DELAY '00:00:05';
update DataTable set Address = '上海市' where Id = 3; commit;


begin tran; update DataTable set Address = '上海市' where Id = 3;
--延迟5秒执行
WAITFOR DELAY '00:00:05';
update DataTable set Address = '上海市' where Id = 2; commit;

执行一段时间,其中一个会出现下面错误

SQL Server Profiler 捕获死锁分析
打开Locks事件的死锁图形
重新执行上面语句,模拟死锁,Profiler捕获到死锁


可以看出
1. 进程56 请求的Key 的排它锁 被进程 54 占有
2. 进程54 请求的Key 的排他锁 被进程 56 占有
3. 形成了循环依赖
我们这里的Sql比较简单,而且没有用参数化执行,所以我们指定是哪一行被锁,线上的通常不能直接看到哪一行被锁
我们可以通过xml查看等待的资源,在xml里面有process-list 下面有多个process,process节点上面有个waitresource属性,这个指出每个进程等待的资源

锁类型:db_id : hobt_id : (hashvalue)
KEY: 6:72057594043760640 (61a06abd401c)
通过%%lockres%% 查到被锁资源
select %%lockres%%,* from DataTable where %%lockres%% = '(98ec012aa510)'
锁类型不一样,得到的会不一样,根据各自的格式用db_name / object_name / dbcc去查到当前被锁的资源,有时候需要利用DBCC查询Page存储页面,可以参考上一篇文章【SQL SERVER】数据内部存储结构简单探索
避免死锁
首先需要说明死锁不能完全避免,但遵守特定的编码惯例可以将发生死锁的机会降至最低
1. 按同一顺序访问对象,一个获取锁,另外一个就必须等待
2. 避免事务中的用户交互 ,这样导致事务时间过长,容易造成死锁
3. 保持事务简短并处于一个批处理中,道理和2一样,尽量让事务运行时间短。
4. 使用较低的隔离级别,这个看能不能接受脏读,幻读等副作用
总结
1. 锁机制保证并发情况下的数据访问。
2. 开发中应该尽量利用索引检索数据,特别是UPDATE/DELETE这种需要排它锁,应该利用唯一聚集索引字段更新(通常是主键)
3. 规范使用事务能减少死锁发生
转发请标明出处:https://www.cnblogs.com/WilsonPan/p/12618849.html
[转帖]【SQL SERVER】锁机制的更多相关文章
- SQL Server 锁机制 悲观锁 乐观锁 实测解析
先引入一些概念,直接Copy其他Blogs中的,我就不单独写了. 一.为什么会有锁 多个用户同时对数据库的并发操作时会带来以下数据不一致的问题: 1.丢失更新 A,B两个用户读同一数据并进行修改,其中 ...
- SQL Server 锁机制
锁兼容性图: 一.锁的粒度: 比较需要注意的是RID/KEY.HoBT/PAGE这两对儿的区别,RID和HoBT是针对堆表的,即没有聚集索引的表. 二.锁的模式: 1.关于其中的S.U.X锁: 共享锁 ...
- 简单理解SQL Server锁机制
多个用户同时对数据库的并发操作时,可能会遇到下面几种情况,导致数据前后不一致: 1,A.B事务同时对同一个数据进行修改,后提交的人的修改结果会破坏先提交的(丢失更新): 2,事务A修改某一条数据还未提 ...
- Sql server锁机制
如何查看锁 了解SQL Server在某一时间点上的加锁情况无疑是学习锁和诊断数据库死锁和性能的有效手段.我们最常用的查看数据库锁的手段不外乎两种: 使用sys.dm_tran_locks这个DMV ...
- [转]了解SQL Server锁争用:NOLOCK 和 ROWLOCK 的秘密_Mr_Indigo的空间
了解SQL Server锁争用:NOLOCK 和 ROWLOCK 的秘密 关系型数据库,如SQL Server,使用锁来避免多用户修改数据时的并发冲突.当一组数据被某个用户锁定时,除非第一个用户结束修 ...
- 了解SQL Server锁争用:NOLOCK 和 ROWLOCK 的秘密
关系型数据库,如SQL Server,使用锁来避免多用户修改数据时的并发冲突.当一组数据被某个用户锁定时,除非第一个用户结束修改并释放锁,否则其他用户就无法修改该组数据. 有些数据库,包括SQL Se ...
- 转:sql server锁知识及锁应用
sql server锁(lock)知识及锁应用 提示:这里所摘抄的关于锁的知识有的是不同sql server版本的,对应于特定版本时会有问题. 一 关于锁的基础知识 (一). 为什么要引入锁 当多个用 ...
- SQL SERVER锁(LOCK)知识及锁应用
提示:这里所摘抄的关于锁的知识有的是不同sql server版本的,对应于特定版本时会有问题. 一 关于锁的基础知识 (一). 为什么要引入锁 当多个用户同时对数据库的并发操作时会带来以下数据不一致的 ...
- sql server 锁与事务拨云见日(中)
一.事务的概述 上一章节里,重点讲到了锁,以及锁与事务的关系.离上篇发布时间好几天了,每天利用一点空闲时间还真是要坚持.听<明朝那些事儿>中讲到"人与人最小的差距是聪明,人与人最 ...
- sql server 锁与事务拨云见日(上)
一.概述 讲到sql server锁管理时,感觉它是一个大话题,因为它不但重要而且涉及的知识点很多,重点在于要掌握高并发要先要掌握锁与事务,涉及的知识点多它包括各式各样的锁,锁的组合,锁的排斥,锁延伸 ...
随机推荐
- 如何用.net制作一个简易爬虫抓取华为应用市场数据
公司最近要做一款手机,手机需要制作一个应用市场.那么问题来了,自己制作应用市场,数据从哪来呢?作为一个创业型公司.搜集数据变成为了难题. 于是突然想到能不能通过程序去抓取别人应用市场的数据-- 那么我 ...
- 这一次,弄明白JS中的文件相关(一):概念篇
概念是学习的基础.在学习JS中的文件操作之前,先把文件相关的各种概念搞清楚,很有好处. 1. 二进制: 计算机硬件仅能处理和存储二进制数据,所以不管是你正在写的代码,还是你硬盘里的小姐姐,都是以二进制 ...
- 文心一言 VS 讯飞星火 VS chatgpt (48)-- 算法导论6.1 6题
值为<23,17,14,6,13,10,1,5,7,12>的数组是一个最大堆吗? 文心一言: 是的,这个数组是一个最大堆. 最大堆是一种特殊的二叉树,它满足以下性质:对于任意节点 x,其子 ...
- 文心一言 VS 讯飞星火 VS chatgpt (32)-- 算法导论5.2 4题
四.利用指示器随机变量来解如下的帽子核对问题(hat-heck problem):n位顾客,他们每个人给餐厅核对帽子的服务生一顶帽子.服务生以随机顺序将帽子归还给顾客.请问拿到自己帽子的客户的期望数是 ...
- 微信小程序本地测试报错 IllegalArgumentException
在微信小程序本地测试时出现 IllegalArgumentException 错误,解决方法将https换成http Note: further occurrences of HTTP request ...
- 在Docker上面安装/启动、运行、挂载MySQL5.7
下载文档请看:https://hub.docker.com/r/mysql/mysql-server 一.下载镜像 执行命令: docker pull mysql/mysql-server:5.7 查 ...
- 云图说|什么是可信智能计算服务TICS
阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 本文分享自华为云社区&l ...
- 今天又和Redis超时杠上了
摘要:究竟是不是cpu占比高的问题导致redis超时的呢? 本文分享自华为云社区<我又和redis超时杠上了>,作者:蓝胖子的编程梦 . 背景 经过上次redis超时排查,并联系云服务商解 ...
- 技术实践丨PostgreSQL插件之pg_dirtyread "闪回查询"
摘要:Oracle数据库有时候不小心删除掉数据,想查询这些数据,或者恢复数据,就可以使用带有as of子句的select语句进行闪回查询. PG粉有福了,下面介绍一种类似"闪回查询" ...
- 【有奖征文】WEB前端大作战,走在技术最前端!
摘要:投稿分享你在前端领域的积累,秀出你的技术"肌肉",为自己,也为技术发声. 近几年大家对于WEB前端的关注度很高, 比如整体势头发展良好,各种技术百花齐放,人才稀缺, 随着互联 ...