latch是一种轻量级用于保护oracle共享内存结构,用户并发操作一致性的串行化锁定机制,如SGA中,各种数据被反复从磁盘读取到内存,又被重新写回到磁盘上,如果有并发用户做相同的事情,oracle必须使用一种机制来保证数据在读取的时候,只能由一个会话来完成,这就是latch,latch 不会造成阻塞,是只会等待,与每个latch相联系的还有一个清楚过程,当持有latch的进程成为死进程时,系统清除过程就会被调用,系统lock导致 用户等待,需要考虑系统的逻辑设计是否有问题,如多用户对主键的删除或者修改,是否有用户使用select… for update这样的语法,外键是否创建索引。latch 争用多半要考虑系统及数据库自身设计问题,如绑定变量,热块及参数设置是否合理。
  spin:比如数据缓存中的某个块要被读取,我们会获得这个块的 latch,这个过程叫做spin,另外一个进程恰好要修改这个块,他也要spin这个块,此时他必须等待,当前一个进程释放latch后才能spin 住,然后修改,如果多个进程同时请求的话,他们之间将出现竞争,没有一个入队机制,
  一旦前面进程释放所定,后面的进程就蜂拥而上,没有先来后到的概念,并且这一切都发生的非常快,因为Latch的特点是快而短暂。
  spin与休眠:
  休眠意味着暂时的放弃CPU,进行上下文切换(context switch),这样CPU要保存当前进程运行时的一些状态信息,比如堆栈,信号量等数据结构,然后引入后续进程的状态信息,处理完后再切换回原来的进程 状态,这个过程如果频繁的发生在一个高事务,高并发进程的处理系统里面,将是个很昂贵的资源消耗,所以Oracle选择了spin,让进程继续占有 CPU,运行一些空指令,之后继续请求,继续spin,直到达到_spin_count值,这时会放弃CPU,进行短暂的休眠,再继续刚才的动作。
  oracle中,latch是一种轻量级的锁。一般来说,latch由三种内存元素成:pid(进程id),内存地址和内存长度。Latch保证对共享数 据结构的排它性访问,以此来保证内存结构的完整性不受到损坏。在多个会话同时修改或者检视(inspect)sga中同一个内存结构时,必须串行化访问以 保证sga中数据结构的完整性。
  进程获取latch有两种模式:willing-to-wait和No_wait。no-wait模式只在少数latch中使用。通过no-wait模式 获取latch的统计信息记录在immediate_gets immediate_misses列中,这些列在v$latch,v$latch_parent,v$latch_children视图中都存在。一般来 说,no-wait模式在第一次获取一些有很多子latch的latch比如redo copy时使用。如果一个进程第一次获取这些子latch中的任何一个失败,它会立即使用no-wait模式询问下一个。只有当采用no-wait模式试 图获取所有的子latch都失败以后,才会转而采用willing-to-wait模式。
  通过willing-to-wait模式获取latch的统计信息存放在gets和misses列中。每当一个进程用willing-to-wait模式去获取一个latch时,gets都会增加。
  如果进程在第一次请求latch时,latch可用,就会直接获得该latch。在修改任何受到保护的数据结构之前,进程会将一些恢复信息写入到latch恢复区,这样当获得latch的进程发生异常时,pmon进程才能够清理该进程持有的latch。
  如果请求latch时,该latch不可用,进程就会在cpu中等待一小段时间(spin)然后重新请求latch。如果latch一直不可用,该过程 (spin一段时间然后重新请求)会一直重复。重复的次数由隐含参数_spin_count决定,默认值2000。如果在请_spin_count次之内 获得了latch,就对spin_gets和misses列各加一,否则,进程v$session_wait中记录latch free等待事件,然后释放cpu,转入睡眠状态。睡眠一定时间后,进程被唤醒并重复上面的过程,一直到获得latch。在成功获得latch后,才会更 行sleep列得统计信息。
  由于进程只有在获得latch后才会停止对latch得请求,如果某个持有latch的进程发生异常,其他请求该latch的进程该怎么办?岂不是要一直 等待下去?不会的。当一个进程请求latch失败一定次数后,它会请求pmon进程查看该latch的持有者,如果持有进程异常,pmon就会清理该进 程,释放latch。
  每个latch都有一个从0到13的优先级编号。父latch和独立latch的优先级编号是在oracle内核代码中固定的。子latch是÷在实例启动时创建,其优先级编号从其父latch继承。使用优先级可以避免死锁。
  当一个进程请求no-wait模式的latch时,该latch的优先级编号必须和它当前已经持有的latch的优先级编号相同。
  当一个进程请求willing-to-wait模式的latch时,该latch的优先级编号必须比它当前已经持有的latch的优先级编号要大。
  进程获取Latch的过程:
  任何时候,只有一个进程可以访问内存中的某一个数据块,如果进程因为别的进程正占用块而无法获得Latch时,他会对CPU进行一次spin(旋转),时 间非常的短暂,spin过后继续获取,不成功仍然spin,直到 spin次数到达阀值限制(这个由隐含参数_spin_count指定),此时进程会停止spin,进行短期的休眠,休眠过后会继续刚才的动作,直到获取 块上的Latch为止。进程休眠的时间也是存在算法的,他会随着spin次数而递增,以厘秒为单位,休眠的阀值限制由隐含参数 _max_exponential_sleep控制,默认是2秒,如果当前进程已经占用了别的Latch,则他的休眠时间不会太长(过长会引起别的进程的 Latch等待),此时的休眠最大时间有隐含参数_max_sleep_holding_latch决定,默认是4厘秒。这种时间限制的休眠又称为短期等 待。另外一种情况是长期等待锁存器(Latch Wait Posting),此时等待进程请求Latch不成功,进入休眠,他会向锁存器等待链表(Latch Wait List)压入一条信号,表示获取Latch的请求,当占用进程释放Latch时会检查Latch Wait List,向请求的进程传递一个信号,激活休眠的进程。Latch Wait List是在SGA区维护的一个进程列表,他也需要Latch来保证其正常运行,默认情况下share pool latch和library cache latch是采用这个机制。
  如果将隐含参数_latch_wait_posting设置为2,则所有Latch都采用这种等待方式,使用这种方式能够比较精确的唤醒某个等待的进程, 但维护Latch Wait List需要系统资源,并且对Latch Wait List上Latch的竞争也可能出现瓶颈。
  数据缓冲池Latch争用
  访问频率非常高的数据块被称为热快(Hot Block),当很多用户一起去访问某几个数据块时,就会导致一些Latch争用,最常见的latch争用有:
  (1)  buffer busy waits
  (2)  cache buffer chain
  Cache buffer chian产生原因:
  当一个会话需要去访问一个内存块时,它首先要去一个像链表一样的结构中去搜索这个数据块是否在内存中,当会话访问这个链表的时候需要获得一个Latch,如果获取失败,将会产生Latch cache buffer chain 等待,导致这个等待的原因是访问相同的数据块的会话太多或者这个列表太长(如果读到内存中的数据太多,需要管理数据块的hash列表就会很长,这样会话扫描列表的时间就会增加,持有chache buffer chain latch的时间就会变长,其他会话获得这个Latch的机会就会降低,等待就会增加)。
  Buffer busy waits 产生原因:
  当一个会话需要访问一个数据块,而这个数据块正在被另一个用户从磁盘读取到内存中或者这个数据块正在被另一个会话修改时,当前的会话就需要等待,就会产生一个buffer busy waits等待。
  产生这些Latch争用的直接原因是太多的会话去访问相同的数据块导致热快问题,造成热快的原因可能是数据库设置导致或者重复执行的SQL 频繁访问一些相同的数据块导致。
  查看造成LATCH BUFFER CACHE CHAINS等待事件的热快
  select distinct a.owner, a.segment_name
  from dba_extents a,
  (select dbarfil, dbablk
  from x$bh
  where hladdr in (select addr
  from (select addr
  from v$latch_children
  order by sleeps desc)
  where rownum<20)) b
  where  a.relative_fno=b.dbarfil
  and a.block_id<=b.dbablk
  and a.block_id+a.blocks>b.dbablk;
  查询当前数据库最繁忙的Buffer,TCH(Touch)表示访问次数越高,热点快竞争问题就存在
  select *
  from (select addr,
  ts#,
  file#,
  dbarfil,
  dbablk,
  tch
  from x$bh
  order by tch desc)
  where rownum<11;
  查询当前数据库最繁忙的Buffer,结合dba_extents查询得到这些热点Buffer来自哪些对象
  select e.owner, e.segment_name, e.segment_type
  from dba_extents e,
  (select *
  from (select addr, ts#, file#, dbarfil, dbablk, tch
  from x$bh
  order by tch desc)
  where rownum<11) b
  where e.relative_fno=b.dbarfil
  and e.block_id<=b.dbablk
  and e.block_id+e.blocks>b.dbablk;
  如果在Top 5中发现latch free热点块事件时,可以从V$latch_children中查询具体的子Latch信息
  select *
  from (select addr, child#, gets, misses, sleeps, immediate_gets igets,
  immediate_misses imiss, spin_gets sgets
  from v$latch_children
  where name= ‘cache buffers chains’
  order by sleeps desc)
  where rownum<11;
  获取当前持有最热点数据块的Latch和buffer信息
  select b.addr, a.ts#, a.dbarfil, a.dbablk, a.tch, b.gets, b.misses, b.sleeps
  from (select *
  from (select  addr, ts#, file#, dbarfil, dbablk, tch, hladdr
  from x$bh
  order by tch desc)
  where rownum<11) a,
  (select addr, gets, misses, sleeps
  from v$latch_children
  where name= ‘cache buffers chains’) b
  where a.hladdr = b.addr;
  利用前面的SQL可以找到这些热点Buffer的对象信息
  select distinct e.owner, e.segment_name, e.segment_type
  from dba_extents e,
  (select *
  from (select addr, ts#, file#, dbarfil, dbablk, tch
  from x$bh
  order by tch desc)
  where rownum<11) b
  where e.relative_fno = b.dbarfil
  and e.block_id<=b.dbablk
  and e.block_id+e.blocks>b.dbablk;
  结合SQL视图可以找到操作这些对象的相关SQL,然后通过优化SQL减少数据的访问,或者优化某些容易引起争用的操作(如connect by等操作)来减少热点块竞争
  break on hash_value skip 1
  select /*+ rule */ hash_value,sql_text
  from v$sqltext
  where (hash_value, address) in (
  select a.hash_value, a.address
  from v$sqltext a,
  (select distinct a.owner, a.segment_name, a.segment_type
  from dba_extents a,
  (select dbarfil, dbablk
  from (select  dbarfil, dbablk
  from x$bh
  order by tch desc)
  where rownum<11) b
  where a.relative_fno = b.dbarfil
  and a.block_id <= b.dbablk
  and a.block_id + a.blocks > b.dbablk) b
  where a.sql_text like ‘%’ || b.segment_name || ‘%’
  and b.segment_type = ‘TABLE’)
  order by  hash_value, address, piece;

