讲解更新锁(U)与排它锁(X)的相关知识

一直没有认真了解UPDATE操作的锁,最近在MSDN论坛上看到一个问题,询问堆表更新的死锁问题,问题很简单,有类似这样的表及数据:

CREATE TABLE dbo.tb(     c1 int,     c2 char(10),     c3 varchar(10));GODECLARE @id int;SET @id = 0;WHILE @id <5BEGIN;     SET @id = @id + 1;     INSERT dbo.tb VALUES( @id, 'b' + RIGHT(10000 + @id, 4), 'c' + RIGHT(100000 + @id, 4) );END;

在查询一中执行更新操作:

BEGIN TRANUPDATE dbo.tb SET c2 = 'xx' WHERE c1 = 2;WAITFOR DELAY '00:00:30';UPDATE dbo.tb SET c2 = 'xx' WHERE c1 = 5;ROLLBACK;

在查询一执行开始后,马上在查询二中执行下面的操作

BEGIN TRANUPDATE dbo.tb SET c2 = 'xx' WHERE c1 = 1;ROLLBACK;

为什么会出现死锁,如果条件改为 c1 = 4 则不会死锁。

开始的时候想得比较简单,死锁的表现是形成循环等待(对于两个查询而言,可以简单地认为就是在相互等待对方锁定资源的释放)。

对于这个例子而言,第一个查询更新两次,会先更新并锁定一条记录,然后等待第二个更新;但第二个查询只会更新一条记录,它要么与第一个查询冲突,无法获得锁,需要等待查询一完成,这个时候它并没有锁定什么;要么能够获得锁,完成更新。似乎不应该会出现死锁,死锁会不会是其他原因导致。

在自己的电脑上简单测试了一下,似乎也确实没有死锁。

但后面通过Profile跟踪更新操作的下锁情况才发现,自己的分析大错特错了。主要原因在于没有正确理解更新操作是如何用锁的。

在联机帮助上“锁模式”中有关于更新的U(更新锁)和X(排它锁)的说明

http://msdn.microsoft.com/zh-cn/library/ms175519(v=sql.105).aspx

不过说得确实挺模糊的,里面还提到了S锁,我一直以为是查询数据过程中用的S锁(也 SELECT 一样),找到满足条件的记录后用U锁,再转换为X锁做更新。

    Profile(事件探查器)跟踪的结果让我知道了这是一个错误的理解,在Profile中新建一个跟踪,选择Locks中的Lock:Acquired(加锁),Lock:Acquired(释放锁)解两个事件,在筛选中设置只跟踪测试用的查询窗口对应的spid(可以执行 PRINT @@SPID获得),然后执行一个更新语句,比如 UPDATE dbo.tb SET c2 = ‘xx’ WHERE c1 = 3

在Profile中可以看到,对于每条记录都有加 U 锁的操作,对于不满足条件的记录,会马上释放U锁;对于满足条件的记录,最终转换为X锁。如下图所示。

讲解更新锁(U)与排它锁(X)的相关知识

注意一下,在这个跟踪结果里面,并没有出现S锁。

另外学做了一些测试:

通过加大记录量做更新测试,会发现数据扫描涉及的记录都有U锁,并不限于更新记录所在的页。这从另一个角度说明了大表中Scan 可怕。

当使用索引Scan的时候,也会通过跟踪发现所Scan的索引资源有U锁,如果更新不涉及索引变化,那以只会对应的记录有U转X锁,索引的U锁会释放;如果影响索引,那么索引的U锁会转X锁。

删除操作与更新操作类似

使用 UPDATE aSET c2 = ‘xx’ FROM dbo.tb AS a WITH(NOLOCK) WHERE c1 = 3  的加锁情况是一样的, 并不会因为NOLOCK的提示而不加 U 或者 X 锁

最后回头研究一下示例中的死锁问题:

