RAC 锁管理与锁问题的定位 一.docx

上传人:b****6 文档编号:6508020 上传时间:2023-01-07 格式:DOCX 页数:18 大小:337.15KB
下载 相关 举报
RAC 锁管理与锁问题的定位 一.docx_第1页
第1页 / 共18页
RAC 锁管理与锁问题的定位 一.docx_第2页
第2页 / 共18页
RAC 锁管理与锁问题的定位 一.docx_第3页
第3页 / 共18页
RAC 锁管理与锁问题的定位 一.docx_第4页
第4页 / 共18页
RAC 锁管理与锁问题的定位 一.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

RAC 锁管理与锁问题的定位 一.docx

《RAC 锁管理与锁问题的定位 一.docx》由会员分享,可在线阅读,更多相关《RAC 锁管理与锁问题的定位 一.docx(18页珍藏版)》请在冰豆网上搜索。

RAC 锁管理与锁问题的定位 一.docx

RAC锁管理与锁问题的定位一

RAC锁管理与锁问题的定位一

从我一到公司,主要工作就是维护我们的一套大RAC。

主库5个节点,备库最多时曾有4个节点,后来备库减至单实例了。

主、备一共8套存储,总间共300T空间。

内部互联采用业内最快的InifiniBand。

也算是豪华配置了。

最高峰时,主库数据130T左右,每天归档量巅峰时接近6T,是我见过的最大、最忙的数据库。

      库一大,很多本来不是问题的问题,就会变成问题。

比如数据字典维护,Oracle在这一块上做的很好,因为这是Oracle的根本。

这一块上罕有问题的。

但是,当数据库中有几百万个段时呢!

其实就算有几百万个段,Oracle也运行的好好的,在极偶然的情况下,会遇到问题。

还有控制文件,通常也就几十M,但当它接近1G呢,它就会像一个活火山一样,偶而爆发。

另外,还有更容易想到的,如备份的问题,搭建备库的问题等等。

如果一个库只有1T,搭建个备库只需要几个小时,但是上百T呢!

不但是时间问题,选择合适的方法是另一个需要考虑的问题。

      平时工作太忙,现在有时间了,慢慢和大家分享,总比烂在我的肚子里强。

      开始今天的正题,聊一聊RAC中的锁管理。

      大家一般对RAC中的CacheFusion比较熟悉,而对锁管理,讨论的不多。

其实,锁管理更为基础,因为块,或者更准确点,Buffercache中的Buffer,也是锁管理的对象之一。

好,下面我们开始。

一、      首先,了解一下RAC中要管理的锁的类型:

(一)、你在V$LOCK中看到的全部锁,这一部分我们可以称之为高级队列锁。

(二)、Librarycachelock/pin,还有Rowcachelock,这一部分我们称之为中级内存锁。

