SQL Server的死锁说明

news2025/2/26 6:04:08

死锁指南

  • 一、了解死锁
  • 二、检测并结束死锁
    • 2.1、可能死锁的资源
  • 三、处理死锁
  • 四、最大限度地减少死锁
    • 4.1、以相同的顺序访问对象
    • 4.2、避免事务中的用户交互
    • 4.3、保持交易简短且在一个批次中
    • 4.4、使用较低的隔离级别
    • 4.5、使用基于行版本控制的隔离级别
    • 4.6、使用绑定连接
    • 4.7、停止事务
  • 总结

一、了解死锁

死锁是导致数据库中的竞争性并发锁,通常在多步骤事务中。
当两个或多个任务永久相互阻止时,每个任务都锁定了其他任务尝试锁定的资源,就会发生死锁。例如:

  • 事务 A 获取第 1 行上的共享锁。
  • 事务 B 获取第 2 行上的共享锁。
  • 事务 A 现在请求第 2 行上的独占锁,并被阻止,直到事务 B 完成并释放第 2 行上的共享锁。
  • 事务 B 现在请求第 1 行上的独占锁,并被阻止,直到事务 A 完成并释放它在第 1 行上的共享锁。

事务 A 在事务 B 完成之前无法完成,但事务 B 被事务 A 阻止。此条件也称为循环依赖关系:事务 A 依赖于事务 B,事务 B 通过对事务 A 的依赖来关闭循环。

死锁中的两个事务将永远等待,除非死锁被外部进程打破。SQL Server 数据库引擎死锁监视器定期检查处于死锁状态的任务。如果监视器检测到循环依赖关系,它将选择其中一个任务作为受害者,并在出现错误的情况下终止其事务。这允许其他任务完成其事务。具有因错误而终止的事务的应用程序可以重试该事务,该事务通常在另一个死锁事务完成后完成。

死锁经常与正常阻塞混淆。当一个事务请求锁定另一个事务锁定的资源时,请求事务将等待,直到锁定被释放。默认情况下,除非设置了LOCK_TIMEOUT,否则 SQL Server 事务不会超时。请求事务被阻止,而不是死锁,因为请求事务没有执行任何操作来阻止拥有锁的事务。最终,拥有事务将完成并释放锁,然后请求事务将被授予锁定并继续。死锁几乎可以立即解决,而阻塞理论上可以无限期地持续存在。僵局有时被称为致命的拥抱。

死锁是可能发生在具有多个线程的任何系统上的情况,而不仅仅是在关系数据库管理系统上,并且可能发生在数据库对象上的锁以外的资源上。例如,多线程操作系统中的线程可能会获取一个或多个资源,例如内存块。如果要获取的资源当前由另一个线程拥有,则第一个线程可能必须等待拥有该线程释放目标资源。据说等待线程依赖于该特定资源的拥有线程。在 SQL Server 数据库引擎实例中,会话在获取非数据库资源(如内存或线程)时可能会死锁。
在这里插入图片描述

在图中,事务 T1 依赖于表锁资源的事务 T2。同样,事务 T2 依赖于表锁资源的事务 T1。由于这些依赖项形成一个循环,因此事务 T1 和 T2 之间存在死锁。

当对表进行分区并将 的设置设置为 AUTO 时,也会发生死锁。设置为 AUTO 时,通过允许 SQL Server 数据库引擎在 HoBT 级别而不是表级别锁定表分区,并发性会增加。但是,当单独的事务在表中持有分区锁并希望在其他事务分区上的某个位置使用锁时,这会导致死锁。这种类型的死锁可以通过设置为 ;尽管此设置将通过强制对分区进行大量更新以等待表锁定来降低并发性。

二、检测并结束死锁

