oracle中的闩锁(latch)简介

1、闩锁、锁定和并发性

数据库系统本身是一个多用户并发处理系统,在同一个时间点上,可能会有多个用户同时操作数据库。这里就涉及两个很重要的问题。

这些用户之间的操作不会互相破坏。比如两个用户同时在相同的物理位置上写数据时,不能发生互相覆盖的情况。这叫串行化,也就是说,即便两个用户同 时写,也必须有先后,一个用户写完,另一个用户继续写。串行化会降低系统的并发性,但这对于保护数据结构不被破坏来说则是必需的。

在满足串行化的前提下,如何将并发性提升到最大。

在Oracle数据库中,通过闩锁(latch)和锁定(lock)来解决这两个问题。闩锁和锁定既有相同点又有不同点。相同点在于它们都是用于实现串行化的资源 。而不同点则在于闩锁是一个低级别、轻量级的锁,获得和释放的速度很快,以类似于信号灯的方式实现。而锁定则可能持续的时间很长,通过使用队列, 按照先进先出的方式实现。也可以简单地理解为闩锁是微观领域的,而锁定则是宏观领域的。

2、闩锁(latch)概述

Oracle数据库使用闩锁来管理内存的分配和释放。假设,某个用户进程(假设其为A)发出一条update语句,要去更新58号数据块里的某条记录。则该用户进 程对应的服务器进程在写内存的时候,找到58号数据块,并往里写内容。A在写58号数据块的过程中,这时,另一个用户进程B发出insert语句,要将某个新 的记录插入到58号数据块里。如果没有一定的保护机制,A正要写入的空间可能会被B抢先写入,或者相反,B正要写入的空间也可能会被A抢先写入。不管哪 个用户先抢先写入,造成的结果就是,58号数据块里的数据都混乱了,因为这时,A和B之间的数据互相交织在一起了。

因此,必须使用latch对此进行保护。简单来说,任何进程要写数据块时,都必须先获得latch,在写入过程中,一直持有该latch,写完以后,释放该latch 。对于上面的例子来说,当A在写入58号数据块时,先获得latch,然后开始写。而当A正在写入的过程中,B也要写58号数据块。这时B在尝试获得latch时, 发现该latch正被其他用户(也就是A)持有,因此B进入等待状态。直到A写完数据块并释放latch以后,B才能获得latch,获得latch以后,才能在58号数据 块里写入数据。

这里只是以写数据块为例来说明为何要使用latch。而事实上,latch不仅仅用于写数据块,比如对于shared pool来说,其内存单位就不是数据块了。latch 也不仅仅用于写操作,只要涉及内存地址的读和写,都需要通过获得latch来实现串行化,一次只能有一个服务器进程在读或者写内存地址。

查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/database/Oracle/

Oracle在实例管理中,不管是buffer cache、shared pool还是log buffer,都引入了各种各样的latch。

实现latch时,实际是由操作系统的旗语(semaphore:也叫信号量)来完成的。为了便于理解,可以把它们想象为,通过某个变量值的变化而实现的。变量 值为0则说明latch当前没有被其他进程获取,否则如果为非0值,则说明它已经被其他进程所获取了。Oracle在设计latch的时候将其定义为轻量级锁,因此 它的操作非常快,以微秒(microsecond,也就是百万分之一秒)来计算。

3、latch分为两种类型:

(1)愿意等待(Willing-To-Wait)

大部分的latch都属于这种类型。这种类型的latch都是通过Test-And-Set的方式来实现的。也就是说,如果当前进程不能获得latch的时候,会绕着CPU旋转 ,而不放弃CPU。这也就是所谓的SPIN CPU,实际就是执行一段空循环,类似执行下面一段代码(其中的N由Oracle内部来控制):

loop

exit when i>= N

i := i+1;

null;

end loop;

进程之所以不释放CPU而是绕着CPU旋转,是由于latch操作本身是一个很快速的动作,因此可能等一会就能获得latch了。当进程一旦获得CPU,但是获得不了 latch时,如果这时候立刻放弃CPU,那么需要进行上下文切换,下次再次尝试获得latch时,又要进行上下文切换,可能反而要消耗更多的时间。因此,进程 在不能获得latch的时候,会执行上面这段代码,绕着CPU转一会,然后再次尝试获得latch,如果仍然不能获得,则再次旋转CPU。当反复旋转CPU并尝试获得 latch的的次数超过某个上限(该上限由隐藏参数控制)时,这时进程会释放CPU,并进入睡眠(Sleep)状态。进程一旦进入睡眠状态,则会抛出一个对应的 等待事件,并记录在视图v$session_wait里,说明当前该进程正在等待的latch的类型等信息。初始状态下,一个进程会睡眠0.01秒。然后醒过来,并再次尝 试获得latch。如果旋转CPU的次数达到上限以后,仍然不能获得latch,则再次进入睡眠,这时会睡眠两倍的时间,依此类推,直到达到睡眠的最大值:0.2 秒。

