楼主: chandler_1983

[精华] 请问library cache pin和library cache lock是latch吗

[复制链接]
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
11#
发表于 2008-6-23 21:01 | 只看该作者
为什么是2
是不是一个handle对应的object分为两部分,在两个heap中? 如果这样可能跟object大小相关,object非常大被分在很多heap中的时候是不是就是多个pin。


另外一种假设,你的猜测是不是和两个base table相关,你可以做一个view来测试,或者分别是好用2、3、4个base table的 动态视图 来测试。

使用道具 举报

回复
论坛徽章:
25
授权会员
日期:2007-08-20 23:44:422011新春纪念徽章
日期:2011-01-25 15:42:562011新春纪念徽章
日期:2011-02-18 11:42:49管理团队成员
日期:2011-05-07 01:45:082012新春纪念徽章
日期:2012-01-04 11:49:54咸鸭蛋
日期:2012-02-06 17:15:202012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:362012新春纪念徽章
日期:2012-02-13 15:11:36
12#
发表于 2008-6-23 23:15 | 只看该作者
library cache pin和library cache lock是”锁”
由于”锁“也是一种内存结构,需要由latch来保护,所以也会有两个latch来保护,也称为"library cache pin"和"library cache lock"

library cache lock是施加在library cache object handle上的锁,把这个handle简单地理解为一个指针,而把library cache pin理解为这个指针所指向的内容的锁

假如你要写个多进程程序,从文件读入数据放入内存中,为了避免对同一个文件分配多份内存,导致重复,对每个文件只分配一块内存,为实现这样的目的,你在设计程序时,在内存中设计了一个表,表的条目为一个文件名与一个内存指针。那你在打开一个文件读入时,首先根据文件名称从那个表中找到一个内存指针--HANDLE,并以适当的模式锁住,这个过程可理解为library cache lock。然后从文件中读入数据到这个指针指向的内存,这个过程可以理解为library cache pin。

这个例子举得比较简单,不是很精确。可展开进一步讨论

[ 本帖最后由 magic007 于 2008-6-23 23:16 编辑 ]

使用道具 举报

回复
论坛徽章:
38
2010新春纪念徽章
日期:2010-01-04 08:33:082012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:25版主2段
日期:2012-05-15 15:24:11优秀写手
日期:2013-12-18 09:29:08马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
13#
发表于 2008-6-24 09:08 | 只看该作者
在SQL*Plus直接输入SELECT命令进行实验,将会受到SQL*Plus的影响。我以前实验的结果,在9i环境下,每一条SELECT语句在执行完毕后,ORACLE并不关闭游标,只到下一条语句执行时,才关闭上一条语句的游标。10G下我没试过,但是SQL*Plus肯定会对结果造成一定的影响,我用下面两个脚本,观察硬解析、软解析、快速软解析和无解析时对Library cache lock latch、Library cache pin latch和Library cache latch这三个闩的影响:

--------(脚本1)------------------
declare
  mgets varchar2(10);
  mname varchar2(100);
  msql varchar2(200);
  mcur number;
  mstat number;
  jg varchar2(100);
  kg varchar2(100):=' ';
begin
for i in 1..20 loop
   mcur:=dbms_sql.open_cursor;
   msql:='select name,gets from v$latch where name in (''library cache'',''library cache lock'',''library cache pin'')';
   dbms_sql.parse(mcur,msql,dbms_sql.native);
   dbms_sql.define_column(mcur,1,mname,100);
   dbms_sql.define_column(mcur,2,mgets,10);
   mstat:=dbms_sql.execute(mcur);
   for j in 1..3 loop
     mstat:=dbms_sql.fetch_rows(mcur);
     dbms_sql.column_value(mcur,1,mname);
     dbms_sql.column_value(mcur,2,mgets);
     dbms_output.put(jg||'  '||mname||' : '||mgets);
   end loop;
   dbms_output.put_line('');
   dbms_sql.close_cursor(mcur);
end loop;
end;
/

将上面的程序略做修改,让循环内每次游标的文本都不一样:
--------(脚本2)------------------
declare
  mgets varchar2(10);
  mname varchar2(100);
  msql varchar2(200);
  mcur number;
  mstat number;
  jg varchar2(100);
  kg varchar2(100):=' ';
begin
for i in 1..20 loop
   mcur:=dbms_sql.open_cursor;
   msql:='select name,gets'||kg||'from v$latch where name in (''library cache'',''library cache lock'',''library cache pin'')';
   dbms_sql.parse(mcur,msql,dbms_sql.native);
   kg:=kg||' ';
   dbms_sql.define_column(mcur,1,mname,100);
   dbms_sql.define_column(mcur,2,mgets,10);
   mstat:=dbms_sql.execute(mcur);
   for j in 1..3 loop
     mstat:=dbms_sql.fetch_rows(mcur);
     dbms_sql.column_value(mcur,1,mname);
     dbms_sql.column_value(mcur,2,mgets);
     dbms_output.put(jg||'  '||mname||' : '||mgets);
   end loop;
   dbms_output.put_line('');
   dbms_sql.close_cursor(mcur);