当两个或多个任务永久相互阻止时,每个任务都锁定了其他任务尝试锁定的资源,就会发生死锁。下图显示了死锁状态的高级视图,其中:

  • 任务 T1 锁定了资源 R1(由从 R1 到 T1 的箭头指示),并请求锁定资源 R2(由从 T1 到 R2 的箭头指示)。
  • 任务 T2 锁定了资源 R2(由从 R2 到 T2 的箭头指示),并请求锁定资源 R1(由从 T2 到 R1 的箭头指示)。
  • 由于在资源可用之前,这两个任务都无法继续,并且在任务继续之前无法释放这两个资源,因此存在死锁状态。

在这里插入图片描述
SQL Server 数据库引擎会自动检测 SQL Server 中的死锁周期。SQL Server 数据库引擎选择其中一个会话作为死锁受害者,当前事务将终止,并显示错误以打破死锁。

2.1、可能死锁的资源

每个用户会话可能代表其运行一个或多个任务,其中每个任务可能获取或等待获取各种资源。以下类型的资源可能会导致阻塞,从而导致死锁。

  • 锁。等待获取资源(如对象、页面、行、元数据和应用程序)的锁可能会导致死锁。例如,事务 T1 在行 r1 上具有共享 (S) 锁,并且正在等待在 r2 上获取独占 (X) 锁。事务 T2 在 r2 上具有共享 (S) 锁,并且正在等待在行 r1 上获取独占 (X) 锁。这会导致锁定循环,其中 T1 和 T2 相互等待对方释放锁定的资源。

  • 工作线程。等待可用工作线程的排队任务可能会导致死锁。如果排队的任务拥有阻止所有工作线程的资源,则会导致死锁。例如,会话 S1 启动事务并在行 r1 上获取共享 (S) 锁,然后进入睡眠状态。在所有可用工作线程上运行的活动会话正在尝试获取行 r1 上的独占 (X) 锁。由于会话 S1 无法获取工作线程,因此它无法提交事务并释放行 r1 上的锁。这会导致死锁。

  • 内存。当并发请求正在等待可用内存无法满足的内存授予时,可能会发生死锁。例如,两个并发查询 Q1 和 Q2 作为用户定义的函数执行,分别获取 10 MB 和 20 MB 的内存。如果每个查询需要 30 MB,总可用内存为 20 MB,则 Q1 和 Q2 必须等待对方释放内存,这会导致死锁。

  • 与并行查询执行相关的资源。与交换端口关联的协调器、生产者或使用者线程可能会相互阻塞,从而导致死锁,通常是在包含至少一个不属于并行查询一部分的其他进程时。此外,当并行查询开始执行时,SQL Server 会根据当前工作负荷确定并行度或工作线程数。如果系统工作负荷意外更改(例如,新查询开始在服务器上运行或系统工作线程不足),则可能会发生死锁。

  • 多个活动结果集 (MARS) 资源。用户资源、会话互斥锁、事务互斥锁等这些资源用于控制 MARS 下多个活动请求的交错。

为了使任务在 MARS 下运行,它必须获取会话互斥锁。如果任务在事务下运行,则必须获取事务互斥锁。这保证在给定会话和给定事务中一次只有一个任务处于活动状态。获取所需的互斥锁后,任务就可以执行。当任务完成或在请求中间产生时,它将首先释放事务互斥锁,然后以相反的获取顺序释放会话互斥锁。但是,这些资源可能会发生死锁。在以下伪代码中,两个任务(用户请求 U1 和用户请求 U2)在同一会话中运行。

从用户请求 U1 执行的存储过程已获取会话互斥锁。如果存储过程需要很长时间才能执行,则 SQL Server 数据库引擎假定存储过程正在等待用户的输入。用户请求 U2 正在等待会话互斥锁,而用户正在等待来自 U2 的结果集,U1 正在等待用户资源。这是死锁状态,逻辑上说明为:
在这里插入图片描述

三、处理死锁

当 SQL Server 数据库引擎实例选择某个事务作为死锁受害者时,它将终止当前批处理,回滚该事务,并向应用程序返回错误消息 1205。