oracle latch工作原理的更多相关文章

  1. Oracle NET工作原理、配置及连接问题排查

    一.Oracle NET配置文件 Oracle NET是一个软件层,支持不同网络协议之间的转换.不同的物理机器可以借助这个软件层实现相互间的通信,具体而言就是实现对oracle的远程访问. oracl ...

  2. Oracle Goldengate工作原理

  3. ORACLE工作原理小结

    ORACLE工作原理1-连接 我们从一个用户请求开始讲,ORACLE的完整的工作机制是怎样的,首先一个用户进程发出一个连接请求,如果使用的是主机命名或者是本地服务命中的主机名使用的是机器名(非IP地址 ...

  4. 【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之RAC 工作原理和相关组件(三)

    RAC 工作原理和相关组件(三) 概述:写下本文档的初衷和动力,来源于上篇的<oracle基本操作手册>.oracle基本操作手册是作者研一假期对oracle基础知识学习的汇总.然后形成体 ...

  5. Oracle数据库重做日志及归档日志的工作原理说明

    Oracle数据库重做日志及归档日志的工作原理: lgwr进程将redo log buffer中的重做数据写入到redo log中,此时的redo log分组,每当一个redo log group写满 ...

  6. 转载:【Oracle 集群】RAC知识图文详细教程(三)--RAC工作原理和相关组件

    文章导航 集群概念介绍(一) ORACLE集群概念和原理(二) RAC 工作原理和相关组件(三) 缓存融合技术(四) RAC 特殊问题和实战经验(五) ORACLE 11 G版本2 RAC在LINUX ...

  7. 【转】【Oracle 集群】ORACLE DATABASE 11G RAC 知识图文详细教程之RAC 工作原理和相关组件(三)

    原文地址:http://www.cnblogs.com/baiboy/p/orc3.html 阅读目录 目录 RAC 工作原理和相关组件 ClusterWare 架构 RAC 软件结构 集群注册(OC ...

  8. oracle 索引聚簇表的工作原理

    作者:Richard-Lui 一:首先介绍一下索引聚簇表的工作原理:(先创建簇,再在簇里创建索引,创建表时指定列的簇类型) 聚簇是指:如果一组表有一些共同的列,则将这样一组表存储在相同的数据库块中:聚 ...

  9. Oracle数据库的特点与工作原理

    Oracle数据库的特点 1.开放性: Oracle能在所有主流平台上运行(包括Windows),完全支持所有的工业标准,采用完全开放策略,可以使客户选择最适合的解决方案,对开发商全力支持. 2.可伸 ...

随机推荐

  1. 【BZOJ1038】【ZJOI2008】瞭望塔 [模拟退火]

    瞭望塔 Time Limit: 10 Sec  Memory Limit: 162 MB[Submit][Status][Discuss] Description 致力于建设全国示范和谐小村庄的H村村 ...

  2. 【BZOJ1598】牛跑步 [A*搜索]

    牛跑步 Time Limit: 10 Sec  Memory Limit: 162 MB[Submit][Status][Discuss] Description BESSIE准备用从牛棚跑到池塘的方 ...

  3. [IOS]VMware上虚拟机MAC安装XCode

    1:VMware上虚拟机MAC安装前 VMware上安装Xcode之后 2:安装Xcode过程:把Xcode复制到虚拟机桌面上 3:复制完成之后,双击Xcode_6.4.dmg 文件 4:把Xcode ...

  4. bzoj 2434 fail tree+dfs序

    首先比较明显的是我们可以将字符串组建立ac自动机,那么对于询问s1字符串在s2字符串中出现的次数,就是在以s1结尾为根的fail tree中,子树有多少个节点是s2的节点,这样我们处理fail tre ...

  5. linux驱动基础系列--Linux 串口、usb转串口驱动分析

    前言 主要是想对Linux 串口.usb转串口驱动框架有一个整体的把控,因此会忽略某些细节,同时里面涉及到的一些驱动基础,比如字符设备驱动.平台驱动等也不进行详细说明原理.如果有任何错误地方,请指出, ...

  6. python基础===创建大量对象是节省内存方法

    问题: 你的程序要创建大量(可能上百万) 的对象,导致占用很大的内存. 解决方案: 对于主要是用来当成简单的数据结构的类而言,你可以通过给类添加__slots__属性来极大的减少实例所占的内存.比如: ...

  7. x64dbg

    https://x64dbg.com/ https://github.com/x64dbg/x64dbg https://sourceforge.net/projects/x64dbg/files/s ...

  8. 2017多校第4场 HDU 6078 Wavel Sequence DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6078 题意:求两个序列的公共波形子序列的个数. 解法: 类似于最长公共上升子序列,对于每个i,只考虑存 ...

  9. [hadoop][基本原理]zookeeper简单使用

    代码:https://github.com/xufeng79x/ZkClientTest 1.简介 zookeeper的基本原理和使用场景描述可参考:[hadoop][基本原理]zookeeper基本 ...

  10. P4819 [中山市选]杀人游戏

    题目描述 一位冷血的杀手潜入Na-wiat,并假装成平民.警察希望能在NN个人里面,查出谁是杀手.警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人,谁是杀手,谁是平民.假如查 ...