当前位置: 首页 > article >正文

Oracle 深入理解Lock和Latch ,解析访问数据块全流程

Oracle 锁机制介绍

根据保护对象的不同,单实例Oracle数据库锁可以分为以下几大类: DML lock(data locks,数据锁):用于保护数据的完整性; DDL lock(dictionary locks,字典锁):用于保护数据库对象的结构(例如 表、视图、索引的结构定义); internal locks,latches,mutex,pin:保护内部数据库结构;Oracle DML锁共有两个层次,即行级锁(TX)和表级锁(TM)。

一 .Lock 锁

1.锁介绍

我们在谈到性能优化的时候,通常是讲系统缓慢的时候需要性能优化,系统缓慢通常是由什么原因导致的呢?大概上讲分为两种

  1. 系统的资源耗尽了(cpu耗尽了,IP,吞吐量上不去)性能枯竭,性能达到了极限。
  2. 锁定,阻塞,发现系统性能很高,但应用程序性能就是上不去,这种情况通常来讲是阻塞。

模拟锁的情况:

窗口一:建一张表,插入一条数据,id上有主键

窗口二:再往这张表id列插入一条同样的数据

由于primary key本质上是 unique key + not null ,由于第二个事务不知道第一个事务是提交还是回滚,如果提交则事务二插入失败,如果回滚则插入成功,此时会造成锁阻塞。

窗口一:

窗口二:

2.Oracle中锁的大体分类

Enqueues : 队列类型的锁,通常和业务相关的锁。

Latches: 系统资源方面的锁,比如内存结构,SQL解析等

锁的所有类型可以根据视图v$lock_type 查看

环境oracle 19c 共291种 锁。

 .........

3.锁的原则

  1. 只有被修改时,行才会被锁定。
  2. 当一条语句修改了一条记录,只有这条记录上被锁定,在Oracle数据库中不存在锁升级。
  3. 当某行被修改时,它将阻塞别人对它的修改。
  4. 当一个事务修改一行时,将在这个行上加上行锁(TX),用于阻止其它事务对相同行的修改。
  5. 读永远不会阻止写。
  6. 读不会阻塞写,但有唯一的一个例外,就是select …for update。
  7. 写永远不会阻塞读。
  8. 当一行被修改后,Oracle通过回滚段提供给数据的一致性读。

这里其实听过其它很多人说过Oracle锁升级的概念,根据一下Oracle资料调查Oracle不存在锁升级,但确实存在锁转换。

