返回顶部
首页 > 资讯 > 数据库 >如何理解数据库中的锁
  • 558
分享到

如何理解数据库中的锁

2024-04-02 19:04:59 558人浏览 泡泡鱼
摘要

如何理解数据库中的锁,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。背景数据库中有一张叫后宫佳丽的表,每天都有几百万新的小姐姐插

如何理解数据库中的,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

背景

数据库中有一张叫后宫佳丽的表,每天都有几百万新的小姐姐插到表中,光阴荏苒,夜以继日,日久生情,时间长了,表中就有了几十亿的小姐姐数据,看到几十亿的小姐姐,每到晚上,我可愁死了,这么多小姐姐,我翻张牌呢?

办法当然是精兵简政,删除那些age>18的,给年轻的小姐姐们留位置...

于是我在数据库中添加了一个定时执行的小程序,每到周日,就自动运行如下的脚本

delete from `后宫佳丽` where age>18

一开始还自我感觉良好,后面我就发现不对了,每到周日,这个脚本一执行就是一整天,运行的时间有点长是小事,重点是这大好周日,我再想读这张表的数据,怎么也读不出来了,怎是一句空虚了得,我好难啊!

如何理解数据库中的锁

为什么

编不下去了,真实背景是公司中遇到的一张有海量数据表,每次一旦执行历史数据的清理,我们的程序就因为读不到这张表的数据,疯狂地报错,后面一查了解到,原来是因为定时删除的语句设计不合理,导致数据库中数据由行锁(Row lock)升级为表锁(Table lock)了?.

解决这个问题的过程中把数据库锁相关的学习了一下,这里把学习成果,分享给大家,希望对大家有所帮助.

我将讨论SQL Server锁机制以及如何使用sql Server标准动态管理视图监视SQL Server 中的锁,相信其他数据的锁也大同小异,具有一定参考意义.

铺垫知识

在我开始解释SQL Server锁定体系结构之前,让我们花点时间来描述ACID(原子性,一致性,隔离性和持久性)是什么。ACID是指数据库管理系统(DBMS)在写入或更新资料的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性:原子性(atomicity,或称不可分割性)、一致性(consistency)、隔离性(isolation,又称独立性)、持久性(durability)。

ACID#

原子性(Atomicity)#

一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。

一致性(Consistency)#

在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。

隔离性(Isolation)#

数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括未提交读(Read uncommitted)、提交读(read committed)、可重复读(repeatable read)和串行化(Serializable)。

持久性(Durability)#

事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

来源:维基百科 https://zh.wikipedia.org/wiki/ACID

事务 (Transaction:)#

事务是进程中最小的堆栈,不能分成更小的部分。此外,某些事务处理组可以按顺序执行,但正如我们在原子性原则中所解释的那样,即使其中一个事务失败,所有事务块也将失败。

锁定 (Lock)#

锁定是一种确保数据一致性的机制。SQL Server在事务启动时锁定对象。事务完成后,SQL Server将释放锁定的对象。可以根据SQL Server进程类型和隔离级别更改此锁定模式。这些锁定模式是:

锁定层次结构#

SQL Server具有锁定层次结构,用于获取此层次结构中的锁定对象。数据库位于层次结构的顶部,行位于底部。下图说明了SQL Server的锁层次结构。

如何理解数据库中的锁

共享(S)锁 (Shared (S) Locks)#

当需要读取对象时,会发生此锁定类型。这种锁定类型不会造成太大问题。

独占(X)锁定 (Exclusive (X) Locks)#

发生此锁定类型时,会发生以防止其他事务修改或访问锁定对象。

更新(U)锁 (Update (U) Locks)#

此锁类型与独占锁类似,但它有一些差异。我们可以将更新操作划分为不同的阶段:读取阶段和写入阶段。在读取阶段,SQL Server不希望其他事务有权访问此对象以进行更改,因此,SQL Server使用更新锁。

意图锁定 (Intent Locks)#

当SQL Server想要在锁定层次结构中较低的某些资源上获取共享(S)锁定或独占(X)锁定时,会发生意图锁定。实际上,当SQL Server获取页面或行上的锁时,表中需要设置意图锁。

SQL Server locking

了解了这些背景知识后,我们尝试再SQL Server找到这些锁。SQL Server提供了许多动态管理视图来访问指标。要识别SQL Server锁,我们可以使用sys.dm_tran_locks视图。在此视图中,我们可以找到有关当前活动锁管理的大量信息。