由于提交 Transact-SQL 查询的任何应用程序都可以被选为死锁受害者,因此应用程序应具有可以捕获错误消息 1205 的错误处理程序。如果应用程序未捕获错误,则应用程序可以在不知道其事务已回滚并可能发生错误的情况下继续操作。

实现捕获错误消息 1205 的错误处理程序允许应用程序处理死锁情况并采取补救措施(例如,自动重新提交死锁中涉及的查询)。通过自动重新提交查询,用户无需知道发生了死锁。

在重新提交查询之前,应用程序应短暂暂停。这使死锁中涉及的其他事务有机会完成并释放构成死锁循环一部分的锁。这样可以最大程度地降低在重新提交的查询请求其锁时再次发生死锁的可能性。

四、最大限度地减少死锁

尽管无法完全避免死锁,但遵循某些编码约定可以最大程度地减少生成死锁的可能性。最小化死锁可以提高事务吞吐量并减少系统开销,因为事务较少:

  • 回滚,撤消事务执行的所有工作。
  • 由应用程序重新提交,因为它们在死锁时已回滚。

要帮助最大程度地减少死锁,请执行以下操作:

  • 以相同的顺序访问对象。
  • 避免事务中的用户交互;保持交易简短且批量。
  • 使用较低的隔离级别。
  • 使用基于行版本控制的隔离级别。将数据库选项设置为启用已提交的读取事务以使用行版本控;使用快照隔离。
  • 使用绑定连接。

4.1、以相同的顺序访问对象

如果所有并发事务都以相同的顺序访问对象,则不太可能发生死锁。例如,如果两个并发事务在表上获取锁,然后在表上获得锁,则一个事务在表上被阻止,直到另一个事务完成。第一个事务提交或回滚后,第二个事务将继续,并且不会发生死锁。对所有数据修改使用存储过程可以标准化访问对象的顺序。
在这里插入图片描述

4.2、避免事务中的用户交互

避免编写包含用户交互的事务,因为无需用户干预即可运行的批处理的速度比用户必须手动响应查询(例如回复应用程序请求的参数提示)的速度快得多。例如,如果事务正在等待用户输入,并且用户周末去吃午饭甚至回家,则用户会延迟事务完成。这会降低系统吞吐量,因为事务持有的任何锁仅在提交或回滚事务时释放。即使没有出现死锁情况,访问相同资源的其他事务也会在等待事务完成时被阻止。

4.3、保持交易简短且在一个批次中

当多个长时间运行的事务在同一数据库中同时执行时,通常会发生死锁。事务时间越长,独占锁或更新锁的持有时间就越长,从而阻止其他活动并导致可能的死锁情况。

将事务保存在一个批次中可最大程度地减少事务期间的网络往返,从而减少完成事务和释放锁定时可能出现的延迟。

4.4、使用较低的隔离级别

确定事务是否可以在较低的隔离级别运行。实现 read commit 允许事务读取先前由另一个事务读取(未修改)的数据,而无需等待第一个事务完成。与较高的隔离级别(如可序列化)相比,使用较低的隔离级别(如已提交的读取)保留共享锁的持续时间更短。这减少了锁定争用。

4.5、使用基于行版本控制的隔离级别

当数据库选项设置为 ON 时,在读取提交隔离级别下运行的事务在读取操作期间使用行版本控制而不是共享锁。
快照隔离还使用行版本控制,在读取操作期间不使用共享锁。在事务可以在快照隔离下运行之前,必须设置数据库选项ALLOW_SNAPSHOT_ISOLATIONON。

实现这些隔离级别,以最大程度地减少读取和写入操作之间可能发生的死锁。

4.6、使用绑定连接

使用绑定连接,同一应用程序打开的两个或多个连接可以相互协作。辅助连接获取的任何锁都像由主连接获取一样保存,反之亦然。因此,它们不会相互阻塞。

4.7、停止事务

