热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数据库技术:【SQLSERVER】锁机制

SQLServer中锁机制保证并发情况下的数据访问,开发过程中利用好索引减少数据,能减少数据扫描数据加锁的过程,合理规范使用事务,

锁定是 sql server %ignore_a_1%引擎用来同步多个用户同时对同一个数据块的访问的一种机制。

  1. 利用sql server profiler观察锁

基本概念

数据库引擎隔离级别

隔离级别 定义
未提交的读取 隔离事务的最低级别,只能保证不读取物理上损坏的数据。 在此级别上,允许脏读,因此一个事务可能看见其他事务所做的尚未提交的更改
已提交的读取 允许事务读取另一个事务以前读取(未修改)的数据,而不必等待第一个事务完成。 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条数据

create table datatable(id int identity(1,1), [name] varchar(50), [address] varchar(200), createtime datetime2)      insert into datatable select 'wilson','广东省广州市',getdate() union all select 'alice','北京市朝阳区',getdate() union all select 'miksovsky','吉林省松原市',getdate() union all select 'hines','甘肃省兰州市',getdate() union all select 'kane','辽宁省沈阳市',getdate() union all select 'gode','湖北省荆州市',getdate() union all select 'chen','湖南省岳阳市',getdate() union all select 'trenary','福建省厦门市',getdate() union all select 'achong','广西省玉林市',getdate() union all select 'nixon','江西省景德镇',getdate() 

2. 打开sql server profiler选中锁事件,勾选type和mode,建议取消不需要观察的列,然后用列筛选器过滤要观察的db

【SQL SERVER】锁机制

3. 查询数据

【SQL SERVER】锁机制

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

4. 更新一条数据

【SQL SERVER】锁机制

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)

【SQL SERVER】锁机制

 

 

 可以看出,直接在表,页级别加上意向排它锁(ix),然后在键上加上排它锁(x)

因为这里我们用主键更新,而且sql server主键默认是聚集索引,如果指定是非聚集索引主键,这里也会经历更新锁 到 排他锁,有兴趣的可以自行验证

5. 删除一条数据

【SQL SERVER】锁机制

 

 

 这次我们没用主键删除,过程和更新的第一种情况差不多,就不列了。

因为加了聚集索引,索引定位器执行聚集索引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】锁机制

sql server profiler 捕获死锁分析

打开locks事件的死锁图形【SQL SERVER】锁机制

 

 重新执行上面语句,模拟死锁,profiler捕获到死锁

【SQL SERVER】锁机制

 【SQL SERVER】锁机制

可以看出

1. 进程56 请求的key 的排它锁  被进程 54 占有

2. 进程54 请求的key 的排他锁 被进程 56 占有

3. 形成了循环依赖

我们这里的sql比较简单,而且没有用参数化执行,所以我们指定是哪一行被锁,线上的通常不能直接看到哪一行被锁

我们可以通过xml查看等待的资源,在xml里面有process-list 下面有多个process,process节点上面有个waitresource属性,这个指出每个进程等待的资源

【SQL SERVER】锁机制

锁类型: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 | microsoft docs

需要了解更多数据库技术:【SQL SERVER】锁机制,都可以关注数据库技术分享栏目—编程笔记


推荐阅读
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 怎么在PHP项目中实现一个HTTP断点续传功能发布时间:2021-01-1916:26:06来源:亿速云阅读:96作者:Le ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • 本文介绍了使用kotlin实现动画效果的方法,包括上下移动、放大缩小、旋转等功能。通过代码示例演示了如何使用ObjectAnimator和AnimatorSet来实现动画效果,并提供了实现抖动效果的代码。同时还介绍了如何使用translationY和translationX来实现上下和左右移动的效果。最后还提供了一个anim_small.xml文件的代码示例,可以用来实现放大缩小的效果。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 高质量SQL书写的30条建议
    本文提供了30条关于优化SQL的建议,包括避免使用select *,使用具体字段,以及使用limit 1等。这些建议是基于实际开发经验总结出来的,旨在帮助读者优化SQL查询。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • 本文介绍了Windows操作系统的版本及其特点,包括Windows 7系统的6个版本:Starter、Home Basic、Home Premium、Professional、Enterprise、Ultimate。Windows操作系统是微软公司研发的一套操作系统,具有人机操作性优异、支持的应用软件较多、对硬件支持良好等优点。Windows 7 Starter是功能最少的版本,缺乏Aero特效功能,没有64位支持,最初设计不能同时运行三个以上应用程序。 ... [详细]
  • 基于dlib的人脸68特征点提取(眨眼张嘴检测)python版本
    文章目录引言开发环境和库流程设计张嘴和闭眼的检测引言(1)利用Dlib官方训练好的模型“shape_predictor_68_face_landmarks.dat”进行68个点标定 ... [详细]
author-avatar
丰田高耗能妨功害能侠盗飞车_948
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有