在第一个示例中,我们将创建一个不包含任何索引的演示表,并尝试更新此演示表。

CREATE TABLE TestBlock  (Id INT ,  Nm VARCHAR(100))  INSERT INTO TestBlock  values(1,'codingSight')  In this step, we will create an open transaction and analyze the locked resources.  BEGIN TRAN  UPDATE TestBlock SET   Nm='NewValue_CodingSight' where Id=1  select @@SPID

如何理解数据库中的锁

再获取到了SPID后,我们来看看sys.dm_tran_lock视图里有什么。

select * from sys.dm_tran_locks  WHERE request_session_id=74

如何理解数据库中的锁

此视图返回有关活动锁资源的大量信息,但是是一些我们难以理解的一些数据。因此,我们必须将sys.dm_tran_locks join 一些其他表。

SELECT dm_tran_locks.request_session_id,         dm_tran_locks.resource_database_id,         DB_NAME(dm_tran_locks.resource_database_id) AS dbname,         CASE             WHEN resource_type = 'OBJECT'                 THEN OBJECT_NAME(dm_tran_locks.resource_associated_entity_id)             ELSE OBJECT_NAME(partitions.OBJECT_ID)         END AS ObjectName,         partitions.index_id,         indexes.name AS index_name,         dm_tran_locks.resource_type,         dm_tran_locks.resource_description,         dm_tran_locks.resource_associated_entity_id,         dm_tran_locks.request_mode,         dm_tran_locks.request_status  FROM sys.dm_tran_locks  LEFT JOIN sys.partitions ON partitions.hobt_id = dm_tran_locks.resource_associated_entity_id  LEFT JOIN sys.indexes ON indexes.OBJECT_ID = partitions.OBJECT_ID AND indexes.index_id = partitions.index_id  WHERE resource_associated_entity_id > 0    AND resource_database_id = DB_ID()   and request_session_id=74  ORDER BY request_session_id, resource_associated_entity_id

如何理解数据库中的锁

在上图中,您可以看到锁定的资源。SQL Server获取该行中的独占锁。(RID:用于锁定堆中单个行的行标识符)同时,SQL Server获取页中的独占锁和TestBlock表意向锁。这意味着在SQL Server释放锁之前,任何其他进程都无法读取此资源,这是SQL Server中的基本锁定机制。

现在,我们将在测试表上填充一些合成数据。

TRUNCATE TABLE    TestBlock  DECLARE @K AS INT=0  WHILE @K <8000  BEGIN  INSERT TestBlock VALUES(@K, CAST(@K AS varchar(10)) + ' Value' )  SET @K=@K+1   END  --After completing this step, we will run two queries and check the sys.dm_tran_locks view.  BEGIN TRAN   UPDATE TestBlock  set Nm ='New_Value' where Id<5000

如何理解数据库中的锁

在上面的查询中,SQL Server获取每一行的独占锁。现在,我们将运行另一个查询。

BEGIN TRAN   UPDATE TestBlock  set Nm ='New_Value' where Id<7000

如何理解数据库中的锁

在上面的查询中,SQL Server在表上创建了独占锁,因为SQL Server尝试为这些将要更新的行获取大量RID锁,这种情况会导致数据库引擎中的大量资源消耗,因此,SQL Server会自动将此独占锁定移动到锁定层次结构中的上级对象(Table)。我们将此机制定义为Lock EScalation, 这就是我开篇所说的锁升级,它由行锁升级成了表锁。

根据官方文档的描述存在以下任一条件,则会触发锁定升级:

  •  单个Transact-SQL语句在单个非分区表或索引上获取至少5,000个锁。

  •  单个Transact-SQL语句在分区表的单个分区上获取至少5,000个锁,并且ALTER TABLE SET LOCK_ESCALATION选项设置为AUTO。

  •  数据库引擎实例中的锁数超过了内存或配置阈值。

Https://docs.microsoft.com/en-us/previous-versions/sql/sql-server-2008-r2/ms184286(v=sql.105)

如何避免锁升级

防止锁升级的最简单,最安全的方法是保持事务的简短,并减少昂贵查询的锁占用空间,以便不超过锁升级阈值,有几种方法可以实现这一目标.

将大批量操作分解为几个较小的操作#

例如,在我开篇所说的在几十亿条数据中删除小姐姐的数据:

delete from `后宫佳丽` where age>18

我们可以不要这么心急,一次只删除500个,可以显着减少每个事务累积的锁定数量并防止锁定升级。例如:

SET ROWCOUNT 500  delete_more:       delete from `后宫佳丽` where age>18  IF @@ROWCOUNT > 0 GoTO delete_more  SET ROWCOUNT 0

创建索引使查询尽可能高效来减少查询的锁定占用空间#

如果没有索引会造成表扫描可能会增加锁定升级的可能性, 更可怕的是,它增加了死锁的可能性,并且通常会对并发性和性能产生负面影响。

根据查询条件创建合适的索引,最大化提升索引查找的效率,此优化的一个目标是使索引查找返回尽可能少的行,以最小化查询的的成本。

如果其他SPID当前持有不兼容的表锁,则不会发生锁升级#

锁定升级始总是升级成表锁,而不会升级到页面锁定。如果另一个SPID持有与升级的表锁冲突的IX(intent exclusive)锁定,则它会获取更细粒度的级别(行,key或页面)锁定,定期进行额外的升级尝试。表级别的IX(intent exclusive)锁定不会锁定任何行或页面,但它仍然与升级的S(共享)或X(独占)TAB锁定不兼容。

如下所示,如果有个操作始终在不到一小时内完成,您可以创建包含以下代码的sql,并安排在操作的前执行

BEGIN TRAN  SELECT * FROM mytable (UPDLOCK, HOLDLOCK) WHERE 1=0  WaiTFOR DELAY '1:00:00'  COMMIT TRAN

此查询在mytable上获取并保持IX锁定一小时,这可防止在此期间对表进行锁定升级。

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程网数据库频道,感谢您对编程网的支持。

您可能感兴趣的文档:

--结束END--

本文标题: 如何理解数据库中的锁

