前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >性能优化:Cache Buffer Chain Latch等待事件

性能优化:Cache Buffer Chain Latch等待事件

作者头像
数据和云
发布于 2018-03-06 07:35:58
发布于 2018-03-06 07:35:58
1.5K0
举报
文章被收录于专栏:数据和云数据和云

彭小波

ACOUG核心成员,Oracle用户组年轻专家。擅长Oracle数据库架构规划、SQL,OWI方面的优化。曾服务于各大企业数据库的维护以及系统开发,目前从事百年人寿保险股份有限公司的数据库服务运维工作。

产生的背景

Oracle为了将物理 IO 最小化,把最近使用过的数据块保持在内存中。为了管理这些内存,oracle 使用如图的结构,Hash Chain 的结构,Hash Chain 位于共享池中,使用典型内存结构 Bucket->Chain->Header 结构进行管理 lock# 组成的,当扫描块时使用Hash函数进行hash运算,使用hash值查找 hash bucket,具有相同hash值的 buffer haeder 在 hash bucket 上以 chain 形式链接。Buffer header 有指向实际缓冲区的指针。注意:Hash Chain结构是在共享池中,而实际缓冲区信息存储在高速缓冲区中。Hash Chain 结构利用 cache buffers chain Latch来保护。

当进程扫描特定的数据块时,必须获得相应数据块所在 Hash Chain 管理的 cache buffers chain Latch。基本上一个进程获得仅有的一个 cache buffers chain Latch,一个 cache buffers chain Latch 管理多个 Hash Chain。当多个进程同时检索Buffer Cache时,获得 cache buffers chain Latch 的过程中发生争用,就会产生该等待事件。Hash Chain 结构的起点是Hash表,Hash 表由多个 hash bucket 组成,块地址是由 file#+b cache buffers chain Latch 等待事件。

进程扫描特定的数据块的过程如下: 1、Oracle 以每个块的文件号、块号和类型做 HASH 运算,得到 HASH 值。根据 HASH值,到 HASH 表中取出指定块的内存地址 2、获取 CBC Latch 3、根据 HASH 值,搜索 CBC 链表 4、根据 DBA 找到 BH(Buffer Header) 加 Buffer Pin 5、加完 Buffer Pin 马上释放 CBC Latch 6、访问 Buffer 开始 fetch 数据 7、获取 CBC Latch 8、释放 Buffer Pin 9、释放 CBC Latch

使用 SQL 语句可以获得 hash_latches,hash_buckets 数量,因此一个锁存器保护 Bucket数量是1048576/32768=32个。

SQL> select x.ksppinm name, y.ksppstvl value, y.ksppstdf isdefault, decode(bitand(y.ksppstvf, 7), 1, 'MODIFIED', 4, 'SYSTEM_MOD', 8 'FALSE') ismod, decode(bitand(y.ksppstvf, 2), 2, 'TRUE', 'FALSE') isadj from sys.x$ksppi x, sys.x$ksppcv y where x.inst_id = userenv('Instance') and y.inst_id = userenv('Instance') and x.indx = y.indx and x.ksppinm like '%db_block_hash%' order by translate(x.ksppinm, ' _', ' ');

产生的原因

1.执行效率低下的SQL,低效的 SQL 语句是发生 Latch:cache buffers chains 争用的主要原因。发生在多个进程同时扫描大范围的表或索引时。

2.出现热块 hot block 时,由于编写 SQL 语句时,SQL 持续扫描少数特定块(between and ,in,not in, exists),多个会话同时执行 SQL 语句时,发生 Latch:cache buffers chains 争用。

【案例1 Latch:cache buffers chains争用事件重现 】

--1.创建测试表

create table t1(id int,name varchar2(10)); insert into values(1,'xiaobo'); commit;

--2.获取t1表的第一行数据及 ROWID,根据 dbms_rowid 包查出这行数据的文件号、块号

SQL> select rowid, dbms_rowid.rowid_relative_fno(rowid) file#, dbms_rowid.rowid_block_number(rowid) block#, id, name from emm.t1 where rownum = 1; 2 3 4 5 6 7 ROWID FILE# BLOCK# ID NAME ------------------ -------- ---------- ----- ---------- AAADfaAAFAAAACDAAA 5 131 1 xiaobo