(中级内存锁还有一个,就是Bufferpin,它导致的竞争,就是我上遍文章中所讲的bufferbusywaits。

注意啊,想降低bufferbusywaits吗,哪就使用更快速的设备存放RedoFile吧。

详在中的第一遍日志,或在上个帖子中参加讨论:

(三)、还有,就是针对Buffercache中的块的锁了,Oracle为它定义的类型为BL。

      上面这些,就是RAC锁的全部了。

也就是说,RAC的数据库在运行期间,只有这些东西,需要在节点间同步。

      下面提个问题,猜猜看哪种锁数量最多?

      你一定会说针对Buffer的BL锁,但不是。

大多数情况下,是Rowcachelock的数量最多(这里不讨论极致情况)。

      但是Rowcachelock通常是静止的,很少修改。

数据字典,元数据吗,改动当然不多。

而Buffer的BL锁就不一样的,修改频繁。

因此,Oracle在普通的锁管理机制之外,针对BL又搞了个CacheFusion。

好,这里就不讨论它了,以后我会再详细讨论CacheFusion的。

二、      资源池与主节点

      和单实例中的队列锁一样,RAC中的锁,也分为两部分:

资源结构和锁结构。

      在共享池中,还有一个资源结构池,审请锁的第一部,就是到这个池中审请一个Free的资源结构。

      可以把资源池想像一块内存,其时,它就是一大块内存,在实例启动时分配。

如下图:

2012-3-722:

38上传

下载附件(30.95KB)

在资源池中,内存又被分成一个个小块,每个小块,就是上图中的一行,Oracle称为一个Slot。

每个Slot,就叫做一个资源结构(Resourcestruct)。

每个资源结构中的主要信息如下:

资源名(RESOURCE_NAME)

转换者队列地址(ON_CONVERT_Q)

持有者队列地址(ON_GRANT_Q)

主节点(MASTER_NODE)

      可以进一步把资源池想像成如下的表格:

2012-3-722:

41上传

下载附件(34.14KB)

我们把其中重要的东西解释一下。

      1、资源名:

和单实例中的队列锁一样。

资源名由资源类型加两个参数构成。

比如TM锁的资源名,一般写为TM-ID1-ID2,TM是资源类型(也就是锁类型)。

参数ID1是DBA_OBJECTS中的对象编号,ID2为0。

假设有个表,对象编号是195,它的TM资源(或称为TM锁)的资源名为:

TM-195-0。

这点对于单实例、多实例来说,是一样的。

      再来找个不一样的,比如一个Buffer。

资源类型是BL,两个参数ID1、ID2分别是从块地址计算出来的(计算规则我会在CacheFusion中详细描述)。

这个BL-ID1-ID2锁,在单实例中,绝对不会出现。

      2、转换者队列和持有者队列:

这分别是两个链表,记录有多个进程持有锁,或正在等待锁。

RAC认为每个实例中的每个进程都可以获得空锁,所以,如果进程想获得独占锁,但没有成功,那么它是要从空锁转换成独占锁而没有成功。

所以这里没有等待者队列,只有转换者队列。

我们可又把转换者队列,理解为等待者队列,记录所有正在等待进程信息。

      3、主节点:

这个信息,是单实例中资源结构所没有的。

RAC中,每个锁都有一个主节点。

或者,准确点说,每个资源结构都有一个主节点。

      主节点的计算方式,是用资源名作HASH。

这里的HASH算法,可以理解为根据资源名的一串字符,求得一个数字,再用这个数字除以节点数,取余数。

比如有个这样的资源名,TM-1234-0,求得的HASH值为3,它的主节点就是3。

      某个节点的进程,如果想对某个资源加锁,第一步就是根据资源名计算出HASH值,根据HASH值找到资源的主节点。

注意:

锁,或者队列锁,也叫资源。

它包含两部分信息,资源结构和锁结构。

资源结构有主节点,锁结构没有主节点。

千万不要被资源结构、锁结构这样的名称所误导。

这两个东西,就是锁的两部分信息。

三、资源结构的查找

      各节点的进程想要加锁,第一步就是定位资源结构。

如何定位,HASH算法。

Oracle内部,只要涉及在内存中查找东西,比如要BufferCache中找某个Buffer,在共享池中找某条SQL,等等,全部用的是HASH。

资源结构的查找定位也不例外。

      比如,有个表叫MythData,节点1的进程程想在MythData表上加锁,此表的对象编号为1234,那么资源名为TM-1234-0,根据此资源名,计算HASH值,得到主节点为2号节点。

节点1向节点2发送加锁请求。

接到加锁请求,节点2根据TM-1234-0这个资源名,再次计算HASH值,这次不再是为了求主节点了,是为了在自己的内存中定位此资源的资源结构。

      如下图:

2012-3-722:

44上传

下载附件(39.04KB)

接下来,节点2在自已的内存中定位资源TM-1234-0:

2012-3-722:

44上传

下载附件(58.39KB)

四、锁结构

      如果节点1可以持有TM-1234-0,接下来Oracle会如何处理呢?

在资源结构上加锁结构。

      我们再一次强调,千万不要被资源结构、锁结构这样的名称所误导。

这两个东西,就是锁的两部分信息。

      同样的,共享池中也有一个锁池,如下图:

2012-3-722:

47上传

下载附件(45.72KB)

再进一步的,锁池内存也被分为一个个的小块,每一块称为一个Slot,就是图中的一行。

每一行我们就称之为一个锁结构。

      锁结构中的信息比较多,有资源名、加锁的节点、加锁的进程、锁结构所在队列、状态等信息。

下面把重要的说一下:

      加锁的节点:

锁结构没有主节点,锁结构只会隶属于某个资源结构。

而资源结构是有主节的。

      锁结构所在队列:

如果请求进程可以加锁,锁结构会被加入资源结构的持有者队列。

否则,如果有其他人以不兼容的方式持有锁,请求进程将被挂在资源结构的转换者队列,也就是说,请求被阻塞了。

      也就是说,锁池的形式如下:

2012-3-722:

47上传

下载附件(42.46KB)

好,下面我们来详细说一下完整的锁的获取过程。

接着上面第10点。

五、完整的锁的获取过程

      上面第10步,已经说到,主节点2中,TM-1234-0的资源结构显示,无人持有此资源,持有者队列为空。

转换者队列也为空。

哪么节点1可以持有此资源。

      接下来再看下面这些图:

2012-3-722:

53上传

下载附件(50.76KB)

2012-3-722:

53上传

下载附件(52.93KB)

2012-3-722:

53上传

下载附件(57.97KB)

注意,下面的图,和上面的图的区别,多了个箭头。

2012-3-722:

55上传

下载附件(56.25KB)

第15步的目的,就是建立资源结构和锁结构的联系。

更通俗点说,就是将锁结构挂到对应资源结构的持有者队列中。

      至此,节点1的操作完毕。

主节点(节点2)也会有类似操作。

主节点上的操作不再详述,大至如下:

(1)、如果TM-1234-0在节点2上还没有资源结构,节点2会在自已的共享池中的资源池中审请一个Slot,并填入信息

(2)节点2在共享池的锁池中审请一个锁结构,并填入信息。

(3)、将锁结构挂在资源结构的持有队列中。

具体如下:

2012-3-722:

55上传

下载附件(59.27KB)

也就是说,主节点和审请节点,都会有锁的相关信息。

再次强调,“锁的相关信息”指的就资源结构和锁结构。

六、实际操作

      理论先说这么多吧,下面来点实验。

我们的最终目的,是要从理论中学习如果RAC出现了锁问题,如何定位。

我们研究理论,也要和实践挂钩,要不然,理论就成了虚无飘渺的东西。

但是,有时研究内部、研究理论,不是马上就能有成果,往往需要潜心研究一段时间才可。

      总之,我的观点,研究内部,一定不能满足于听一听、或看一看别人的成果,这样的研究,毫无意义。

一定要自己动手,反复测试、验证别人的理论,这样才会进步。

      好,闲言少叙,开始。

1、测试环境

      两节点RAC,有表T3,对象号为12566,16进制为3136。

我分别在两个节点进行如下操作:

节点2,会话1:

insertintot3values(1,'a');

      插入为DML,在T3对象上要加TM锁。

也就是要在资源名为TM-3136-0的资源上,加共享型的锁。

节点2,会话2:

insertintot3values(2,'b');

      也在TM-3136-0上加共享型的锁。

节点1,会话1:

insertintot3values(3,'c');

      同上。

节点1:

lock  table  t3  in  exclusive  mode;

      在TM-3136-0上,加独占锁。

      每做完一步,用视图观察资源结构和锁结构。

步1:

在节点2执行:

SQL>insertintot3values(1,'a');

1rowcreated.

步2:

查看锁情况:

(1)、在节点2查看资源结构:

SQL>selectRESOURCE_NAME,ON_CONVERT_Q,ON_GRANT_Q,MASTER_NODEfromV$DLM_RESSwhereresource_namelike'[0x3116%TM%';

RESOURCE_NAME            ON_CONVERT_QON_GRANT_QMASTER_NODE

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

[0x3116][0x0],[TM]                0      1        0

RESOURCE_NAME:

资源名,就是TM-3116-0。

ON_CONVERT_Q:

转换者队列中锁结构的数量。

现在为0,也就是没有人补阻塞。

ON_GRANT_Q:

持有者队列中锁结构的数量。

现在为1,有进程的锁结构在持有者队列中。

MASTER_NODE:

资源的主节点。

此处为0,即主节点为0,也就是节点1。

(2)、在节点1查看资源结构:

SQL>selectRESOURCE_NAME,ON_CONVERT_Q,ON_GRANT_Q,MASTER_NODEfromV$DLM_RESSwhereresource_namelike'[0x3116%TM%';

RESOURCE_NAME            ON_CONVERT_QON_GRANT_QMASTER_NODE

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

[0x3116][0x0],[TM]                0      1        0

      和在节点2查看一样。

(3)、在节点2查看锁结构:

SQL>setlinesize1000

SQL>colSTATEfora15

SQL>selectGRANT_LEVEL,REQUEST_LEVEL,PID,OWNER_NODE,WHICH_QUEUE,STATE,BLOCKED,BLOCKERfromV$GES_ENQUEUEwhereRESOURCE_NAME1like'[0x3116%TM%';

GRANT_LEVREQUEST_L  PIDOWNER_NODEWHICH_QUEUESTATE  BLOCKED  BLOCKER

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

KJUSERCWKJUSERCW  29079  1    1GRANTED        0      0

GRANT_LEVEL:

锁的类型,我只记得最后两个字母的意义,CW是共享,EX为独占,NL为空锁。

REQUEST_LEVEL:

请求的锁的类型。

PID:

进程号。

OWNER_NODE:

审请并持有锁的节点。

此处为1,即节点2.

WHICH_QUEUE:

锁结构被挂在资源结构的哪队列中。

此处是1,即持有者队列。

为0则为转换者队列,此表正在等待。

STATE:

状态。

BLOCKED:

是否被阻塞。

BLOCKER:

是否阻塞别人。

      根据这些列的信息,我们可以知道,29079号进程,在节点2上审请TM-3116-0资源。

请求的模式为共享,得到的模式也为共享,没有被阻塞。

(4)、在节点1观察锁结构:

SQL>setlinesize1000

SQL>colSTATEfora15

SQL>selectGRANT_LEVEL,REQUEST_LEVEL,PID,OWNER_NODE,WHICH_QUEUE,STATE,BLOCKED,BLOCKERfromV$GES_ENQUEUEwhereRESOURCE_NAME1like'[0x3116%TM%';

GRANT_LEVREQUEST_L  PIDOWNER_NODEWHICH_QUEUESTATE  BLOCKED  BLOCKER

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

KJUSERCWKJUSERCW  0  1      1GRANTED          0      0

      显示结构同在节点2中看到的基本一样。

有一列不同,就是PID列,此处为0。

步3:

再在节点2执行一条DML语句:

另外在节点2上打开个一会话,执行:

SQL>insertintot3values(2,'b');

1rowcreated.

步4:

查看锁情况

(1)、在节点2查看资源结构与锁结构:

SQL>selectRESOURCE_NAME,ON_CONVERT_Q,ON_GRANT_Q,MASTER_NODEfromV$DLM_RESSwhereresource_namelike'[0x3116%TM%';

RESOURCE_NAME            ON_CONVERT_QON_GRANT_QMASTER_NODE

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

[0x3116][0x0],[TM]                0      1        0

ON_GRANT_Q仍然为1,但其实TM-3116-0资源的持有者队列中,已经有两个共享锁结构了。

这说明ON_GRANT_Q只是说明有锁结构在持有者队列中,至于有多少锁,此列并不显示。

SQL>selectGRANT_LEVEL,REQUEST_LEVEL,PID,OWNER_NODE,WHICH_QUEUE,STATE,BLOCKED,BLOCKERfromV$GES_ENQUEUEwhereRESOURCE_NAME1like'[0x3116%TM%';

GRANT_LEVREQUEST_L  PIDOWNER_NODEWHICH_QUEUESTATE  BLOCKED  BLOCKER

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

KJUSERCWKJUSERCW  12870      1        1GRANTED      0      0

KJUSERCWKJUSERCW  29079      1        1GRANTED      0      0

锁结构又多了一个,PID为12870。

(2)、在节点1上显示资源结构与锁结构

SQL>selectRESOURCE_NAME,ON_CONVERT_Q,ON_GRANT_Q,MASTER_NODEfromV$DLM_RESSwhereresource_namelike'[0x3116%TM%';

RESOURCE_NAME            ON_CONVERT_QON_GRANT_QMASTER_NODE

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

[0x3116][0x0],[TM]                0      1        0

资源结构的显示结果,与在节点2上显示的一样。

SQL>selectGRANT_LEVEL,REQUEST_LEVEL,PID,OWNER_NODE,WHICH_QUEUE,STATE,BLOCKED,BLOCKERfromV$GES_ENQUEUEwhereRESOURCE_NAME1like'[0x3116%TM%';

GRANT_LEVREQUEST_L  PIDOWNER_NODEWHICH_QUEUESTATE  BLOCKED  BLOCKER

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

KJUSERCWKJUSERCW  0      1      1GRANTED      0      0

      锁结构的显示结果就不一样了。

在节点2(1号节点)上,已经有两个锁了(也就是有两个锁结构),但在主节点上,只显示一行。

      这是Oracle为了节省内存做的优化。

主节点没有必要知道其他节点持有的全部锁,只需要知道某个节点持有的最高级别的锁即可。

现在,1号节点也就是节点2,持有的最高级别的锁是共享锁。

步5:

在节点1上执行DML:

SQL>insertintot3values(3,'c');

1rowcreated.

步6:

查看信息

(1)、资源结构中的信息,在两个节点中都没有变化。

(2)、锁结构的信息,节点2没有变化。

因为节点2不是主节点,并且新的操作也不是在节点2上产生的。

所以节点2上的锁结构完全没有变化。

(3)、节点1的锁结构信息:

SQL>selectGRANT_LEVEL,REQUEST_LEVEL,PID,OWNER_NODE,WHICH_QUEUE,STATE,BLOCKED,BLOCKERfromV$GES_ENQUEUEwhereRESOURCE_NAME1like'[0x3116%TM%';

GRANT_LEVREQUEST_L  PIDOWNER_NODEWHICH_QUEUESTATE  BLOCKED  BLOCKER

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

KJUSERCWKJUSERCW  30873    0        1GRANTED      0      0

KJUSERCWKJUSERCW  0      1        1GRANTED      0      0

多了一个PID为30873的锁。

OWNER_NODE节点为0,0号结构也就是节点1。

步7:

在节点1产生一个独占锁请求:

SQL>lock  table  t3  in  exclusive  mode;

步8:

观察锁信息

(1)、节点2上资源结构和锁结构没有变化。

(2)、节点1上资源结构:

SQL>selectRESOURCE_NAME,ON_CONVERT_Q,ON_GRANT_Q,MASTER_NODEfromV$DLM_RESSw

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 幼儿教育

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1