在死锁方案中,受害事务会自动停止并回滚。在死锁情况下无需停止事务。

总结

有些应用程序依赖于读取提交隔离的锁定和阻止行为。对于这些应用程序,在启用使用基于行版本控制的隔离级别之前需要进行一些更改。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/427442.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【云原生|Docker】04-docker的资源限制

目录 前言 容器的生命周期 1. 容器的启动过程 2. 容器的生命周期 ​编辑 内存限制 1. 内存限制的相关参数 2. 内存限制方式 2.1 设置-m,--memory,不设置--memory-swap 2.2 设置-m,--memorya,--memory-swapb,且b >a 2.…

本地从0搭建Stable Diffusion WebUI及错误记录

从0开始搭建本地Stable Diffusion WebUI环境 一.环境配置 1.使用的电脑配置 系统Windows10处理器英特尔 i7内存24GB显卡NVIDIA GTX 1060(6GB) 2.镜像源 阿里云 清华大学 中国科技大学 3.电脑环境变量配置 我的电脑–属性–高级系统设置–系统属性(高级)–环境变量 新建…

spring框架注解

3.Spring有哪些常用注解呢? Spring常用注解 Web: Controller:组合注解(组合了Component注解),应用在MVC层(控制层)。 RestController:该注解为一个组合注解,相当于Con…

首个ChatGPT开发的应用上线;ChatMind思维导图工具;中文提示词大全;Copilot平替 | ShowMeAI日报

👀日报&周刊合集 | 🎡生产力工具与行业应用大全 | 🧡 点赞关注评论拜托啦! 🤖 『一本与众不同的AI绘本』ChatGPT 编写故事 Midjourney 绘制插图 作者的女儿特别喜欢迪士尼动画《海洋奇缘》里的主人公莫阿娜&#…

Mybatis分解式查询

目录 一、Mybatis一对多分解式查询 1. 新增持久层接口方法 2. 新增映射文件对应的标签 3. 新增测试方法 4. 运行效果 二、Mybatis一对一分解式查询 1. 新增持久层接口方法 2. 新增映射文件对应的标签 3. 新增测试方法 4. 运行效果 三、Mybatis延迟加载 1. 开启延迟加…

超实用的十个超级实用事半功倍的Python自动化脚本

一淘模板 56admin.com在日常的工作学习当中,我们总会遇到各式各样的问题,其中不少的问题都是一遍又一遍简单重复的操作,不妨直接用Python脚本来自动化处理,今天小编就给大家分享十个Python高级脚本,帮助我们减少无谓的…

【数据结构与算法】栈的实现(附源码)

目录 一.栈的概念和结构 二.接口实现 A.初始化 Stackinit 销毁 Stackdestroy 1.Stackinit 2.Stackdestroy B.插入 Stackpush 删除 Stackpop 1.Stackpush 2.Stackpop C.出栈 Stacktop D. 栈的有效元素 Stacksize 判空 Stackempty 1.Stacksize 2.Stackempty …

Flink进阶篇-CDC 原理、实践和优化采集到Doris中

