ITPUB??ì3
ITPUB论坛 » Oracle专题深入讨论 » library cache latch 只有一个么?

标题: library cache latch 只有一个么?
离线 fxyj2008
一般会员



精华贴数 0
个人空间 0
技术积分 161 (11179)
社区积分 0 (884258)
注册日期 2006-4-25
论坛徽章:0
      
      

发表于 2007-11-19 17:43 
library cache latch 只有一个么?

在data buffer 中 ,我们知道有一个 hash buckets 来管理内存 ,即对每个块做hash映射 ,然后hash相同得块都在一个桶中,并且hash相同得块
用链表来连接 ,然后保护这些链表得latch 就叫做 cache buffers chains,

按我得理解 ,那么每个hash桶中都有一个 cache buffers chains latch ,查询v$latch_children ,确实有多个  cache buffers chains latch 得
,基本得数据结构如下:


typedef struct hash_buckets
(
  long hash_value;
  char cache_buffers_chains_latch; // 定义 latch
  struct cache_buffer_chains  *head;  //存放cache buffers chains得首地址
  .......  //其他字段
) hb;

typedef struct
(
  char  real_address[32];  
  struct  cache_buffer_chains *next;  //存放下一个节点地址
  struct  cache_buffer_chains *pre; //上一个节点地址
  struct block_head * bh ; //存放得对应得block 头部
  ....... //其他字段
)cache_buffer_chains;


那么我数据库刚起来得时候 ,读参数文件 ,然后分配共享内存 ,然后是初始化hash bucket;其实就是结构数组得初始化吧

使用某个块得时候 ,应先进行hash映射 ,找到 相应得 struct cache_buffer_chains  *head ,然后上latch ,
其实就是一个变量,通过机器指令来做得 ,比如 testandset 类似得指令 ,改指令在一个指令周期内执行得,因此不会被中断,因此该进程也就不可能
被切换,查到相应得块后 ,再 置为 0 就可以了  。



但是再share_pool 中得分配我却不是想得很明白 ,当我们提交一条sql得时候 ,如果没有对应得hash 值 ,需要做 parsing ,在 解析得过程中肯定是需要对这个结构上
library cache latch 得 ,但我查询v$latch_children 时为什么 只有一个值呢 ,按我得理解,应该一个 hash 值对应一个library cache latch 才对 ,即一条sql 对应
一个library cache latch 才对阿 ,这样才可以提高并发程度 ,否则一条sql 在解析得时候 ,那么其他sql 不是都不能解析么?
查了一下
KSPPINM                        KSPPSTVL                                                                                                               
------------------------------ ------------------------------                                                                                         
_kgl_latch_count               0      

这个参数 ,结果是0 ,为什么oracle 默认是0 呢? 我这边是一个CPU得。

因此我想问 ,一条sql 是对应一个 library cache latch  呢 ,还是多个 sql 只用 一个library cache latch ;
其实library cache latch  应该就是一个变量,只不过设置和测试得时候用得是原子指令。

还有 share_pool 里面得内存得数据结构到底是怎么样得 ? 可否用C 描述一下呢 ?
不胜感激阿!!!


只看该作者    顶部
离线 jinshen1979
奥尔口


来自 武汉
精华贴数 0
个人空间 0
技术积分 154 (11648)
社区积分 13 (9272)
注册日期 2007-1-14
论坛徽章:6
生肖徽章2007版:猴生肖徽章2007版:牛生肖徽章2007版:鸡生肖徽章2007版:虎生肖徽章2007版:兔生肖徽章2007版:鼠
      

发表于 2007-11-20 20:20 
沙发中,楼上研究的比较高深,我也望尘莫及了,顶一下,帖子不要沉下去,还会有高人指点的


__________________
他人即陷阱
┣━MSN:jinshen979@hotmail.com
┣━QQ  :46180893                 
只看该作者    顶部
离线 Yong Huang
版主



精华贴数 2
个人空间 0
技术积分 3994 (347)
社区积分 120 (3013)
注册日期 2001-10-9
论坛徽章:6
现任管理团队成员ITPUB元老管理团队2006纪念徽章会员2006贡献徽章授权会员2008年新春纪念徽章
      

发表于 2007-11-21 12:15 


