欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

OCP知识点讲解 之 队列、资源与锁

程序员文章站 2022-05-26 11:33:57
...

一、队列与共享资源共享资源可以被多个会话、进程同时访问,因此它的访问需要保护。Oracle中,除了PGA,所有的东西(包括内存、磁盘、CPU、表、索引、事务等等,

一、队列与共享资源

共享资源可以被多个会话、进程同时访问,因此它的访问需要保护。Oracle中,除了PGA,所有的东西(包括内存、磁盘、CPU、表、索引、事务等等,种类太多,网站空间,一概用东西两字来代表)都是共享资源。多个进程或会话对共享资源操作时,就需要排队。这里所需要排的队就是队列(Enqueue)。访问不同的共享资源,需要排不同的队。可以这样说,有多少种队列,就有多少种需要保护的共享资源。队列的名字一般是两个字节构成,如TM,TX,JQ,……。具体所有队列的种类、名字,参见V$LOCK视图介绍中的附表。


二、队列标识

我们以TM为例,它是DML队列锁。在对表作DML操作时,需要先在此排队,正式点的说法是:需要先获得TM队列锁。TM也被称作表锁,因为它主要是在对表作操作是获得的。如果数据库中有1000个表,针对这一千个表,并非只有一个队列,要是这样的话也不太合理。1000个表,就应该有1000个TM队列,这样才附合常理。如果一千个队列都叫TM,将来操作时不好区分,因此,需要为这一千个TM队列分别名命,这个名字,也被称为队列标识。TM队列的命名格式为:TM-OID-0。其中OID是Object ID,即对象ID。最后一部分一般都是0。假如AA表的OID是6636,它的队列标识就是TM-6636-0。

每种队列的命名格式各不相同,总的来说是“队列名-ID1-ID2”,ID1和ID2分别是两个参数,对于TM队列来说,ID1是OID,ID2为0。


三、资源结构

继续我们上面的假设,如数据库中有一千个表,这就要对应一千个TM队列。但只有当操作到哪个表了,才会为它建立相关的队列信息。比如会话发布了对AA表的更新操作,需要在SGA中为AA建立相关的TM队列信息。这些相关AA的TM信息,也被称为“资源结构”(KSQRS,KSQ是内核服务队列的简写,RS是Resource Structure的简写,即资源结构)。每一个资源结构维持一个所有者、等待者和转换者的列表。如下图:

OCP知识点讲解 之 队列、资源与锁

资源结构前的即是队列标识,也可以作为资源结构标识(资源标识)。

每一个所有者、等待者和转换者有一个锁结构(Ksqlk),简单点说每一个所有者、等待者和转换者有一个链表,此链表由会话、锁模式等信息构成,网站空间,具体描述了什么会话以什么模式获得此资源结构。具体如下:

1)如果会话获得锁,锁结构将在所有者列表上

2)如果会话正在等待获得锁,锁结构将在等待者列表上

3)如果锁已被获得,但会话正在等待它被转换到一种不同的模式,锁结构将在转换者列表上

所有资源结构组成一个资源表,资源表和资源结构上的锁都被分配在SGA中。资源表中总的行数由初始化参数ENQUEUE_RESOURCES决定,且资源表中的行可以在X$KSQRS中被看到。正在被使用的将在V$RESOURCE中显示。还可以在v$resource_limit中看到资源结构数量的限制和使用情况:

sid=9 pid=10> select * from v$resource_limit where resource_name = 'enqueue_resources';

RESOURCE_NAME CURRENT_UTILIZATION MAX_UTILIZATION INITIAL_ALLOCATION LIMIT_VALUE

------------------------------ ------------------- --------------- -------------------- -------------

enqueue_resources 32 32 968 UNLIMITED

可以看到,当前使用了32个资源结构,最多时使用了32个资源结构,初始化参数中分配了968个资源结构。最多使用是UNLIMITED,没有限制。由于Oracle 9i采用的算法,我们在X$KSQRS中看到的总行数并不是968,而是992。为确保重用,资源表中未用的资源结构被放置在一个连接列表,称为:Resource Free List。我们可以发布一些更新声明,不要提交,这样占用的TM、TX资源结构一直不会释放。观察X$KSQRS,TM资源结构的占用增多,但视图的总行数不变,还是992。新增的TM、TX资源结构占用了其他已经释放的资源结构。


四、资源结构哈希表

为了在资源表中快速找到某一资源结构,Oracle当然还是要使用HASH算法。Oracle根据资源标识计算HASH值。当然,和Library cache一样,资源表中已被占用的资源结构的HASH值构成了一个个HASH Buckut。

OCP知识点讲解 之 队列、资源与锁

上图就是HASH Bucket和资源结构的图,可以看到和Library cache中的很像。HASH算法吗,所有的HASH算法都会有很多共同点。从上图中可以看到,想访问Hash Bucket,需要Enqueue hash chain闩,它需要保护上图中的HASH表,和每个Hash Bucket后的Hash链。它的数量由隐含参数_enqueue_hash_chain_latches控制。Enqueue hash chain闩类似于Buffer cache chain闩。它们都是一个闩要管理多个哈希桶,不过Enqueue hash chain更特殊,在单CPU环境中,只有一个,却要管理所有的哈希桶,这是因为队列的争用,毕竞比Buffer要小的多。

Oracle中所有关于HASH的算法,都要有HASH表、HASH链和保护HASH链的闩,网站空间,HASH表不需要保护,这是因为HASH表是大小固定的数组。每一个数组元素就是一个Hash Bucket。每个哈希桶的哈希值也都是事先定好的。因此不存在对哈希桶的更改,如插入一个哈希桶、修改一个哈希桶的哈希值或删除一个未使用的哈希桶等等,这些操作都是不存在的。因此,既然不会有修改操作,哈希表就不需保护。需要保护的是每个哈希桶后的链。每个桶后的链中,都可以挂多个对象,我们可能向链上添加或删除对象,既然有修改,就需要保护。

队列资源Hash表的长度由_enqueue_hash控制,其始值来源于SESSION参数,初始是375。我们的资源表共有992行,而哈希桶只有375个,这必然会有多个资源结构排在某一个哈希桶后面。如果曾经增加过ENQUEUE_RESOURCES的值,也就是说,资源结构比系统默认的还要更多一些,但控制哈希表长度的_enqueue_hash参数值如果不跟着增加。这就意味着每个哈希桶下要挂接更多的资源结构,这有可能因起Enqueue hash chain闩的竞争。如何观察闩的使用情况这是下一章节的内容,这里就不多说了。_enqueue_hash的初始值是根据Sessions参数来定的,计算公式如下:((sessions-10)*2)+55,默认 ((170-10)*2)+55,正好等于375,它并不随ENQUEUE_RESOURCES的增加而增加。

OCP知识点讲解 之 队列、资源与锁

队列、资源结构和锁结构的关系如上图。上图是分别在两个会话中发布如下声明后的结果:

在会话10:sid=10 pid=11> insert into a1 values(1,1,1);

已创建 1 行。

在会话12:sid=12 pid=12> insert into a1 values(2,2,2);

已创建 1 行。

查看哈希表视图:

sid=9 pid=10> select * from v$resource where type ='TM';

ADDR TY ID1 ID2

-------- -- ---------- ----------

7B6D5C40 TM 6657 0

可以看到,有一个TM队列,地址是7B6D5C40,对象ID是6657,这个正是A1表。

查看V$LOCK视图:

sid=13 pid=13> select * from v$lock where sid>=8;

ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK

-------- -------- ---------- -- ---------- ---------- ---------- ---------- ---------- ----------