这是在数据库服务器具有多个CPU时的情形,如果只有一个CPU,就不存在旋转CPU的情况,一旦获得不了latch,就进入睡眠。

总的来说,当进程尝试获取Willing-To-Wait类型的latch时,如果失败,则进程会一直尝试对latch的获取,不断循环,直到获得latch为止,或者是达到所 指定的上限值为止。当达到上限值时,进程进入睡眠。

(2)不等待(No-Wait)

这种类型的latch比较少,对于这种类型的latch来说,都会有很多个可用的latch。当一个进程请求其中的一个latch时,会以no-wait模式开始请求。如果所 请求的latch不可用,则进程不会等待,而是立刻请求另外一个latch。只有当所有的latch都不能获得时,才会进入等待。

从另外一个角度来说,latch分为单个latch(Solitary latch,比如shared pool latch以及redo allocation latch等)和latch组(比如library cache  latch、cache buffers lru chain latch以及cache buffers chains latch等)。latch组包括父latch和子latch。单个latch和父latch都是定义在数据库软 件代码里的,而且都是静态分配的。对于每种类型的latch,只有一个父latch。而子latch则根据参数或默认值而动态设定,而且子latch的访问独立于父 latch。通常来说,父latch只用于汇总显示报表的目的。

如果latch资源被争用,通常都会表现为CPU资源使用过高。而反过来说,如果我们发现CPU资源很紧张,利用率总是在90%以上,甚至总是在100%,其主要原 因有以下几点。

SQL语句没有使用绑定变量。如果没有使用绑定变量,或者书写SQL时随意性过大,比如大小写混用等。则Oracle对每一条SQL语句都要进行解析,也就是要非 常频繁地读写shared pool里的内存块,从而导致与解析SQL相关的latch争用。

执行SQL语句时,扫描的数据块过多,或者说SQL语句写的比较低效,导致要扫描很多的数据块才能返回所要的记录。因为在查找、扫描数据块的过程中,进 程也要获得latch,直到找到数据块为止。

为何一旦latch资源发生争用,就会导致CPU繁忙呢?可以想象一下,假设某个进程(A)执行一条SQL语句需要访问10000个数据块,那么该进程在扫描数据块 的过程中,一直持有latch。而另一个进程B也要执行SQL,但是由于A持有了latch,导致B无法获得,于是旋转一会CPU,再去获得latch,直到进入睡眠才释 放CPU。接下来C进程也要执行SQL,同样的,由于A持有了latch,导致C无法获得,于是也旋转一会CPU,再去获得latch,直到进入睡眠才释放CPU。如果类似 B和C的进程很多的话,那我们会发现,CPU总是在被旋转,也就是在做空的循环,而无法做其他的事情。因此,体现出CPU的使用率过高。

要解决latch的争用,关键在于共享SQL语句(比如使用绑定变量、规范SQL的书写等)以及优化SQL语句,使其搜索以及扫描的数据块的个数下降到最低。

时间: 2024-10-02 15:12:36

oracle中的闩锁(latch)简介的相关文章

通过sql脚本查看Oracle中是否有锁表

1.查看是否有锁表的sql select 'blocker('||lb.sid||':'||sb.username||')-sql:'|| qb.sql_text blockers, 'waiter ('||lw.sid||':'||sw.username||')-sql:'|| qw.sql_text waiters from v$lock lb, v$lock lw, v$session sb, v$session sw, v$sql qb, v$sql qw where lb.sid=sb

Oracle的闩锁、锁定及并发性

数据库系统本身是一个多用户并发处理系统,在同一个时间点上,可能会有多个用户同时操作数据 库.这里就涉及两个很重要的问题. 这些用户之间的操作不会互相破坏.比如两个用户同时在相同的物理位置上写数据时,不能发生互 相覆盖的情况.这叫串行化,也就是说,即便两个用户同时写,也必须有先后,一个用户写完,另一个 用户继续写.串行化会降低系统的并发性,但这对于保护数据结构不被破坏来说则是必需的. 在满足串行化的前提下,如何将并发性提升到最大. 在Oracle数据库中,通过闩锁(latch)和锁定(lock)来