QUOTE:
原帖由 fxyj2008 于 2007-11-19 17:43 发表
但是再share_pool 中得分配我却不是想得很明白 ,当我们提交一条sql得时候 ,如果没有对应得hash 值 ,需要做 parsing ,在 解析得过程中肯定是需要对这个结构上
library cache latch 得 ,但我查询v$latch_children 时为什么 只有一个值呢 ,按我得理解,应该一个 hash 值对应一个library cache latch 才对 ,即一条sql 对应
一个library cache latch 才对阿 ,这样才可以提高并发程度 ,否则一条sql 在解析得时候 ,那么其他sql 不是都不能解析么?
查了一下
KSPPINM                        KSPPSTVL                                                                                                               
------------------------------ ------------------------------                                                                                         
_kgl_latch_count               0      

这个参数 ,结果是0 ,为什么oracle 默认是0 呢? 我这边是一个CPU得。

因此我想问 ,一条sql 是对应一个 library cache latch  呢 ,还是多个 sql 只用 一个library cache latch ;
其实library cache latch  应该就是一个变量,只不过设置和测试得时候用得是原子指令。

Every SQL has a library cache latch managing it. The child latch number is shown in v$sql.child_latch (before 9i, you have to dump library cache to get that child latch number). Obviously, each library cache latch child can manage multiple SQLs.

_kgl_latch_count defaults to 0 meaning Oracle creates certain number of KGL latches based on the number of CPUs (more accurately, the setting of _cpu_count which you can change too if you really want). One CPU gives you one latch. Multiple CPUs give you next prime number of the number of CPUs. When you have only 1 CPU, it makes no sense to have 2 latches because only one SQL can be parsed at one single point of time anyway.

Regarding your description of cache buffers chains and buckets, I always thought the concepts of buckets and chains are the same. Could it possible they actually are one struct instead of two?

Yong Huang


只看该作者    顶部
离线 yxyup
木易大夫


精华贴数 5
个人空间 1902
技术积分 10487 (113)
社区积分 361 (1639)
注册日期 2006-5-21
论坛徽章:35
现任管理团队成员红孩儿    
      

发表于 2007-11-22 09:23 
学习


__________________
克制浮燥,虚心学习!

欢迎访问我的博客:http://123ok.cublog.cn/ ;   http://space.itpub.net/7364032/

投入多少,收获多少;投入多深,领悟多深。
太阳底下没有新鲜事,排列组合就是创新。
每天多做一点点,就是进步的开始。
每天进步一点点,就是成功的开始。
每天创新一点点,就是领先的开始。
只看该作者    顶部
离线 fxyj2008
一般会员



精华贴数 0
个人空间 0
技术积分 161 (11179)
社区积分 0 (884258)
注册日期 2006-4-25
论坛徽章:0
      
      

发表于 2007-11-22 16:00 
多谢Yong Huang 得回复

后来我又看了 eygle 的关于shared pool的深入探讨 相关的文章

后来把library cache 内存里面的东西dump 出来看了一下 ,稍微有点头绪

在share_pool 里面的空间管理也是通过 hash buckets (hash 桶)来实现的 ,其实以前我们在学操作系统的时候 ,一般内存管理都是通过
一个链表来管理的 ,比如说空闲内存的链表 ,整个链表按空闲内存的大小进行排序 ,当我们要找一个空闲内存的时候 ,然后给链表上锁 ,搜索整个
链表,直到找到一个适合自己的 ,然后将该节点摘下 ,减去需要的内存后,再把该节点重新插入到 整个 链表中 ,其实就是再排序了 ,这样的话可能会造成
碎片的增多,就就造成链表长度的增长 ,使查询效率降低 ,所以操作系统中过段时间需要合并内存碎片,一个是可以申请更大的内存区域 ,还有就是减少查找
次数。

但是oracle 里面使用了更好的方法来管理share_pool ,因为sql 的内存申请一般比较小,通常都是只有几k ,如果纯粹使用链表来管理 ,那势必会极大的降低并发性能
,因此可以使用 hash buckets 来管理 ,每一个桶里面放一定大小的空闲空间,当要申请空间的时候,先做hash 映射 ,找到该桶,然后再搜索链表,C描述如下:

typedef  struct
(
   int size ; //    该桶内放的空闲内存的大小(其实是范围)
   struct  free_mem * head ;
  ..... //其他字段
)hash_buckets;