end loop;
end;
/

还可以将上面两段代码中的SQL语句换成:'select gets, pins from v$librarycache where namespace=''SQL AREA'''; 观察一下Library cache lock/pin会和 latch有什么不同的结果,测试数据如下:

  1. 利用脚本1查看在循环中共享游标的情况:
  2. 在游标被缓存到PGA后:
  3.                                                      Library cache  Library cache    Library cache
  4.                                   Gets    Pins    Lock latch     Pin Latch               latch
  5. 在循环中打开游标:          0        1        0                    2                       2
  6. 在循环中解析        :        0        1        0                    2                       2 (将mcur:=dbms_sql.open_cursor移到循环之外)
  7. 只在循环中执行、抓取:    0        0        0                    0                       0(将dbms_sql.parse(mcur,msql,dbms_sql.native)移到循环之外)

  8. 在游标未被缓存到PGA(即将session_cached_cursors设为0)时:

  9. 在循环中打开游标:          0        1        4                   2                        2
  10. 在循环中解析        :        0        1        4                   2                        2
  11. 只在循环中执行、抓取:    0        0        0                   0                        0

  12. 利用脚本2查看硬解析或不在循环中共享游标的情况(session_cached_cursors为0):
  13. 硬解析时的(每测前用alter system flush shared_pool清空共享池)

  14. 硬解析        :                 1        2        12                13                     33
  15. 第一次软解析:                0        1        4                  4                       11
  16. 第二次软解析:                0        1        4                  2                        6
  17. (第三次软件的结果同第二次)


  18. 利用脚本2查看硬解析或不在循环中共享游标的情况(session_cached_cursors为50):
  19. 硬解析时的(每测前用alter system flush shared_pool清空共享池)

  20. 硬解析        :                 1        2        12                13                    33
  21. 第一次软解析:                0        1        6                  4                      11
  22. 第二次软解析:                0        1        2                  2                        4
  23. 第三次软解析:                0        1        0                  2                        2
  24. (第四次软件的结果同第二次)
复制代码

根据测试结果可以看到,很难猜测到Library cache Lock/Pin Latch以及Library cache闩的作用。不过,通过实验,比较肯定的有两点发现:
1、ORACLE在循环中共享游标执行计划时,所需要的Latch更少。而同样是软解析,在非循环中需要更多的Latch。
2、Open cursor操作应该只是在PGA中为私有游标区分配空间,并没有操作共享SQL区。因此在循环中打开游标,和在循环之外打开游标,Latch的次数是一样的。
3、即使session_cached_cursors为0,当在循环中共享执行计划时,应该也会缓存游标。

[ 本帖最后由 晶晶小妹 于 2008-6-24 09:40 编辑 ]

使用道具 举报

回复
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
14#
发表于 2008-6-24 09:19 | 只看该作者
今天早上在想这类锁的实现方式,可能非常地简单,一种具体的锁类型本身(比如null类型,比如share类型)甚至可以不需要排队。 但为了维护 null、share、exclusive 之间的制约关系以满足ddl和编译的需要,同时保护这个内存结构数据不遭遇破坏(比如两个进程要更新同一个共享内存中的变量必需要互斥进行),又要采用轻量级 latch 来保护这个锁本身。

oracle这里将锁和latch的模糊化了,实际上这里是有锁又有latch,latch是保护这个锁的,获得 latch就是为了获得锁,获得锁之前必须先获得latch,所以才导致我们经常在理解这个概念的时候陷入困境。


latch 和 lock 随着发展,在中间地带肯定是模糊化了,重量级的 latch 和轻量级的lock 越来越靠近。 这两个lock是一种轻量级的锁,单还需要latch来保护。实际上我们在应用层的锁算是重量级的锁,因为一般还包含了数据块的修改在里面。应用层的锁的内存信息也有latch在保护,但由于太重量了,一般我们是看不到这个latch等待信息的,只有在事务超级繁忙情况下才可能发现这种latch等待。

[ 本帖最后由 biti_rainy 于 2008-6-24 09:23 编辑 ]

使用道具 举报

