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

设计无SQL死锁的编码模式-AchievingSQLDeadlock-FreeDesign

在运行于MSSQLServer2005的.NET2.0Web应用中,我偶尔会遇到令人头疼的SQL死锁问题。过去,我们主要通过调整查询来解决这些问题,但这既耗时又不可靠。我希望能找到一种确定性的查询模式,确保从设计上彻底避免SQL死锁。

在我运行于MS SQL Server 2005的.NET 2.0 Web应用中,偶尔会遇到令人头疼的SQL死锁问题。过去,我们主要通过调整查询来解决这些问题,但这既耗时又不可靠。我希望找到一种确定性的查询模式,确保从设计上彻底避免SQL死锁。

例如,在C#多线程编程中,一个简单的设计规则是按字典顺序获取锁,这可以确保不会发生死锁。那么,SQL中是否有类似的编码模式可以保证无死锁呢?

解决方案

#1

编写防死锁代码非常困难。即使以相同的顺序访问表,仍然可能会遇到死锁。我在博客中详细讨论了一些方法,可以帮助避免和解决死锁情况。如果您希望确保两个语句/事务不会死锁,可以使用sp_lock系统存储过程观察每个语句使用的锁,但必须非常迅速或使用带有HOLDLOCK提示的开放事务。

#2

在一般情况下,零死锁是一个非常昂贵的问题,因为您必须知道每个运行事务将读取和修改的所有表/对象(包括SELECT语句)。常见的解决方法是有序严格的两阶段锁(2PL),但即使是2PL也不能保证无死锁。很少有DBMS实现严格的2PL,因为这会导致大量性能损失。您可以考虑调整SQL Server中的隔离级别,例如使用快照隔离或读未提交隔离级别。

#3

没有通用的解决方案可以完全避免死锁。您可以将并发控制移到应用程序层面,但这可能非常复杂,尤其是需要与其他程序协调时。一些减少死锁机会的一般方法包括:基本查询优化、热点回避设计、尽量缩短事务时间、设置合理的查询超时等。

#4

在某些限制条件下,以下读/写模式可以防止死锁:

  • 约束:
    • 一个表
    • 使用索引或主键进行读/写,避免表锁
    • 可以使用单个SQL WHERE子句读取一批记录
    • 使用SQL Server术语
  • 写周期:
    • 所有写操作在一个“读提交”事务中
    • 事务中的第一个更新是针对每个更新组中特定的、始终存在的记录
    • 随后可以以任何顺序写入多个记录
  • 读周期:
    • 默认读提交事务级别
    • 无事务
    • 将记录作为一个选择语句读取
  • 好处:
    • 二级写周期在第一个记录的写入过程中被阻塞,直到第一个写事务完全完成
    • 在写提交之间,读取被阻塞/排队/自动执行
    • 无需使用“可序列化”即可实现事务级别的一致性

#5

始终以相同的顺序访问表是避免死锁的好方法。此外,尽可能缩短事务时间。另一个技巧是尽可能将两个SQL语句组合成一个。单个语句总是事务性的。例如,使用“UPDATE ... SELECT”或“INSERT ... SELECT”,使用“@@ERROR”和“@@ROWCOUNT”代替“SELECT COUNT”或“IF (EXISTS ...)”。最后,确保调用代码可以通过重新发布查询的可配置次数来处理死锁。

#6

除了一致的锁获取顺序,还可以显式使用锁和隔离提示,以减少在读取过程中无意地获取锁(如共享意图)所浪费的时间/资源。

#7

对于SQL Server,许多锁定问题可以通过正确的覆盖索引来消除。这是因为它可以大大减少对表的聚集索引的书签查找,从而减少争用和锁定。

#8

如果您对应用程序有足够的设计控制,可以将更新/插入限制在特定的存储过程中,并从应用程序使用的数据库角色中删除更新/插入权限(仅显式允许通过这些存储过程进行更新)。将数据库连接隔离到应用程序中的特定类(每个连接必须来自这个类),并指定“仅查询”连接将隔离级别设置为“脏读”。

#9

没有绝对保证的技术可以避免死锁。如果您预先锁定流程中可能需要的所有资源,即使最终不需要这些资源,也可能导致第二个进程等待获取所需的第一个锁,从而影响可用性。解决SQL死锁问题的最佳方法是查看分析器中的工作负载并理解其行为。

#10

虽然不是直接回答您的问题,但“用餐哲学家问题”是一个经典的死锁问题思想实验。阅读相关内容可能会帮助您找到解决特定问题的方法。


推荐阅读
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • QUIC协议:快速UDP互联网连接
    QUIC(Quick UDP Internet Connections)是谷歌开发的一种旨在提高网络性能和安全性的传输层协议。它基于UDP,并结合了TLS级别的安全性,提供了更高效、更可靠的互联网通信方式。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • 本文详细介绍了如何在Linux系统上安装和配置Smokeping,以实现对网络链路质量的实时监控。通过详细的步骤和必要的依赖包安装,确保用户能够顺利完成部署并优化其网络性能监控。 ... [详细]
  • 1.如何在运行状态查看源代码?查看函数的源代码,我们通常会使用IDE来完成。比如在PyCharm中,你可以Ctrl+鼠标点击进入函数的源代码。那如果没有IDE呢?当我们想使用一个函 ... [详细]
  • CentOS7源码编译安装MySQL5.6
    2019独角兽企业重金招聘Python工程师标准一、先在cmake官网下个最新的cmake源码包cmake官网:https:www.cmake.org如此时最新 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 本文探讨了如何优化和正确配置Kafka Streams应用程序以确保准确的状态存储查询。通过调整配置参数和代码逻辑,可以有效解决数据不一致的问题。 ... [详细]
  • 尽管使用TensorFlow和PyTorch等成熟框架可以显著降低实现递归神经网络(RNN)的门槛,但对于初学者来说,理解其底层原理至关重要。本文将引导您使用NumPy从头构建一个用于自然语言处理(NLP)的RNN模型。 ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 本文介绍如何使用Objective-C结合dispatch库进行并发编程,以提高素数计数任务的效率。通过对比纯C代码与引入并发机制后的代码,展示dispatch库的强大功能。 ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
author-avatar
悸末丶C彼岸花开
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有