注意:这里的 DBA(Data Block Address) 就是由5号文件和131号块组成

--3.根据 DBA获取 CBC Latch 的地址

SQL> select hladdr from x$bh where file#=5 and dbablk=131; HLADDR ---------------- 00000001D1C266D8

--4.根据CBC Latch的地址可以查出这个 CBC Latch 被获得的次数

SQL> select addr,name,gets from v$latch_children where addr='00000001D1C266D8'; ADDR NAME GETS ---------------- --------- ------ 00000001D1C266D8 cache buffers chains 46

--5.再次读取t1表的第一行数据,再次产生一次逻辑读

SQL>select id,name from emm.t1 where rowid='AAADfaAAFAAAACDAAA'; ID    NAME ------- ------------ 1    xiaobo

--6.CBC Latch 的次数变为 48,说明一次逻辑读产生两次 CBC Latch

SQL> select addr,name,gets from v$latch_children where addr='00000001D1C266D8'; ADDR NAME GETS ---------------- ------------------------ ------- 00000001D1C266D8 cache buffers chains 48

这里说明一次逻辑读要加两次 CBC Latch,一次为了加 Buffer Pin,一次为了释放 Buffer Pin!

使用 oradebug 跟踪 CBC Latch 争用事件

SQL> oradebug setmypid Statement processed. SQL> oradebug peek 0x1D1C266D8 4 -- 观察 CBC Latch 地址为 0x1D1C266D8 开始之后的4字节信息的值为0 [1D1C266D8, 1D1C266DC) = 00000000 SQL> oradebug poke 0x1D1C266D8 4 1 --修改 CBC Latch 地址为 0x1D1C266D8 开始的4字节信息的值为1,相当于获取了 Latch BEFORE: [1D1C266D8, 1D1C266DC) = 00000000 --修改前的值 AFTER: [1D1C266D8, 1D1C266DC) = 00000001 --修改后的值

--7. 再开一个新的会话,会话号为768

SQL> conn / as sysdba Connected. SQL> select sid from v$mystat where rownum=1; SID ---------- 768

--8.在新会话768下再查询T1表的第一行,我观察到不会堵塞

SQL>select id,name from emm.t1 where rowid='AAADfaAAFAAAACDAAA'; ID   NAME -------- ------------ 1   xiaobo

--9.我们回到 oradebug 的会话,这次我们不是使用 select 语句,而使用 update 语句来获 取 latch

SQL> update emm.t1 set id=2 where rowid='AAADfaAAFAAAACDAAA'; 1 row updated.

--10.再次使用 oradebug 模拟获取 latch

SQL> oradebug setmypid Statement processed. SQL> oradebug poke 0x1D1C266D8 4 1 BEFORE: [1D1C266D8, 1D1C266DC) = 00000000 AFTER: [1D1C266D8, 1D1C266DC) = 00000001

--11.回到刚才768会话下,查询T1表的第一行,这时我观察到产生了堵塞

SQL>select id,name from emm.t1 where rowid='AAADfaAAFAAAACDAAA';

--12.我们再开第三个会话,查看会话号768的等待事件,我们看到产生了 CBC Latch 的等待事件

最后在第一个会话中释放 lacth

SQL> oradebug poke 0x1D1C266D8 4 0 BEFORE: [1D1C266D8, 1D1C266DC) = 00000001 AFTER: [1D1C266D8, 1D1C266DC) = 00000000