本文链接: https://lsjlt.com/news/68277.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何理解数据库中的锁
    如何理解数据库中的锁,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。背景数据库中有一张叫后宫佳丽的表,每天都有几百万新的小姐姐插...
    99+
    2024-04-02
  • 数据库死锁:理解并解决数据库中的“纠纷”
    1. 数据库死锁的概念 数据库死锁是指两个或多个数据库事务在执行过程中,互相等待对方的资源释放,导致双方都无法继续执行的情形。死锁通常发生在多个事务同时请求相同资源时,例如: 事务 A 请求资源 X,但资源 X 被事务 B 持有。 事...
    99+
    2024-02-05
    数据库死锁 事务 资源 死锁检测 死锁预防 死锁避免 死锁恢复
  • 如何解锁Oracle数据库中账号
    在创建数据库时,其中SYS登录Oracle数据库在SQL*Plus工具通过如下SQL解锁。1、通过数据字典dba_users,查看Oracle账户的锁定状态,如下:(v其中,OPEN表示账户为解锁状态;EX...
    99+
    2024-04-02
  • oracle数据库锁定后如何解锁
    要解锁Oracle数据库中的锁定对象,可以执行以下步骤:1. 确定锁定对象和锁定级别:首先需要确定哪个对象被锁定以及锁定级别,可以使...
    99+
    2023-09-15
    oracle数据库
  • 数据库死锁:数据库中的“交通堵塞”——如何化解?
    一、数据库死锁简介 数据库死锁是指两个或多个事务在等待对方释放锁时互相等待,从而导致系统无法继续执行。死锁通常是由于多个事务同时访问同一资源引起的。例如,两个事务同时更新同一行数据,就会发生死锁。 二、数据库死锁的危害 数据库死锁可能会...
    99+
    2024-02-05
    数据库死锁 事务 隔离级别 回滚
  • 数据库中的锁
    1 前言数据库大并发操作要考虑死锁和锁的性能问题。看到网上大多语焉不详(尤其更新锁),所以这里做个简明解释,为下面描述方便,这里用T1代表一个数据库执行请求,T2代表另一个请求,也可以理解为T1为...
    99+
    2024-04-02
  • postgresql数据库中出现锁表如何解决
    一、出现场景 锁表通常发生在 DML( insert 、update 、delete )语句中,例如:程序 A 对 A 表的 a 数据 进行修改,修改过程中产生错误,没有 commit 也没有 rollback ,这个时候程序 B...
    99+
    2023-08-30
    数据库 postgresql mysql oracle
  • 数据库死锁的奥秘:理解和解决数据库中的“尴尬时刻”
    什么是数据库死锁? 数据库死锁是指两个或多个事务同时请求彼此锁定的资源,从而导致彼此都无法继续执行的情况。 例如,考虑以下两个事务: 事务 A 希望更新表 A 中的行 X。 事务 B 希望更新表 B 中的行 Y。 如果事务 A 先于...
    99+
    2024-02-05
    数据库死锁 事务 性能
  • 数据库锁表和解锁
    问题描述 在开发或生产环境中,我们经常会遇到数据库锁表的情况,一旦发生锁表,对业务将会产生很大的影响,本篇主要介绍如何判断数据库锁表和锁表后的处理。 mysql锁表处理 一、导致锁表的原因 锁表发生在insert update 、...
    99+
    2023-08-20
    数据库 mysql java sql oracle
  • Oracle数据库表被锁如何查询和解锁详解
    目录1、锁表原因2、锁表查询的代码有以下的形式3、查看哪个表被锁4、查看是哪个session引起的5、杀掉对应进程6、如何避免锁表总结1、锁表原因 可能是修改表中的数据,忘了提交事务会造成锁表。 oracle数据库操作中...
    99+
    2023-03-08
    oracle表锁住了怎么办 oracle数据表被锁怎么办 oracle数据库被锁原因查询
  • Oracle数据库表被锁定如何处理?
    Oracle数据库表被锁定是数据库管理中常见的问题,在进行数据操作时可能会遇到各种锁定情况,如行级锁、表级锁等。本文将详细介绍Oracle数据库表被锁定的处理方法,并提供相关的代码示例...
    99+
    2024-03-11
    oracle 解锁 处理 sql语句
  • 如何在 Golang 中使用数据库锁?
    在 golang 中,可以使用 sync.mutex 或 database/sql 包中的 tx 实现数据库锁。sync.mutex 适用于非阻塞操作,而 tx 允许在事务中执行一系列操...
    99+
    2024-05-14
    golang 数据库锁
  • 数据库死锁:避免和解决数据库中的“数据僵持”
    1. 数据库死锁概述 数据库死锁是指两个或多个事物在等待对方释放锁并在等待过程中都无法进行进一步执行时出现的情况。死锁经常发生在多个事务都试图通过锁机制来控制对共享资源的访问的情况下。在死锁发生时,所有涉及的事务都会被阻塞,直到其中一个...
    99+
    2024-02-05
    数据库死锁 死锁原因 避免死锁 解决死锁 演示代码
  • 如何锁定MySQL数据库表
    本篇文章给大家分享的是有关如何锁定MySQL数据库表,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。  如何锁定MySQL数据库表  锁定表的方...
    99+
    2024-04-02
  • MySQL数据库锁如何实现
    这篇“MySQL数据库锁如何实现”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“MySQL数...
    99+
    2023-03-23
    mysql
  • 当数据“卡住”:数据库死锁的原理与解析
    一、数据库死锁的原理 数据库死锁是指两个或多个事务在竞争资源时,导致彼此无法继续执行的情况。死锁的发生通常有以下几种原因: 互斥访问资源: 当多个事务同时请求同一资源时,如果该资源无法同时满足多个事务的需求,就会产生死锁。例如,两个事...
    99+
    2024-02-05
    数据库死锁 死锁类型 死锁处理 死锁预防 死锁检测 死锁恢复
  • MySQL数据库锁机制原理解析
    在并发访问情况下,很有可能出现不可重复读等等读现象。为了更好的应对高并发,封锁、时间戳、乐观并发控制(乐观锁)、悲观并发控制(悲观锁)都是并发控制采用的主要技术方式。 锁分类 ①、按操作划分:DML锁,DDL锁 ...
    99+
    2022-05-21
    MySQL 数据库 锁机制
  • 数据库死锁是如何产生的
    这篇文章主要介绍了数据库死锁是如何产生的,具有一定借鉴价值,需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获。下面让小编带着大家一起了解一下。死锁(Deadlock)所谓死锁:是指两个或两个以上的进程...
    99+
    2024-04-02
  • 数据库的乐观锁如何实现
    本文小编为大家详细介绍“数据库的乐观锁如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“数据库的乐观锁如何实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。线程锁分类有很多...
    99+
    2024-04-02
  • 如何理解数据库的B+树
    本篇内容介绍了“如何理解数据库的B+树”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1 数据从磁盘读写与内...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作