char  share_pool_latch ; //保护内存分配的latch

当数据库刚起来的时候 ,先初始化结构数组

struct hash_buckets[N] ; //可能每个数据库版本初始化的结构数组都不同。如9i的就比8i的多

初始化以后,刚开始肯定空闲空间都比较大 ,但数据库运行一段时间后 ,就会出现碎片,比如说 hash_buckets[1] 里面放的是 14k~20k 的空闲块  ,
hash_buckets[2] 里面放的是 21k~27k 的空闲块,现在需要申请一个 26k的空闲块了 ,那可以先对空闲块大小做映射 ,然后找到hash_buckets数组,然后再找到
相关链表的头部;

比如说分配内存可能会有如下代码:
int * mallc(int mallc_size)
{
  ..........
struct free_mem *head;
  int hashvalue=hash_map(mallc_size); //根据需要分配的大小做hash映射 成 数组下标
while(1)
{
    if(count>N)  // 假如尝试的次数大于某个数值时
       return null;
    testandset(share_pool_latch) ; //内存分配的临界区
   if(error)      //这边testandset机器指令的执行结果应该存在CPU某个寄存器中
   sleep(3) //比如这边休息3秒 ,3秒后再由操作系统放入运行队列中 .也就是说明 willing-to-wait 什么的
   count++;  //失败的次数
}
head=hash_buckets[hashvalue].head;
  for( ;head
  {
    head=head->next;
     .......
  } //直到找到合适自己的 ,如果减去自己需要申请的 ,还需要把剩余空闲节点放到相应的hash_bucket 中去

  。。。。。。。
  testandclear(share_pool_latch);
}
如果说每个运行的oracle 进程都会有上面一个代码影像 ,那么在windows 中还比较好考虑,因为在windows 里面都是以线程跑的 ,所以 char  share_pool_latch ; 这个变量是所以线程共享的 ,但如果在unix 中呢? 每个连接都是以进程方式跑的,如果每个进程都有一个share_pool_latch 变量的拷贝 ,那么testandclear() 这个指令就不起作用的 ? 在unix 中难道 share_pool_latch  这个变量是由操作系统来管理的 ? 那么对每个变量的操作就需要系统调用 ,势必会浪费不少时间(进程的上下文切换以及。。。) ,还是将mallc 函数封装在 so ,即动态连接库中 ? 这样就可以有一份变量拷贝?  // 这边是一个疑问? who knows?



上面是空间的管理 ,然后就是涉及到library cache 中的 object 的管理 ,似乎oracle 中很多都是通过hash buckets 来管理的 ,而不是有纯粹的链表形式,这样能
增加并发性吧

基本数据结构如下:

typedef struct
(
   ......;
   strcut LIBRARY_OBJECT_HANDLE * head ; //这边的handle 翻译成句柄 ,一直不明白为什么解释成这样,打开一个文件的时候有个文件句柄,就理解成指针吧
  ........
)lib_cache_hash_buckets;

typedef  struct
(
   char *  name ;
  char*  hash;
   char * namespace;
    //char  lock=0 pin=0 latch#=1  ???
   ..................
  struct children_LIBRARY_OBJECT_HANDLE [N] ; //存放副本
  struct data[N] ;  //
   ......... //这个struct 中应该还有 union 结构,因为不仅存放sql ,还有存储过程,触发器之类的东西,用union 可以节省内存
) LIBRARY_OBJECT_HANDLE ;


children_LIBRARY_OBJECT_HANDLE  存放的就是这个sql 的副本 ,也有很多人称呼

LIBRARY_OBJECT_HANDLE  为 sql header , children_LIBRARY_OBJECT_HANDLE  为sql body
一个header 有多个 body ,因为sql 可能相同,但查询的表可能属于不同的用户,所以会有多个版本 ,似乎v$sqlarea 的version_count 来记录这个的

在每个body 中存放的是执行计划,还有什么?? //这边不清楚???

还有在 sql header 中存放的data  里面的数据到底是什么???

如何根据一条sql映射到相应的hash_bucket ,其实就是如何找到 LIBRARY_OBJECT_HANDLE  ???
我这边有一个现象,我两条相同的sql 映射到不同的 hash_bucket 上了


如下:
BUCKET 40886 total object count=1
BUCKET 41078:
  LIBRARY OBJECT HANDLE: handle=671ef69c
  name=select * from t
  hash=45b47d9c timestamp=11-22-2007 11:04:49
  namespace=CRSR flags=RON/TIM/PN0/SML/[12010000]
  kkkk-dddd-llll=0000-0001-0001 lock=0 pin=0 latch#=1
  lwt=671EF6B4[671EF6B4,671EF6B4] ltm=671EF6BC[671EF6BC,671EF6BC]
  pwt=671EF6CC[671EF6CC,671EF6CC] ptm=671EF724[671EF724,671EF724]
  ref=671EF6A4[671EF6A4, 671EF6A4] lnd=671EF730[671EF730,671EF730]
    LIBRARY OBJECT: object=671ef424
    type=CRSR flags=EXS[0001] pflags= [00] status=VALD load=0
    CHILDREN: size=16
    child#    table reference   handle
    ------ -------- --------- --------
         0 671ef5e0  671ef340 671ee4ac
    DATA BLOCKS:
    data#     heap  pointer status pins change    alloc(K)  size(K)
    ----- -------- -------- ------ ---- ------     -------- --------
        0 671ef62c 671ef4ac I/-/A     0 NONE       0.80     1.09


BUCKET 116770:
  LIBRARY OBJECT HANDLE: handle=6740d778
  name=select * from t
  hash=f3f74e27 timestamp=11-22-2007 09:56:51
  namespace=CRSR flags=RON/KGHP/TIM/PN0/SML/[12010000]
  kkkk-dddd-llll=0000-0001-0001 lock=N pin=0 latch#=1
  lwt=6740D790[6740D790,6740D790] ltm=6740D798[6740D798,6740D798]
  pwt=6740D7A8[6740D7A8,6740D7A8] ptm=6740D800[6740D800,6740D800]
  ref=6740D780[6740D780, 6740D780] lnd=6740D80C[6740D80C,6740D80C]
    LIBRARY OBJECT: object=6740d500
    type=CRSR flags=EXS[0001] pflags= [00] status=VALD load=0
    CHILDREN: size=16
    child#    table reference   handle
    ------ -------- --------- --------
         0 6740d6bc  6740d41c 6740d1fc
         1 6740d6bc  6740d45c 673e611c
    DATA BLOCKS:
    data#     heap  pointer status pins change    alloc(K)  size(K)
    ----- -------- -------- ------ ---- ------     -------- --------
        0 6740d708 6740d588 I/P/A     0 NONE       0.86     1.09

?????


to: Yong Huang


Obviously, each library cache latch child can manage multiple SQLs.

从哪儿可以看出呢 ?
那oracle 如何区分多个
library cache latch呢 ? 不同的变量? 或者说是这个latch 是直接放在struct 中的 ?
这样的话就是每个sql 都有一个惟一的 latch ?
可否用相应的数据结构描述一下? 谢谢



Regarding your description of cache buffers chains and buckets, I always thought the concepts of buckets and chains are the same. Could it possible they actually are one struct instead of two?


这应该是两个struct ,hash_bucket 是用来快速定位的 ,因为是根据数组的下标来搜索的 ,那么得到一个地址很容易
数组首地址+偏移量找到相应的 bucket ,然后根据bucket 来访问 链表。


只看该作者    顶部
离线 cc59
Love oracle



精华贴数 0
个人空间 326
技术积分 10643 (109)
社区积分 13738 (104)
注册日期 2004-8-13
论坛徽章:65
现任管理团队成员欧洲冠军杯纪念徽章海蓝宝石红宝石2008北京奥运纪念徽章:拳击2008北京奥运纪念徽章:篮球
体育版块博采纪念徽章2008北京奥运纪念徽章:自行车2008北京奥运纪念徽章:沙滩排球2008北京奥运纪念徽章:柔道2008北京奥运纪念徽章:皮划艇激流回旋2008年新春纪念徽章

发表于 2007-11-22 19:34 
这个问题我想可能只有oracle公司的开发人员能回答您了.


__________________
My blog: tuning rac and using parallel


msn:liuyi8903@hotmail.com
只看该作者    顶部
离线 zhuojm
资深会员



精华贴数 0
个人空间 0
技术积分 1150 (1515)
社区积分 35 (5693)
注册日期 2005-12-12
论坛徽章:6
授权会员数据库板块每日发贴之星数据库板块每日发贴之星数据库板块每日发贴之星数据库板块每日发贴之星数据库板块每日发贴之星
      

发表于 2007-11-23 00:15 
关注。


__________________
努力冲击1000.
只看该作者    顶部
离线 fxyj2008
一般会员



精华贴数 0
个人空间 0
技术积分 161 (11179)
社区积分 0 (884258)
注册日期 2006-4-25
论坛徽章:0
      
      

发表于 2007-11-23 12:59 
回答自己的一个问题 ,自己傻了

但如果在unix 中呢? 每个连接都是以进程方式跑的,如果每个进程都有一个share_pool_latch 变量的拷贝 ,那么testandclear() 这个指令就不起作用的 ? 在unix 中难道 share_pool_latch  这个变量是由操作系统来管理的 ? 那么对每个变量的操作就需要系统调用 ,势必会浪费不少时间(进程的上下文切换以及。。。) ,还是将mallc 函数封装在 so ,即动态连接库中 ? 这样就可以有一份变量拷贝?  // 这边是一个疑问? who knows?

unix 中都是通过共享内存来的 ,所以变量当然只有一份拷贝 (latch 是放在共享内存里的),否则怎么会有sga 这个名字呢


只看该作者    顶部
离线 hanjs
高级会员


精华贴数 1
个人空间 0
技术积分 9564 (123)
社区积分 51 (4729)
注册日期 2006-7-30
论坛徽章:15
会员2007贡献徽章蓝色妖姬嫦娥授权会员数据库板块每日发贴之星数据库板块每日发贴之星
2008年新春纪念徽章生肖徽章2007版:鸡生肖徽章2007版:鼠ITPUB新首页上线纪念徽章生肖徽章:蛇生肖徽章:兔

发表于 2007-11-24 18:27 
lz怎么知道人家结构怎么定义的啊?


__________________
Database Concepts
Database Performance Tuning Guide and Reference
只看该作者    顶部
离线 Yong Huang
版主



精华贴数 2
个人空间 0
技术积分 3994 (347)
社区积分 120 (3013)
注册日期 2001-10-9
论坛徽章:6
现任管理团队成员ITPUB元老管理团队2006纪念徽章会员2006贡献徽章授权会员2008年新春纪念徽章
      

发表于 2007-11-25 01:54 


QUOTE:
原帖由 fxyj2008 于 2007-11-22 16:00 发表
> Obviously, each library cache latch child can manage multiple SQLs.

从哪儿可以看出呢 ?
那oracle 如何区分多个
library cache latch呢 ? 不同的变量? 或者说是这个latch 是直接放在struct 中的 ?
这样的话就是每个sql 都有一个惟一的 latch ?
可否用相应的数据结构描述一下? 谢谢

> Regarding your description of cache buffers chains and buckets, I always thought
> the concepts of buckets and chains are the same. Could it possible they actually are one struct instead of two?

这应该是两个struct ,hash_bucket 是用来快速定位的 ,因为是根据数组的下标来搜索的 ,那么得到一个地址很容易
数组首地址+偏移量找到相应的 bucket ,然后根据bucket 来访问 链表。

You can see each library cache latch child manage multiple SQLs like this:

SQL> select child_latch, count(*) from v$sql group by child_latch;

CHILD_LATCH   COUNT(*)
----------- ----------
          1       1376
          2       1428
          3       1437

I don't understand the other part of your message.  Each child latch has a number. Oracle uses the SQL hash value to calculate the latch number. So each SQL will have a latch (i.e. it's not possible for a SQL to be not managed by any latch). But it's not that each SQL has its own unique latch; there wouldn't be that many. I don't know how to describe it in data structure.

Conceptually, I equate a hash bucket with a chain because they have a one-to-one relationship. Is that correct? I didn't go into details as you did. Perhaps when you go that deep, you do need to make a distinction between the two concepts.

Yong Huang


只看该作者    顶部
相关内容


CopyRight 1999-2006 itpub.net All Right Reserved.
北京皓辰广域网络信息技术有限公司. 版权所有
E-mail:Webmaster@itpub.net
京ICP证:010037号 联系我们 法律顾问