回复
论坛徽章:
38
2010新春纪念徽章
日期:2010-01-04 08:33:082012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:25版主2段
日期:2012-05-15 15:24:11优秀写手
日期:2013-12-18 09:29:08马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
15#
发表于 2008-6-24 10:30 | 只看该作者
Buffer cache的内存组织非常简单,就是块。而库缓存池则不同,库缓存池中可以有各种大小不一的对象。而且这些对象通常还包含大小不一的部分。为了便于管理,Oracle将库缓存中对象的各种不同部分分了一下类,为每一类分别编号,这就是库缓存中的子堆。例如6号子堆专门存放执行计划,1号子堆一般是SQL*Plus代码的源码,等等。而每一个库缓存对象都可以包含多个类型的子堆,为了方便管理,再专门设个0号子堆,保存依赖表等重要信息和其他各个子堆的指针。另外还有就是对象的名称、Lock owners、Lock waiters和Pin owners和Pin waiters等等信息本来也可以放进0号子堆中的,但是为了提高并发性,ORACLE将这些信息放进另外一块内存,这块内存不再叫做“子堆”,而称为对象句柄,通常对象句柄中保存有0号子堆的地址。0号子堆和句柄中的信息其实都属于管理库缓存对象本身的管理性信息,本可以放在一起,但是分成两块可以提高并发性。而通常要想访问0号堆,要先访问句柄,其实就是从句柄中读取0号堆地址这个操作就是Library cache lock。ORACLE在Library cache lock操作期间,完成访问相关信息、取0号堆地址等操作。而Library cache lock操作由很多行构成,ORACLE需要用闩来保证此操作的原子性,这个闩应该就是Library cache latch和Library cache lock latch。Library cache pin也一样,Library cache pin对应一段代码,为了保证此段代码的原子性,Library cache pin latch就派上用场了。也就是说,Library cache lock/pin是用来完成某种操作的一段代码,而它俩相应的闩,就是用来保护这段代码可以不被打扰的执行。


根据我的试验,PGA中有时也记有常用对象的0号堆地址,根据最后一次实验的结果可以看到,当第三次软解析后,V$librarycache的Gets变为0,Pins为1。而且Library cache lock latch也变为0,Library cache pin和Library cache lathc还每次增加2。Gets就是读句柄的次数,它变为0,就是不再到句柄中读堆0的地址,可以直接访问堆0等子堆。因此,在会话的PGA中,肯定是记录了堆0的地址。但是,虽然不再需Library cache lock latch,但还是需要Library cache闩,我认为这可能是还要将进程信息写进句柄的Lock owners或Pin owners中,持有Library cache闩,是保护这个写操作的(但是没有读句柄,所以Library cache lock latch和V$librarycache中的Gets都没有增加)。

[ 本帖最后由 晶晶小妹 于 2008-6-24 10:32 编辑 ]

使用道具 举报

回复
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
16#
发表于 2008-6-24 11:05 | 只看该作者
“Library cache lock/pin是用来完成某种操作的一段代码,而它俩相应的闩,就是用来保护这段代码可以不被打扰的执行”

我感觉这样描述只会让不清楚的人更不清楚,尤其自己不够强大的时候。我喜欢描述我们希望实现什么目的,oracle应该怎样做,最后才是oracle就是这么做的。这样引导似的表述容易让人理解,而平铺直叙似的大段表述很枯燥, 引入与主要表达意思不直接的内容越多越容易让人糊涂。


那么,我的看法是:
Library cache lock 是一种锁,要获得这个锁,必须在获得的过程中不被打断并且禁止其他进程来同时获得,因为不这样可能会使得锁的完整性和正确性被破坏(比如两个进程在share和exclusive之间一定要串行)。 所以获得锁的过程需要latch来保护。 但是一旦获得锁,latch的使命也就完成了。 latch使命的完成不意味着锁一定结束,锁可能依然存在(比如null类型锁会一直存在,exclusive类型应该要跟随latch而消失)



btw: 已经差不多一年多没摸数据库了,纯粹做想法上的探讨,不去做实验来检验了。

使用道具 举报

回复
论坛徽章:
47
蒙奇·D·路飞
日期:2017-03-27 08:04:23马上有车
日期:2014-02-18 16:41:112014年新春福章
日期:2014-02-18 16:41:11一汽
日期:2013-09-01 20:46:27复活蛋
日期:2013-03-13 07:55:232013年新春福章
日期:2013-02-25 14:51:24ITPUB 11周年纪念徽章
日期:2012-10-09 18:03:322012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20
17#
发表于 2008-6-24 12:22 | 只看该作者
原帖由 biti_rainy 于 2008-6-23 07:01 发表
为什么是2
是不是一个handle对应的object分为两部分,在两个heap中? 如果这样可能跟object大小相关,object非常大被分在很多heap中的时候是不是就是多个pin。

另外一种假设,你的猜测是不是和两个base table相关,你可以做一个view来测试,或者分别是好用2、3、4个base table的 动态视图 来测试。


I proved the second hypothesis (mine) to be wrong. I ran these SQLs (216 is library cache pin latch):

select kslltwgt from x$ksllt where kslltnum = 216;
select kslltwgt from x$ksllt where kslltnum = 216;
select kslltwgt from x$ksllt where kslltnum = 216;
...

