🌹欢迎来到《小5讲堂》🌹
🌹这是《C#》系列文章,每篇文章将以博主理解的角度展开讲解。🌹
🌹温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!🌹

在这里插入图片描述

目录

  • 前言
  • 锁定分析
    • Lock锁对象
    • 事务锁
    • 重复键
  • DeepSeek解决方案
    • 死锁的原因
    • 解决方案
      • 1. **减少事务范围**
      • 2. **优化 SQL 语句**
      • 3. **使用锁提示**
      • 4. **重试机制**
      • 5. **检查索引**
      • 6. **分析死锁图**
    • 示例代码改进
    • 总结
  • 相关文章

前言

最近博主在开发一个项目时,用到的都是基本框架功能,有些造轮子的意思。
如果不留意,那么很容易犯一些代码逻辑上的错误。
自己封装框架和使用现有成熟框架最大区别就是容易踩坑,除非你有比较多的框架开发经验。

锁定分析

Lock锁对象

这里博主犯了个小细节错误,锁的对象和范围逻辑不对,导致重复数据出现,大事务里存在同表查询和添加,即使在小量并发下,出现争抢资源,导致锁。

实例化锁对象
下面是错误写法,有发现那里不对吗?

namespace MvcMyNameSpace
{public class GetClass{private object lockObj = new object();public string GetNo(string tableName, string prefix){lock (lockObj){// 查询表string sql = "select top 1 * from Test"}}}

静态实例化
正确写法,确保锁对象是当前唯一

namespace MvcMyNameSpace
{public class GetClass{private static object lockObj = new object();public string GetNo(string tableName, string prefix){lock (lockObj){// 查询表string sql = "select top 1 * from Test"}}}

锁范围
博主在上面独立方法代码块加上锁后,运行一段时间任务后,发现还是会出现重复索引。
后来排查发现,是并发会在最外层接口方法没有锁定。
之后在接口API整个方法加了锁后,就再也没有出现了重复索引。

事务锁

博主这里是在一个大事务内进行了表查询,在高并发下就会出现,多个事务可能同时尝试更新或读取相同的数据行或表,导致资源竞争。

重复键

对于sql server数据库而言,可对表的字段设置唯一索引,确保数据库表唯一性。
如果表设置了唯一索引,那么还会出现重复,说明程序端代码逻辑不对,写法有问题。
博主此处出现的错误就是在并发情况,至少有两个并发同一时间获取到同一条记录。

DeepSeek解决方案

从你提供的代码和错误信息来看,程序在执行 SQL 命令时遇到了死锁问题。死锁通常发生在多个事务同时竞争相同的资源,并且每个事务都在等待其他事务释放锁时发生。SQL Server 检测到死锁后,会选择其中一个事务作为“牺牲品”并终止它,以便其他事务可以继续执行。

死锁的原因

在你的代码中,死锁可能由以下原因引起:

  1. 并发事务竞争相同的资源:多个事务可能同时尝试更新或读取相同的数据行或表,导致资源竞争。
  2. 事务范围过大:如果事务涉及多个表或大量数据,死锁的风险会增加。
  3. 锁的顺序不一致:如果不同的事务以不同的顺序锁定资源,可能会导致死锁。

解决方案

以下是几种可能的解决方案:

1. 减少事务范围

  • 尽量减少事务的持续时间,确保事务只包含必要的操作。
  • 如果可能,将事务拆分为多个较小的事务,减少锁的持有时间。

2. 优化 SQL 语句

  • 确保 SQL 语句尽可能高效,减少锁的持有时间。
  • 使用 WITH (NOLOCK) 提示来避免读取操作时的锁竞争(但要注意脏读的风险)。
  • 确保更新操作只锁定必要的行,而不是整个表。

3. 使用锁提示

  • 在 SQL 语句中使用锁提示来控制锁的行为。例如,使用 UPDLOCKROWLOCK 来减少锁的粒度。
  • 例如:
    SELECT * FROM TableName WITH (UPDLOCK) WHERE ...
    

4. 重试机制

  • 在捕获到死锁异常后,实现重试机制。死锁通常是暂时的,重试后事务可能会成功执行。
  • 例如:
    int retryCount = 3;
    while (retryCount > 0)
    {try{// 执行 SQL 命令cmd.ExecuteNonQuery();break;}catch (SqlException ex){if (ex.Number == 1205) // 1205 是死锁错误代码{retryCount--;if (retryCount == 0)throw; // 重试次数用尽,抛出异常Thread.Sleep(1000); // 等待一段时间后重试}else{throw; // 其他异常直接抛出}}
    }
    

5. 检查索引

  • 确保表上有适当的索引,以减少锁的竞争。缺少索引可能导致全表扫描,增加锁的冲突。

6. 分析死锁图

  • 使用 SQL Server 的死锁图(Deadlock Graph)来分析死锁的原因。你可以通过 SQL Server Profiler 或 Extended Events 来捕获死锁图,了解哪些资源和事务导致了死锁。

示例代码改进

以下是一个简单的重试机制示例,你可以在代码中添加:

int retryCount = 3;
while (retryCount > 0)
{try{using (SqlConnection connection = new SqlConnection(connectionString)){connection.Open();using (SqlCommand cmd = new SqlCommand()){cmd.Connection = connection;foreach (String str in List){sqlText = "";// 添加参数ArrayList paramsArray = listParams[i];foreach (Dictionary<string, object> paramsItem in paramsArray){foreach (var keyItem in paramsItem){if (string.IsNullOrEmpty($"{keyItem.Value}")){cmd.Parameters.AddWithValue(keyItem.Key, DBNull.Value);}else{cmd.Parameters.AddWithValue(keyItem.Key, $"{keyItem.Value}");}if (str.Contains("update")){sqlText += $"{keyItem.Key.Replace("@", "")}='{keyItem.Value}',";}else{sqlText += $"'{keyItem.Value}',";}}}allSql = $"{str}";// 在这里执行你的 SQL 命令cmd.CommandText = str;cmd.ExecuteNonQuery();cmd.Parameters.Clear();i++;}rows += 1;}}break; // 执行成功,退出循环}catch (SqlException ex){if (ex.Number == 1205) // 1205 是死锁错误代码{retryCount--;if (retryCount == 0)throw; // 重试次数用尽,抛出异常Thread.Sleep(1000); // 等待一段时间后重试}else{throw; // 其他异常直接抛出}}
}

总结

死锁是数据库系统中常见的问题,通常通过优化事务范围、SQL 语句、锁策略以及实现重试机制来解决。通过分析死锁图和调整代码逻辑,可以有效减少死锁的发生。

相关文章

【C#】事务(进程 ID 64)与另一个进程被死锁在锁资源上,并且已被选作死锁牺牲品。请重新运行该事务。不能在具有唯一索引“XXX_Index”的对象“dbo.Test”中插入重复键的行。

【C#】使用DeepSeek帮助评估数据库性能问题,C# 使用定时任务,每隔一分钟移除一次表,再重新创建表,和往新创建的表追加5万多条记录

【C#】合理使用DeepSeek相关AI应用为我们提供强有力的开发工具,在.net core 6.0框架下使用JsonNode动态解析json字符串,如何正确使用单问号和双问号做好空值处理

【C#】已经实体类和动态实体类的反射使用方法,两分钟回顾,码上就懂

【C#】使用vue3的axios发起get和post请求.net framework部署的API显示跨域

【C#】.net core 6.0 webapi 使用core版本的NPOI的Excel读取数据以及保存数据

【C#】pdf按页分割文件,以及分页合并,效果还不错,你值得拥有

【C#】未能加载文件或程序集“CefSharp.Core.Runtime.dll”或它的某一个依赖项。找不到指定的模块。

【C#】.net core 6.0 在program时间格式统一json格式化,并列举program默认写法和简化写法

【C#】.net core 6.0 ApiController,API控制器方法,API接口以实体类作为接收参数应该注意的点

【C#】 SortedDictionary,查找字典中是否存在给定的关键字

【C#】.net core 6.0 MVC返回JsonResult显示API接口返回值不可被JSON反序列化

【C#】.net core 6.0 使用第三方日志插件Log4net,配置文件详细说明

【C#】使用代码实现龙年春晚扑克牌魔术(守岁共此时),代码实现篇

【C#】使用代码实现龙年春晚扑克牌魔术(守岁共此时),流程描述篇

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode Hot 100 搜索二维矩阵

给你一个满足下述两条属性的 m x n 整数矩阵&#xff1a;每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。给你一个整数 target &#xff0c;如果 target 在矩阵中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。示例…

python毕设高分案例:基于机器学习的抑郁症数据分析与预测系统,flask框架,算法包括XGboost模型、梯度提升树模型等

1 绪论 1.1 课题研究背景和意义 1.1.1 研究背景 在医疗行业不断发展的当下&#xff0c;数据量呈现出爆炸式增长&#xff0c;医学数据的复杂性和多样性也达到了前所未有的程度。电子病历系统记录了患者丰富的诊疗信息&#xff0c;医学影像技术如 CT、MRI 等生成海量的图像数据…

STM32与ADS1256多通道数据采样原理及控制程序

好的,使用 STM32 与 ADS1256 通信读取多通道电压是精密数据采集的常见方案。ADS1256 是一款高精度、24 位、8 通道(或差分 4 通道)的 ΔΣ ADC,非常适合需要高分辨率的应用(如传感器信号、医疗仪器等)。 以下是对整个过程的详细分析及基于 STM32 HAL 库的程序示例: 核…

Spring Boot 3.5.x 使用 SpringDoc 2 / Swagger3

这篇文章资料来自于网络&#xff0c;对部分知识整理&#xff0c;这里只是记录一下&#xff0c;仅供参考 为什么要用 Swagger Swagger 的核心思想是通过定义和描述 API 的规范、结构和交互方式&#xff0c;以提高 API 的可读性、可靠性和易用性&#xff0c;同时降低 API 开发的难…

@RefreshScope 核心原理深度解析:Spring Boot 的动态魔法

让我们通过全新的原理图解和代码级分析&#xff0c;揭开RefreshScope实现配置热更新的神秘面纱&#xff01;一、工作原理全景图&#xff08;优化版&#xff09; #mermaid-svg-50lhLlOFeSRIWnLn {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px…

万字详解——OSI七层模型:网络通信的完整架构解析

OSI七层模型&#xff1a;网络通信的完整架构解析OSI&#xff08;Open Systems Interconnection&#xff09;七层模型是计算机网络领域最基础、最权威的参考框架。它由国际标准化组织&#xff08;ISO&#xff09;于1984年提出&#xff0c;旨在为不同厂商、不同技术的网络设备和系…

一个人开发一个App(OpenApi)

为了少写代码&#xff0c;统一前后端的网络层&#xff0c;我使用了OpenApi设计restful接口。然后用openapi-generator来生成flutter的代码。生成go代码用的是oapi-codegen,它对go更友好一些。 我们直接在api.yml中设计接口&#xff0c;所有的返回值与请求者都提取到components里…

光伏气象监测系统:助力光伏发电的智慧大脑

光伏气象监测系统&#xff1a;助力光伏发电的智慧大脑 柏峰【BF-GFQX】在全球积极推动能源转型、大力倡导 “双碳” 目标的当下&#xff0c;光伏发电凭借其清洁、可再生的显著优势&#xff0c;宛如一颗冉冉升起的新星&#xff0c;在能源领域迅速崭露头角&#xff0c;得以广泛推…

SpringCloud01——项目演变、微服务远程调用三种方式、springcloud介绍、nacos注册中心

目录 一、项目架构演变过程 1、单体应用架构 2、垂直应用架构 3、分布式服务架构 4、流动计算架构&#xff08;SOA架构&#xff09; 5、微服务架构 二、如何实现微服务远程调用 1、HttpClient工具类&#xff08;springboot中&#xff09; 形式1&#xff1a;调用第三方…

Oracle 和 MySQL 中的日期类型比较

Oracle 和 MySQL 都提供了多种日期和时间数据类型&#xff0c;但它们在实现和功能上有一些差异。以下是两者的主要日期类型对比&#xff1a;Oracle 日期类型DATE存储日期和时间&#xff08;精确到秒&#xff09;格式&#xff1a;YYYY-MM-DD HH24:MI:SS示例&#xff1a;TO_DATE(…

基于 Redis 实现共享 Session 登录的多种方法与实践

全文目录&#xff1a;开篇语**前言****1. 什么是共享 Session 登录&#xff1f;****2. 基于 Redis 实现共享 Session 的基本方法****2.1 通过 Redis 存储 Session 数据****2.1.1 基本流程****2.1.2 示例代码&#xff08;Java Spring Boot Redis&#xff09;****3. 使用 Redis…

spring cloud + easyRules 零基础搭建智能规则引擎

你是否曾想过在项目中嵌入一套轻量级且高度可扩展的规则引擎&#xff0c;轻松实现动态化的业务决策&#xff1f;在金融、电商、政务等领域&#xff0c;风险控制是业务安全的核心。传统硬编码方式很难应对复杂多变的风控需求&#xff0c;而规则引擎允许我们将这些规则独立出来&a…

AI应用:电路板设计

Diode Computers 公司 Diode Computers是一家专注于利用AI技术进行定制电路板设计和制造的公司&#xff0c;提供从概念到量产的全流程服务。其核心优势在于将电路板设计转化为AI可理解的代码形式&#xff0c;大幅提升设计效率并降低传统EDA工具的使用门槛 0。 核心服务 设计与制…

RocketMQ学习系列之——客户端消息确认机制

一、客户端使用MQ基本代码示例1、添加maven依赖<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>5.3.0</version> </dependency>2、生产者代码示例public class Produc…

[leetcode] 组合总和

39. 组合总和 - 力扣&#xff08;LeetCode&#xff09; i class Solution {int aim;vector<vector<int>> ret;vector<int> path; public:vector<vector<int>> combinationSum(vector<int>& nums, int target) {aim target;dfs(nums…

新能源行业B端极简设计:碳中和目标下的交互轻量化实践

新能源行业B端极简设计&#xff1a;碳中和目标下的交互轻量化实践内容摘要在新能源行业&#xff0c;碳中和目标正推动着企业追求更高的运营效率和更低的资源消耗。然而&#xff0c;传统的B端交互设计往往复杂繁琐&#xff0c;不仅增加了用户的操作成本&#xff0c;还可能导致资…

减速机:自动化生产线的“精密传动心脏”

减速机作为自动化生产线的核心传动部件&#xff0c;通过调节转速与扭矩实现设备精准控制&#xff0c;其在自动化生产线中发挥着关键作用。以下是其具体应用方式&#xff1a;输送线驱动在自动化生产线中&#xff0c;输送线用于运输物料、半成品或成品&#xff0c;通过减速机可以…

从0到1学PHP(五):PHP 数组:高效存储与处理数据

目录一、数组的定义与分类1.1 索引数组1.2 关联数组1.3 多维数组二、数组的基本操作2.1 数组元素的添加、删除、修改和访问2.2 数组指针的操作三、数组处理函数3.1 数组排序函数3.2 数组统计函数3.3 数组过滤与转换函数一、数组的定义与分类 在 PHP 中&#xff0c;数组是一种非…

vscode 字体的跟换

打开vscode 左下角输入电脑中已经有的字体&#xff1a;有想要用的可以自己进行安装刷新这样就可改变了

墨者:SQL过滤字符后手工注入漏洞测试(第3题)

1. 墨者学院&#xff1a;SQL过滤字符后手工注入漏洞测试(第3题)&#x1f680; 因为练习过太多的sql注入&#xff0c;废话不多介绍&#xff0c;我会通过围绕手动注入和工具爆破的方式达到靶场目标&#xff0c;开练&#xff01;&#xff01;&#xff01; 2. 手工注入方式&#x1…