简介 基于doris官方用doris构建实时仓库的思路,从flinkcdc到doris实时数仓的实践。 原文 Apache Flink X Apache Doris 构建极速易用的实时数仓架构 (qq.com) 前提-Flink CDC 原理、实践和优化 CDC 是什么 CDC 是变更数据捕获(Change Data Captur…

Spring《三》DI依赖注入

🍎道阻且长,行则将至。🍓 上一篇:Spring《二》bean的实例化与生命周期 下一篇:敬请期待 目录一、setter注入🍉1.注入引用数据类型2.注入简单数据类型二、构造器注入🍊1.注入引用数据类型2.简单数…

数据挖掘(2.3)--数据预处理

目录 三、数据集成和转换 1.数据集成 2.数据冗余性 2.1 皮尔森相关系数 2.2卡方检验 3.数据转换 四、数据的规约和变换 1.数据归约 2数据离散化 三、数据集成和转换 1.数据集成 数据集成是将不同来源的数据整合并一致地存储起来的过程。 不同来源的数据可能有不同…

Qt优秀开源项目之十七:QtPromise

QtPromise是Promises/A规范的Qt/C实现。该规范的译文见附录。 QtPromise基于Qt5.6及以上版本,当然也包括Qt6。 github地址:https://github.com/simonbrunel/qtpromise 新手导航:Getting Started | QtPromise API手册:API Referenc…

详解Spring、SpringBoot、SpringCloud三者的联系与区别

一、Spring二、Spring Boot三、Spring Cloud四、三者的关系一、Spring Spring 是一个轻量级的Java 开发框架,主要依存于SSM 框架,即Spring MVC Spring Mybatis,定位很明确,Spring MVC主要负责view 层的显示,Spring …

Scala 一文搞定

第一节:概述为什么学习Scala ?Apache Spark 是专为大规模数据快速实时处理的计算引擎/内存级大数据计算框架。Apache Spark 是由Scala 语言编写。Scala 与Java 关系总结三点:java 编译器与Scala 编译器可以相互使用。Java SDK 的类库可以被Scala使用,Sc…

理解什么是sql注入攻击 + xss攻击 + cors 攻击

SQL注入 SQL注入就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。 SQL注入攻击的总体思路: 寻找到SQL注入的位置判断服务器类型和后台数据库类型针对不同的服务器和数据库特点进行SQL注入攻击 SQL注入…

Cookie和Session的工作流程及区别(附代码案例)

目录 一、 HTTP协议 1.1 为什么HTTP协议是无状态的? 1.2 在HTTP协议中流式传输和分块传输编码的区别 二、Cookie和Session 2.1 Cookie 2.2 Session 2.3 Cookie和Session的区别 三、servlet中与Cookie和Session相关的API 3.1 HttpServletRequest 类中的相关方…

CSRF漏洞的概念、利用方式、防御方案

CSRF漏洞1.CSRF的概念1.1 什么是CSRF?1.2 基本攻击流程2.CSRF攻击实现2.1 靶场练习2.2 CSRFXSS组合拳2.2.1 攻击页面部署2.2.2 构造恶意xss语句,实现重复生效的CSRF3. CSRF攻击的防御**3.1 只使用JSON API****3.2 验证HTTP Referer字段****3.3 在请求地址…

【Spring源码】Spring事务原理

目录 1、什么是事务 2、Spring事务基本概念 2.1、基础配置 2.1.1、Spring事务的基础配置 2.1.2、Spring事务的传播特性 2.1.3、Spring事务的隔离级别 2.2、基本原理 3、事务嵌套 3.1、PROPAGATION_REQUIRED 3.2、PROPAGATION_REQUIRES_NEW 3.3、PROPAGATION_SUPPORTS…

【时序论文小集】

目录【2021 NeurIPS】Autoformer: Decomposition Transformers with Auto-Correlation for Long-Term Series Forecasting【2022 ICML】FEDformer: Frequency Enhanced Decomposed Transformer for Long-term Series Forecasting【2023 ICLR】TIMESNET: TEMPORAL 2D-VARIATION …

【云原生】k8s NetworkPolicy 网络策略是怎么样的

前言 随着微服务的流行,越来越多的云服务平台需要大量模块之间的网络调用。 在 Kubernetes 中,网络策略(NetworkPolicy)是一种强大的机制,可以控制 Pod 之间和 Pod 与外部网络之间的流量。 Kubernetes 中的 NetworkPolicy 定义了一组规则&…

FastAPI: 极速开发Python Web应用的未来之星

我在工作中经常使用Flask来开发Web应用。但是随着项目规模的增长,我发现自己需要写越来越多的重复代码,同时Flask并没有提供一个良好的数据验证和文档生成工具。 有一天,我听说了一个名为FastAPI的框架,它被誉为是Python Web框架…