数据库在必要时执行锁转换。在锁转换中,数据库自动将较低限制的表锁转换为较 高限制的其它锁定。(锁转换不同于锁升级,锁升级发生在当某个粒度级别持有许多锁(例如行),数据库将其提高到更高粒度级别(例如表)Oracle数据库永远不会升级锁。

Oracle的锁是block里面实现的,(SQLSERVER、DB2是内存里面实现的。内存实 现有资源消耗问题,当内存不足会引发锁升级)但是Oracle不会发生锁升级。

事务拥有在此事务内被插入(insert)、更新(update)、删除(delete)的数 据行的排它行级锁(exclusive row lock)。对于数据行来说,排它行级锁已经是 限制程度最高的锁,因此无需再进行锁转换(lock conversion)。

 4.TM锁和TX锁

  1. TM表锁,发生在insert,update,delete以及select for update操作时,目的是保证操 作能够正常进行,并且阻止其它人对表执行DDL操作。
  2. TX锁事务锁(行锁)对于正在修改的数据,阻止其它会话进行修改。

根据官方文档归纳总结: v$lock视图列出当前系统持有的或正在申请的所有锁的情况,其主要字段说明如下:

v$locked_object视图列出当前系统中哪些对象正被锁定,其主要字段说明如下:

inert 锁过程验证:

窗口一:

窗口二:

 查看锁结构:

在整个过程中

  1. 首先会话58 对表T 加TM(表锁 )和TX(行锁),TM锁的BLOCK = 1 代表这个会话在阻塞其它会话
  2. 第二个会话273 也对T表加了一个TM(表锁),又加了一个TX(行锁),这个行锁request = 4,代表它正在被阻塞
  3. 中间那把锁(会话273的行锁)正在请求锁并且被会话58的行锁阻塞。会话58持有的行锁(LMODE = 6)正在阻塞会话273对相同行的访问,导致会话273的请求(REQUEST = 4)被阻塞。

update锁过程验证:

窗口一:

窗口二:

 查看锁过程:

整个过程

会话53 对表T加TM和TX锁,TX锁阻塞了其它会话,会话273对表T 加TM和TX锁,TX锁request=6 被阻塞。

delete 锁过程验证:

窗口一:

窗口二:

查看锁过程:

 会话58对表T加表锁和行锁,会话273对表T加表锁和行锁,58的行锁阻塞了273的行锁。

从v$session_wait 查看阻塞详情(从会话层面查看锁阻塞):

 所以TX锁又叫队列锁(enq锁)

TM锁的几种模式:

ORACLE里锁有以下几种模式:
0:none
1:null 空
2:Row-S 行共享(RS):共享表锁,sub share
3:Row-X 行独占(RX):用于行的修改,sub exclusive
4:Share 共享锁(S):阻止其他DML操作,share
5:S/Row-X 共享行独占(SRX):阻止其他事务操作,share/sub exclusive
6:exclusive 独占(X):独立访问使用,exclusive

数字越大锁级别越高, 影响的操作越多。

1级锁有:Select,有时会在v$locked_object出现。
2级锁有:Select for update,Lock For Update,Lock Row Share
select for update当对话使用for update子串打开一个游标时,所有返回集中的数据行都将处于行级(Row-X)独占式锁定,其他对象只能查询这些数据行,不能进行update、delete或select for update操作。
3级锁有:Insert, Update, Delete, Lock Row Exclusive
没有commit之前插入同样的一条记录会没有反应, 因为后一个3的锁会一直等待上一个3的锁, 我们必须释放掉上一个才能继续工作。
4级锁有:Create Index, Lock Share
locked_mode为2,3,4不影响DML(insert,delete,update,select)操作, 但DDL(alter,drop等)操作会提示ora-00054错误。
00054, 00000, "resource busy and acquire with NOWAIT specified"
5级锁有:Lock Share Row Exclusive
具体来讲有主外键约束时update / delete ... ; 可能会产生4,5的锁。
6级锁有:Alter table, Drop table, Drop Index, Truncate table, Lock Exclusive

 TM锁几种模式的互斥关系:

模式锁定的SQL排斥的模式允许的DML
2lock table t in row share mode6select, insert, update, delete, for update
3lock table t in row exclusive mode4,5,6select, insert, update, delete, for update
4lock table t in share mode3,5,6select
5lock table t in share row exclusive mode3,4,5,6select
6lock table t in exclusive mode2,3,4,5,6select

5..RI锁 - 基于 引用关系的锁

当对具有主外键关系的表做DML操作时,锁定不单单发生在操作表上,相应的引用表上也可能加上相应的锁定

示例:

 insert 操作在往主表注入一条数据的时候会在主表和从表上同时上TM锁,对主表上TX锁

 

 

update 操作 只会在主表上加TM和TX锁

6.死锁

两个会话互相持有对方资源导致死锁 (Oracle 会自动检测死锁)

会话一:

会话二:

如上,Oracle自动检测到了死锁,释放了会话一。 

二 .Latch 锁(闩锁)

用中国话理解闩,就是古代插在门后面那个上锁的。(意味着获取一个资源之后,把它插住,谁也用不了,用完之后再把它打开)

Latch和Lock的区别:

Lock 可以想象成食堂排队打饭,是有序的。

Latch可以想象成微信群里抢红包,抢红包不是一个一个排队的抢,是无序的。而就因为Latch的无序性,才需要Latch锁

LatchLock
队列性无序有序
时长很短可能很长
层面数据库资源层业务应用层
目的保护资源的完整性保证业务操作的完整性

Latch的目的

  1. 保证资源的串行访问: -保护SGA的资源访问 -保护内存的分配

  2. 保证执行的串行化: -保护关键资源的串行执行 -防止内存结构损坏

Latch在哪里 ->SGA

sharedpool  -sql解析,sql重用....... buffercache -数据访问,数据写入磁盘,数据读入内存,修改数据块,数据段扩展

oracle19c 共993个Latch

Latch的的获取:

wait方式--如果无法获取请求的latch ,则:

-spin

当一个会话无法获得需要的latch时,会继续使用CPU( CPU空转),达到一个间隔后, 再次尝试申请latch ,直到达到最大的重试次数。

-sleep

当一个会话无法获得需要的latch时,会等待一段时间(sleep) ,达到 Y间隔后,再次 尝试申清latch,如此反复,直到达到最大的重试次数。

No wait方式--如果无;标取请求的latch ,则:

-不会发生sleep或者spin.

-转而去获取其它可用的Latch

Latch锁在data buffer中的应用

data buffer存在的意义就是为了在内存中进行高速的数据查找和更新,尽量减少磁盘的IO操作, Buffer Cache中存在一个Hash Bucket结构,将数据库中已经读取的数 据块放到里面,在从数据库文件中读取到一个数据块后,Oracle会根据这个数据块的 文件编号,段编号,数据块号组合到一起通过一个内部的hash算法运算后,会放到不同 的hash bucket中,每个Hash Bucket都有一个Hash chain list,保留Buffer Header 中的信息,然后通过这个list,把相同hash值的Buffer串起来.结构如图:

 ​​​

为保护这个结构不受同步更新的破坏,Oracle设计了一个CBC latch的锁结构 (Cache Buffers Chains),一个latch保护32的桶(Bucket),所以为了访问hash列表, 必须先获得CBC Latch.先获取Latch后,在对Buffer进行操作.对buffer操作是一个比较耗时的操作,比如从磁盘读取block。由于一个latch管理 32个桶,所以对buffer操作时不能继续持有latch。Oracle使用两阶段加latch锁的 方式解决这个问题。

  1. 加latch锁
  2. 查找buffer,并对buffer加pin锁,如果是读取操作则为shared pin,若是写操 作,则exclusive pin
  3. 释放latch锁
  4. 对buffer进行操作
  5. 加latch锁
  6. 释放pin锁
  7. 释放latch锁 

参见下图,一个buffer拥有一个pin锁,每个pin锁对应两个列表,user's list(拥有 锁的用户列表)和waiter's list(等待锁的列表),如果用户等待pin锁的时间超过1 秒,则认为出现死锁。buffer和pin锁是 一 一对应关系

 加上锁保护以后,整体的图

所以读取数据块的过程如下,当一个用户进程想要访问一个数据块:

  1. 根据数据文件号,块号生成hash 值
  2. 在Hash Table中找到bucket地址
  3. 获取CBC latch,一个latch保护32个bucket
  4. bucket有一个指针指向bh(buffer head)
  5. 根据bh的搜索链表
  6. 匹配bh里面的内容和要找的
  7. 匹配到一个bh,给bh加锁buffer pin(共享和独占)
  8. 释放cbc latch, cbc latch做两件事情:保护链表,保护加buffer pin锁
  9. 进程根据bh里面的ba地址找内存块
  10. 找完了,获得cbc latch,在保护下 释放buffer pin锁

利用哈希表管理已经被缓存的data block。为了使得哈希桶上链表尽量短,理想目 标是一个链表上最多只有一个buffer,哈希桶的数量一般是data buffer数量的两 倍,并把桶分组,每个组对应一个latch,latch用来保护桶中的链表。一个latch保 护32个桶。

虽然和lock相比,latch是轻量级的,但是使用latch也是有比较大的开销的,所以 oracle尽量减少latch数量,所以一个latch管理了高达32个桶。

Oracle 等待事件 latch free:

如:

Oracle事件latch free定义为:当多个进程竞争一个latch 2次,而第2次的竞争者失败时,在 Statspack 或ASH报告中可以看到的Oracle事件名称。 当数据库发生IO瓶颈,并且出现这类事件时,就可以查看latch free对Oracle性能的影响。

latch free 是一种 Oracle 的内部技术,是用于提升性能的一种需要得到保护的数据结构。 通俗讲,在有多个几秒之间,用来竞争访问相同的资源的多个进程中,如果短时间内无法访问此特定资源,则会发生latch free事件。

由于Oracle数据库中大量组件都是由不同的进程驱动的,每一个进程都可以同时访问资源,并产生latch free的。 而我们的目的是保护共有的资源,因此在资源访问时,可能会出现竞争的情况。 在竞争时,如果第二个进程竞争失败,则表示该进程无法获取资源,这就引发了latch free事件。

 解决方案:首先查看 latch free 看看哪个类型latch 最多

select p1,p2,p3,inst_id,count(*) from gv$active_session_history where sample_time > sysdate-1/24 and event='latch free' group by p1,p2,p3,inst_id order by 5 desc; 

Latch锁类型较多,需要根据不同类型的Latch 做不同的处理方案

快速查看当前Lock锁等待信息:

Oracle提供一个名为utllockt.sql的脚本,它会给出一个树形结构的锁等待图,显示持有影响其他会话的锁的会话。使用此脚本,可以看出一个会话正在等待什么锁,哪个会话持有这些锁。该脚本位于$ORACLE_HOME/rdbms/admin目录下。

@?/rdbmsa/admin/utllockt.sql

执行脚本可以迅速看到 会话51在请求一个Share锁,等待47释放Exclusive锁。


http://www.kler.cn/a/558448.html

相关文章:

  • 内外网文件传输 安全、可控、便捷的跨网数据传输方案
  • MySQL 选择数据库
  • 【部署优化篇三】《DeepSeek边缘计算实战:把目标检测模型塞进树莓派,让AI在巴掌大的设备上“开天眼“》
  • CASAIM与韩国DOOSAN集团达成合作,开启工业制造自动化检测新篇
  • 网络运维学习笔记 016网工初级(HCIA-Datacom与CCNA-EI)PPP点对点协议和PPPoE以太网上的点对点协议(此处只讲华为)
  • Python 数据结构与实践深度剖析
  • 【HeadFirst系列之HeadFirstJava】第4天之理解对象的行为:方法操作实例变量
  • 3<4>2【Python链式对比,也叫连续比较】
  • Missing required prop: “maxlength“
  • C#上位机--进程和线程的区别
  • 解决Excel文件格式损坏问题:如何通过程序读取并复制内容
  • LLaMA-Factory|微调大语言模型初探索(4),64G显存微调13b模型
  • vue 识别 <think></think>
  • 政安晨【零基础玩转各类开源AI项目】DeepSeek 多模态大模型Janus-Pro-7B,本地部署!支持图像识别和图像生成
  • 精选案例展 | 智己汽车—全栈可观测驱动智能化运营与成本优化
  • http、websocket与MQTT协议
  • fedora 安装 ffmpeg 过程记录
  • 基于WebRTC与AI大模型接入EasyRTC:打造轻量级、高实时、强互动的嵌入式音视频解决方案
  • Spring Boot 启动类的原理与作用
  • 人工智能任务22-Deepseekv3原理架构中的数学公式,通过高度概括实现快速入门