对于查询一,第一个更新依次扫描表中所有记录,对于每条记录,加 U 锁,判断是否符合更新条件,如果符合,转换为 X 锁;如果不符合条件,释放 U 锁。第一个更新完成的时候,查询一锁定了一条记录(由于事务未完成,所以锁一直保持),然后等待第二个更新

对于查询二,依次扫描表中的每条记录(与前面的更新一样),如果它更新的记录在查询一更新的记录前被扫描到,那么这条记录也会变成 X 锁;当继续并进行到查询一的X锁记录的零点,U 与 X 冲突,无法继续,这时候查询二等待查询一释放锁

查询一的第二个更新开始执行,依次扫描每条记录,同一个事务内不会有冲突,所以它不会与自己之前锁定的记录有冲突,但进行到查询二锁定的记录的时候,它也无法获得 U 锁,它需要等待查询二释放资源。这个时候就形成了相互等待,符合死锁条件

如果查询二需要更新的记录在查询一的第一个更新记录之后,则不会有死锁,因为查询二在扫描到查询一第一个更新的记录时就会因为锁冲突等待了,这个时候它没有对任何记录设置与查询一的操作有冲突的锁。我自己测试的时候没有死锁,就是这种情况。

注意这里面提到的顺序,是数据读取的顺序,不一定与存储顺序一样,磁盘上记录的顺序也不一定与INSERT的记录顺序一样,这也是我用同样条件没有测试出死锁的原因(我的环境中,恰好读出的顺序与INSERT的顺序不一样)

更新时,记录读取的顺序,可以通过Profile跟踪的Lock:Acquired (加锁)事件来看,涉及大量数据时,如果服务器支持,还会有并发读取。这也是分析死锁时要考虑的因素

本文讲解了讲解更新锁(U)与排它锁(X)的相关知识,更多相关内容请关注创想鸟。

相关推荐:

SQL Server 2008 处理隐式数据类型转换在执行计划中的增强

如何让MySQL中单句实现无限层次父子关系查询

带进度的SQL Server FileStream如何存取

知我AI 知我AI

一款多端AI知识助理,通过一键生成播客/视频/文档/网页文章摘要、思维导图,提高个人知识获取效率;自动存储知识,通过与知识库聊天,提高知识利用效率。

知我AI 26 查看详情 知我AI



以上就是讲解更新锁(U)与排它锁(X)的相关知识的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/383626.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月6日 12:31:58
下一篇 2025年11月6日 12:33:45