总结: 在获取保护 hash bucket 的 cache buffers chains latch 时,如果是读取工作(select),就以 shared 模式获得(这也是我们刚才在实验中 select 时没有产生争用的原因)。如果是修改工作(update),就以 exclusive 模式获得。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-08-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据和云 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
AngularJS入门心得4——漫谈指令scope
  上篇《AngularJS入门心得3——HTML的左右手指令》初步介绍了指令的概念和作用。已经和指令打过一个照面,就不会那么陌生了,今天主要介绍的是一个困扰了我很久终于想通的问题,这个问题与scope有关,可以看做是《AngularJS入门心得1——directive和controller如何通信》在scope上的补充和延伸。    小时候,老师就教会了我们盲人摸象这个成语,教导我们认识事物不能片面,缺少对于一个事物全局的认知。所以,说到指令,它的一个完整结构如下: angular.module('myA
JackieZheng
2018/01/16
2.1K0
AngularJS入门心得4——漫谈指令scope
angularjs 指令详解
一、指令定义 对于指令,可以把它简单的理解成在特定DOM元素上运行的函数,指令可以扩展这个元素的功能。 首先来看个完整的参数示例再来详细的介绍各个参数的作用及用法: <div my-directive></div> 二、指令参数的作用和意义(这个地方只选常用的几种来讲一下) restrict[string] restrict是一个可选的参数。用于指定该指令在DOM中以何种形式被声明。默认值是A,即以属性的形式来进行声明。 可选值如下: E(元素) <my-directive></my-directive
柴小智
2018/04/10
2.4K0
angularjs 指令详解
angularjs directive学习心得
transclude有三个选项,true, false, 和object.如果不显示指明的话,默认为false. 当为false的时候,则那个directive里面的指令不会嵌入到你写的模板里,举个例子 下面是html代码
嘿嘿嘿
2018/09/10
1.1K0
angularjs directive学习心得
AngularJs指令解密
指令定义 在《AngularJs权威教程》中,指令可以简单理解成特定的DOM元素上运行的函数;我认为还可以理解成将将自定义的HTML标签解析成原始的标签,然后为其加入一些扩展的功能(函数). angularjs 提供了一个强大的扩展系统,通过指令机制,我们可以通过自定义指令来扩展自己的指令系统。 在AngularJS的核心里,指令可以绑定元素的属性(例如可见性,class列表,内部文本,内部HTML或者值)到scope的属性或表达式。最值得注意的是,一旦监测到scope中的变化被标记,这些绑定就会被更新。
双愚
2018/07/17
2.4K0
4、Angular JS 学习笔记 – 创建自定义指令 [翻译中]
注意:本指南是针对已经熟悉AngularJS基础的开发者。如果您只是想要开始,建议您先去看教程。如果你在寻找指令的API,我们最近把他移动到$compile
前Thoughtworks-杨焱
2021/12/08
5K0
AngularJS 1 教程
随着浏览器性能提升,更多Web Page演变为Web App,特别是在中大型的项目中,就需要一个 前端框架 来:
小刀c
2022/08/16
4.8K0
带你走近AngularJS - 创建自定义指令
带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自定义指令 ------------------------------------------------------------------------------------------------ 为什么使用AngularJS 指令? 使用过 AngularJS 的朋友应该最感兴趣的是它的指令。现今市场上的前端框架也只有AngularJS
葡萄城控件
2018/01/10
2.7K0
带你走近AngularJS - 创建自定义指令
Angular Directive 详解
如上所示,return的对象中会有很多的属性,这行属性都是用来定义directive的。
西南_张家辉
2021/02/02
2.8K0
2-进军 angular1.x 表达式和指令
使用驼峰法来命名一个指令, runoobDirective, 但在使用它时需要以 - 分割, runoob-directive:
西南_张家辉
2021/02/02
2.6K0
angularJS学习之路(三十)---自定义指令---templateUrl
不过这里因为js目录是当前的目录,你的html目录肯定在另外一个文件夹里,所以自己记得路径的问题
wust小吴
2019/07/08
5780
第216天:Angular---自定义指令(二)
自定义指令 1、第一个参数是指令的名字,第二个参数任然应该使用一个数组,数组的最后一个元素是一个函数。定义指令的名字,应该使用驼峰命名法 1 <!DOCTYPE html> 2 <html lang="en"> 3 4 <head> 5 <meta charset="UTF-8"> 6 <title>Document</title> 7 <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstr
半指温柔乐
2018/09/11
4780
【AngularJS】—— 8 自定义指令
AngularJS支持用户自定义标签属性,在不需要使用DOM节点操作的情况下,添加自定义的内容。 前面提到AngularJS的四大特性:   1 MVC   2 模块化   3 指令   4 双向数据绑定 下面将会介绍如下的内容: 1 如何自定义指令   2 自定义指令的使用   3 自定义指令的内嵌使用   如何自定义指令:   Angular是基于模块的框架,因此上来肯定要创建一个自己的模块: var myAppModule = angular.module("myApp",[
用户1154259
2018/01/17
8840
【AngularJS】—— 8 自定义指令
angularJS学习之路(十九)---自定义指令关于独立作用域
1.首先关于  scope:{} 和scope:true 效果是一样的 <!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="utf-8"> <title></title> </head> <body> <div ng-init="myProperty = 'wow, this is cool'"></div> Surrounding scope: {{ myProperty }} <div myInherit
wust小吴
2019/07/08
5030
AnagularJs之directive
  假如我们发现要写很多公共或是重用的dom、class、attr属性或是需要操作scope作用域,就要考虑代码最好不要copy、不要出现重复的代码段,好像是哪位大牛说的话,具体记不清了,反正就是为了性能优化等方面。
用户5640963
2019/07/26
1.2K0
【AngularJS】—— 10 指令的复用
前面练习了如何自定义指令,这里练习一下指令在不同的控制器中如何复用。   —— 来自《慕课网 指令3》   首先看一下一个小例子,通过自定义指令,捕获鼠标事件,并触发控制器中的方法。   单个控制器的标签指令   依然是先创建一个模块 var myAppModule = angular.module("myApp",[]);   在模块的基础上,创建控制器和指令 myAppModule.controller("myAppCtrl",["$scope",function($scop
用户1154259
2018/01/17
7740
【AngularJS】—— 10 指令的复用
带你走近AngularJS - 体验指令实例
带你走近AngularJS系列: 带你走近AngularJS - 基本功能介绍 带你走近AngularJS - 体验指令实例 带你走近AngularJS - 创建自定义指令 ------------------------------------------------------------------------------------------------ 之前我们已经介绍了所有的AngularJS 基础知识,下面让我们通过实例来加深记忆,体验自定义指令的乐趣。 手风琴指令 我们展示的第一个例子是手
葡萄城控件
2018/01/10
2.8K0
带你走近AngularJS - 体验指令实例
AngularJS 的 API:模块 API、指令 API、服务 API、过滤器 API、路由 API
AngularJS 是一款流行的前端 JavaScript 框架,提供了丰富的 API 接口,用于实现前端应用的各种功能。本文将详细介绍 AngularJS 的 API,包括模块 API、指令 API、服务 API、过滤器 API、路由 API 等内容,帮助开发者充分了解和熟练运用 AngularJS 的各项功能。
网络技术联盟站
2023/07/05
5930
【AngularJS】—— 12 独立作用域
前面通过视频学习了解了指令的概念,这里学习一下指令中的作用域的相关内容。 通过独立作用域的不同绑定,可以实现更具适应性的自定义标签。借由不同的绑定规则绑定属性,从而定义出符合更多应用场景的标签。 本篇将会总结下面的内容:   1 为何需要独立作用域   2 如何实现独立作用域   3 作用域的数据绑定 之前有一些错误,是由于replace拼写错误导致的。 拼写正确后,网友发现报错,无法正常工作。这是因为模板中存在单标签<br>,导致模板无法正确解析~ 再次感谢博友们提出的错误! 独立作
用户1154259
2018/01/17
1.5K0
【AngularJS】—— 12 独立作用域
angularjs学习第六天笔记(指令简介学习)
  您好,由于周末有事情,没哟学习angularjs,几天晚上开始继续学习angularjs,坚持加油每一天。谢谢
小小许
2018/08/30
5530
angularjs学习第六天笔记(指令简介学习)
【AngularJS】 # AngularJS入门
ng-app 指令定义一个 AngularJS 应用程序。 若不声明,将直接显示表达式。
全栈程序员站长
2022/09/15
24.3K0
【AngularJS】 # AngularJS入门
相关推荐
AngularJS入门心得4——漫谈指令scope
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档