and library cache pin latch gets still go up by 2 for each run. If I run these
select * from x$kslld where KSLLDNAM = 'library cache pin';
select kslltwgt from x$ksllt where kslltnum = 216;
[repeat]

or
select 1 from dual;
select kslltwgt from x$ksllt where kslltnum = 216;
[repeat]

it goes up by 4 every time. So each execution of any SQL takes 2 library cache pins. I think the first hypothesis may be correct. Each SQL has heap 0 and heap 6 so each of them needs 1 pin. If I run PL/SQL, I may get more pins because it has other heaps.

Yong Huang

使用道具 举报

回复
论坛徽章:
38
2010新春纪念徽章
日期:2010-01-04 08:33:082012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:252012新春纪念徽章
日期:2012-02-13 15:12:25版主2段
日期:2012-05-15 15:24:11优秀写手
日期:2013-12-18 09:29:08马上有车
日期:2014-02-19 11:55:14马上有房
日期:2014-02-19 11:55:14
18#
发表于 2008-6-24 14:59 | 只看该作者
哈哈,难得大师这么有兴致。这些内部的东西,其实很难证明,不过这样讨论,对理清自己的思路,还是有很大帮助的。
我为什么说Library cache lock/pin都是一种操作呢!主要还是有很多资料中都提到Library cache lock不但是锁,还要在内存中定位对象。而Pin,如果对象所需数据不在内存中,则会加载该对象的数据。这也就是说,Library cache lock除了锁,还有定位的功能,Library cache Pin除了锁,也还有加载的功能。因此,我觉得它们两个不是但纯的锁,还包含操作。而与它们两个对应的闩,则是保护它们两个的操作可以原子性的执行。

使用道具 举报

回复
论坛徽章:
8
ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:442009日食纪念
日期:2009-07-22 09:30:002010新春纪念徽章
日期:2010-01-04 08:33:082010新春纪念徽章
日期:2010-03-01 11:19:072011新春纪念徽章
日期:2011-01-04 10:37:10ITPUB十周年纪念徽章
日期:2011-11-01 16:21:15ITPUB 11周年纪念徽章
日期:2012-10-09 18:06:202013年新春福章
日期:2013-02-25 14:51:24
19#
发表于 2008-6-24 15:10 | 只看该作者
难得几个高手都在一起讨论实现方式
我一定仔细看完

使用道具 举报

回复
论坛徽章:
86
ITPUB元老
日期:2005-02-28 12:57:002012新春纪念徽章
日期:2012-01-04 11:49:542012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:202012新春纪念徽章
日期:2012-02-13 15:13:20咸鸭蛋
日期:2012-05-08 10:27:19版主8段
日期:2012-05-15 15:24:112013年新春福章
日期:2013-02-25 14:51:24
20#
发表于 2008-6-24 15:33 | 只看该作者
原帖由 晶晶小妹 于 2008-6-24 14:59 发表
哈哈,难得大师这么有兴致。这些内部的东西,其实很难证明,不过这样讨论,对理清自己的思路,还是有很大帮助的。
我为什么说Library cache lock/pin都是一种操作呢!主要还是有很多资料中都提到Library cache lock不但是锁,还要在内存中定位对象。而Pin,如果对象所需数据不在内存中,则会加载该对象的数据。这也就是说,Library cache lock除了锁,还有定位的功能,Library cache Pin除了锁,也还有加载的功能。因此,我觉得它们两个不是但纯的锁,还包含操作。而与它们两个对应的闩,则是保护它们两个的操作可以原子性的执行。


如果是一种操作,那你可以定义为动词。 但是如果你当作一个名次来看待,就有点差异。

Library cache lock  是一种lock,包含了操作,也包含了操作所留下的状态,所以不仅仅是操作。


至于pin ,pin有命中不不命中的问题,不命中则产生 reloads , 这也就是计算 share pool命中率的一个重要计算公式: 根据 reloads 和 pin 来计算命中率,100*sum(pins-reloads)/sum(pins)   。  为什么产生reloads,是因为 share pool 刷新导致 handle 在而 body 不在了,所以需要 reloads。  library cache lock本来就是获得 handle 并放一个 锁标志的过程,获得 handle(指针) 就是为了获得object本身,这就是一个真正执行使用的过程。  如果你要讲  “还有定位功能”  那实际上在理解上偏差就大了!  这个工作的目的就是为了 寻找到object并使用object,所谓 lock也好 pin也好,这才是这个功能实现的一个辅助手段。  这不是 “还有这个功能”,这才是根本目的。

[ 本帖最后由 biti_rainy 于 2008-6-24 15:36 编辑 ]

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

TOP技术积分榜 社区积分榜 徽章 团队 统计 知识索引树 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 未成年人举报专区 
京ICP备16024965号-8  北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表