相关推荐

  • Java中死锁如何避免 分析死锁产生的四个必要条件

    预防死锁最有效的方法是破坏死锁产生的四个必要条件中的一个或多个。死锁的四个必要条件分别是互斥、占有且等待、不可剥夺和循环等待;其中,互斥通常无法破坏,但可以减少使用;占有且等待可通过一次性申请所有资源来打破;不可剥夺可通过允许资源被剥夺打破;循环等待可通过按序申请资源解决。此外,reentrantl…

    2025年12月5日 java
    300
  • 热游情报:排面拉满!《黑神话》专访央视国庆节播出 《NIKKE》目标运营20年!

    大家周末好,我是x博士。 将由“新游动态”“全球热门”两个部分组成。 一句两句无法说清楚,还是跟X博士一起这周有哪些热点资讯吧。 划重点:排面!《黑神话》冯骥专访国庆当天在CCTV4播出 在10月1日国庆节当天,CCTV4的中国新闻栏目播出了《黑神话:悟空》制作人冯骥的专访,让玩家直呼“排面拉满”。…

    2025年12月2日 行业动态
    000
  • mysql死锁是怎么造成的

    造成%ignore_a_1%死锁的原因:两个或两个以上的进程在执行过程中争夺资源。mysql中有三种锁,分别是表级锁、行级锁和页面锁。其中,表级锁开销小、加锁快,不会出现死锁情况。 mysql是一种关系型数据库管理系统,使用的 SQL 语言是用于访问数据库的最常用标准化语言。在mysql的使用过程中…

    2025年12月2日 数据库
    000
  • mysql死锁是什么意思

    mysql死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环。InnoDB存储引擎能检测到死锁的循环依赖并立即返回一个错误。只有部分或完全回滚其中一个事务,才能打破死锁。 什么是死锁?它是如何产生的? 死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用…

    2025年12月2日 数据库
    000
  • mysql怎么查看有没有死锁

    mysql查看有没有死锁的方法:执行【show OPEN TABLES where In_use > 0;】命令查看。如果要解除死锁进程,则执行【kill id】命令。 具体方法: (视频教程推荐:mysql视频教程) 查询是否锁表 show OPEN TABLES where In_use …

    2025年12月2日 数据库
    000
  • mysql事务中死锁如何解决_mysql事务死锁处理方法

    死锁是多个事务相互等待对方释放锁导致的僵局,MySQL会自动回滚一事务打破循环。常见原因包括加锁顺序不一致、全表扫描、长事务等。通过SHOW ENGINE INNODB STATUS可查看最近死锁详情,定位冲突SQL。避免措施有:统一加锁顺序、缩短事务时间、使用索引、合理设置隔离级别。应用层应捕获错…

    2025年12月2日 数据库
    000
  • 如何避免 Java 函数中的死锁和争用条件?

    避免 java 并发中的死锁和争用条件:避免死锁: 使用锁排序,始终以相同的顺序获取锁。避免争用条件: 使用同步机制(锁或原子变量)确保共享数据在同一时间只被一个线程访问。 避免 Java 函数中的死锁和争用条件 简介 死锁和争用条件是 Java 并发编程中常见的错误,可能导致程序长时间阻塞或产生不…

    2025年12月2日 java
    000
  • 数据库死锁产生的原因及解决方案是什么

    死锁(Deadlock) 所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。 由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助…

    2025年11月28日 数据库
    000
  • 数据库死锁产生的原因及解决方案

    数据库死锁产生的原因及解决方案:1、程序的BUG产生,需要调整的程序的逻辑;2、页面的按钮没有立即生效,需要使用乐观锁、悲观锁进行控制;3、执行多个不满足条件的update语句;需要对语句进行分析,建立相应的索引进行优化。 数据库死锁产生的原因及解决方案: 在数据库中有两种基本的锁类型:排它锁(Ex…

    2025年11月26日 数据库
    000
  • 如何实现MySQL底层优化:事务锁的性能优化和避免死锁的方法

    如何通过事务锁的性能优化和避免死锁来实现MySQL底层优化 导言:在MySQL数据库中,事务锁起着至关重要的作用。如果事务锁的性能不好或者存在死锁,将严重影响数据库的性能和稳定性。因此,本文将重点介绍如何通过优化事务锁的性能和避免死锁来实现MySQL底层优化。 一、事务锁的性能优化方法 使用合适的事…

    2025年11月18日
    000
  • 如何实现MySQL底层优化:事务锁的高级性能优化和避免死锁的方法

    如何实现MySQL底层优化:事务锁的高级性能优化和避免死锁的方法 引言:在数据库系统中,事务锁是保证数据一致性和并发访问的重要机制之一。然而,在高并发场景下,事务锁可能会导致性能问题和死锁。为了提高MySQL性能,我们需要对事务锁进行高级性能优化,并采取措施避免死锁的发生。本文将介绍MySQL底层事…

    2025年11月18日
    000
  • Java并发编程避坑指南:8种常见死锁场景与解决方案

    死锁是Java并发编程中多个线程因循环等待资源而陷入的永久阻塞状态。文章详细分析了8种常见死锁场景及解决方案:1. 经典资源顺序死锁,通过统一锁获取顺序避免;2. 多资源有序死锁,采用全局资源编号并按序获取;3. 数据库死锁,确保事务访问表顺序一致并缩短持有锁时间;4. 嵌套同步块死锁,保持嵌套锁获…

    2025年11月17日
    000
  • sql中死锁如何避免 死锁检测和预防的四种策略

    sql死锁是两个或多个事务相互持有对方所需资源,导致彼此无法继续执行的情况。1.避免长事务,将其拆分为多个小事务,尽快释放资源;2.统一事务访问资源的顺序,防止循环等待;3.避免交叉更新,合并事务或使用加锁机制;4.设置合理锁超时时间,根据业务需求调整,并开启数据库自动死锁检测功能;5.优化sql语…

    2025年11月10日 数据库
    000
  • sql中怎么处理死锁 死锁处理的常用方法与预防措施

    死锁的解决方法主要包括预防和检测恢复两类。1.预防措施包括资源排序,强制事务按固定顺序请求资源;2.一次性请求所有资源,避免中途等待;3.设置超时机制,自动释放长时间占用资源;4.拆分长事务,减少资源占用时间。5.检测恢复则通过构建等待图发现环路确认死锁,随后选择代价最小、优先级最低或资源占用最少的…

    2025年11月10日 数据库
    000
  • 什么是死锁?

    死锁是进程间因资源竞争陷入无限等待的状态。其需满足互斥、占有且等待、不可剥夺、环路等待四个条件,打破任一条件可预防死锁。常用检测方法为资源分配图结合DFS检测环路,银行家算法可避免死锁但开销大。实际系统常采用超时或请求失败后处理的策略。避免死锁可通过破坏四个必要条件实现:破坏占有且等待需进程一次性申…

    2025年11月10日 java
    000
  • Oracle LOCK内部机制及最佳实践系列(五)给出一个导致死锁的SQL示例

    给出一个导致死锁的SQL示例死锁定义:从广义上讲包括操作系统应用程序数据库,如果2个进程(会话)相互持有对方的资源,都一直等待对方释放,这种情况会造成死锁 给出一个导致死锁的SQL示例 死锁定义:从广义上讲包括操作系统 应用程序 数据库,如果2个进程(会话)相互持有对方的资源,都一直等待对方释放,这…

    2025年11月9日
    000
  • Java框架如何应对并发编程中的死锁问题?

    在并发编程中,死锁可以通过 java 框架提供的机制解决,包括:锁定分层:组织锁成层次结构,防止循环依赖。超时机制:在等待锁超过指定时间后自动释放锁,打破死锁。活锁分析器:检测和报告死锁或活锁情况,活锁是一种不断尝试获取锁但永远不会成功的特殊死锁。 Java 框架如何应对并发编程中的死锁问题 在并发…

    2025年11月9日 java
    000
  • Java框架中如何处理数据库死锁问题?

    java框架中处理数据库死锁问题的实战指南:自定义错误处理:捕获特定死锁异常并进行自定义处理。连接池死锁检测:使用连接池检测死锁并将其报告给应用程序。乐观并发控制:使用版本号或时间戳来检测和解决冲突,避免数据库锁定。数据库锁定优化:使用更细粒度的锁定、减少锁定持有时间和避免不必要的锁定。定时器和超时…

    2025年11月9日 java
    000
  • 利用sys.sysprocesses检查SqlServer的阻塞和死锁

    Sys.SysProcesses 系统表是一个很重要的系统视图,主要用来定位与解决Sql Server的阻塞和死锁 MSDN:包含正在 SQL Server 实例上运行的进程的相关信息。这些进程可以是客户端进程或系统进程。 视图中主要的字段: 1. Spid:Sql Servr 会话ID 2. Kp…

    数据库 2025年11月7日
    000
  • MySQL死锁与日志分析

    本文主要和大家一起聊一聊mysql死锁与日志二三事,实际业务当中如何快速的定位线上mysql问题,修复异常?本文根据两个实际case,分享下相关的经验与方法,感兴趣的小伙伴们可以参考一下,希望能帮助到大家。 最近线上 MySQL 接连发生了几起数据异常,都是在凌晨爆发,由于业务场景属于典型的数据仓库…

    2025年11月6日 数据库
    200

发表回复

登录后才能评论
关注微信