全面解析oracle中的锁机制4

7.enqueue: 什么是enqueue enqueue可以做名词,也可以做动词来解释. 做名词时,指的的是一种锁的类型,比如Tx enqueue. 做动词时,则是指将锁请求放入到请求队列的操作. 我们知道,lock是一种需要排队的锁实现机制,这和latch是不一样的,latch是一种轻量级的锁,是不需要排队得.Enqueue就是lock的排队机制的实现. lock是用来实现对于共享资源的并发访问的.如果两个session请求的lock是兼容的,则可以同时锁定资源,如果两个session请求的

Oracle latch 闩锁结构 总结

以下内容太整理自网络,完全处于学习目的,如有侵权请及时联系我,我会立即删除. 一. Latch 说明 1.1 Latch Latch属于System Lock, 用于保护SGA区中共享数据结构的一种串行化锁定机制.Latch的实现是与操作系统相关的,尤其和一个进程是否需要等待一个latch.需要等待多长时间有关. Latch是Oracle提供的轻量级锁资源,是一种能够极快地被获取和释放的锁,能快速,短时间的锁定资源,防止多个并发进程同时修改访问某个共享资源,它只工作在SGA中,通常用于保护描述b

《Oracle高性能自动化运维》一一2.1 闩(Latch)

2.1 闩(Latch)2.1.1 Latch简介对于对称多处理机(SMP)系统而言,在同一时间点,所有CPU都可以请求修改同一内存.在理想状态下,"请求""更改"操作是由单个CPU独立完成的,而不会被拆分成多个时间片处理.在特殊情况下,"请求""更改"操作将被拆分成多个时间片处理,这时操作系统就会使用上下文结构来保护内存数据的完整性.Oracle 闩(Latch)的作用与上下文类似,主要是用于保护Oracle内存结构被独占访

Oracle中的锁(LOCK)机制

 本文结合示例简要的介绍了一下Oracle中锁的机制. 为了解决多用户环境下并发操作相同的资源而造成的错误修改数据的问题.单用户环境下不需要考虑锁,因为所有操作都是串行的.下面的文章简要的介绍了一下 锁的分类异常复杂,enqueue.latch.mutex等,都是为了解决并发存在的,自己也有些混乱,所以也不过多解释了.下面列举一些对于lock的要点内容. l 排他锁: 不允许相关的资源被共享.一个资源在一个时间点内只有一个事务能够获取该资源的排他锁,只有持有该锁的事务能够修改相关的资源, 其他想

SQL Server和Oracle中的锁和死锁

1.锁的作用 ORACLE : 锁是一种机制,当某个数据库对象正被其他进程或用户修改时,这种机制可以保护它不被修改. 为了防止对象被两个不同的用户同时修改,数据库系统创建了锁这种复杂的数据结构,来实现锁定机制,这种机制使用在oracle中称为排队的队列结构,以串行的方式执行锁. 锁的作用如下: 1) 他们坚持一致性和完整性,在事务处理期间,数据和对象保证它们的一致性和完整性. 2) 但对象不是立即可用时,它们提供一种队列结构,这种结构允许所有会话都加入到等候对象的队列中, 3) 自动处理锁机制

全面解析oracle中的锁机制3

5.TX事务锁和 TM(DML enqueue)锁: TX锁:数据块的前面有一个开销空间(ITL),这里会存放一个块的事务列表,对于每一个锁定了块的事务,都会在这个事务列表中有一个条目.这个结构的大小有创建对象时的两个参数决定: INITRANS:初始分配的可容纳事务的大小,一般初始为2,可以说是事务槽. MAXTRANS:这个结构可以扩缩到的最大大小.它默认为255,在实际中,最小值为2.在Oracle10g 中,这个设置已经废弃了,所以不再使用.这个版本中的MAXTRANS 总是255.  

oracle中正则表达式相关函数regexp_like简介

前面介绍了oracle中正则表达式构成的元数据,但仅仅知道元数据是不够的,oracle中的正则表达式是结合其特定的4个函数使用的,其中用的最多的就是现在要介绍的的这个函数:regexp_like regexp_like函数的基本构成是: regexp_like(x,pattern[,match_option]) 其基本功能是在x中查找pattern,如果能找到返回true否则返回false,这里的可选参数match_option可以有如下几种形式: 'c' 表明进行匹配时区分大小写(这也是默认选