星期五 三月 25, 2016

使用12c 的 ping target 功能解决虚拟机环境外部公网网线断开不能正常触发failove的问题

在虚拟机环境如果物理主机的公网网线断开的时候,虚拟机内部对应的公网网卡并不知晓物理网线的断开,RAC也不会检测到这种物理网线的断开,VIP等资源 也不会做failover。这实际导致rac 的VIP Listener 在公网故障时的 failover 功能失效。

具体环境:
软件环境:Oracle VM 3 + Oracle Linux 6+ Oracle RAC Cluster 11.2.0.4
架构环境:两节点RAC集群,集群节点分别运行在Oracle VM虚拟机上,RAC的private network和public network分别桥接在OVM Server不同的物理网卡上,物理网卡均为OVM的VM Network。

[Read More]

星期六 三月 19, 2016

expdp导出表数量接近但是时间差距明显原因

为什么有时候两个表数量接近但是导出时间却差距明显?

日前接到一个case,用户反映一个表导出时间特别长,因为担心影响第二天业务,不得不放弃继续导出,但是另外一个表比这个问题表数量更大,但是反而顺利导出,用户在相同版本测试环境上也能顺利导出,当然测试环境和生产环境还是有差异的,客户说那个环境是用两个月前的备份恢复而成的,但是数据量差距并不十分明显,但是导出时间却天壤之别,于是让客户对expdp进行trace,因为导出时间特别长,所以只做了30min的,通过tkprof 查看,时间基本都是io操作,但是因为另外一个表比这个数据量还大却能顺利导出,所以可以排除是IO瓶颈问题,于是查看原始trace文件,大量的db file sequential read,统计了一下,数量非常之多,接近了blocks数量,随便查找了一个block#,居然发现有多条记录。

[Read More]

星期五 三月 11, 2016

一个"间歇性物理IO缓慢"导致log file sync问题的案例

根据 Note 1626301.1 - 故障排除:"log file sync"等待 中提到的 "间歇性物理IO缓慢对 'log file sync' 等待事件的影响":
“如果你发现系统的'log file sync'很高,但是'log file parallel write'是处于正常的范围,那么这可能是由于间歇性物理IO缓慢导致的。你需要使用一些像OSWatcher一样的工具(参照 Document 301137.1)来确定是否系统中存在间歇性物理IO缓慢。”

日前我们就碰到了这么一例,这里给大家分享一下分析的过程。

[Read More]

星期五 三月 04, 2016

主机os重装的节点加回RAC集群步骤示例

很多客户遇到过这样的情况:由于RAC其中一个节点的主机OS损坏,需要重装。而重装后怎样把节点加回集群呢?


这里将涉及的步骤整理如下:

[Read More]

硬件改变导致Osysmond.bin产生Core Dump

Osysmond.bin是Cluster Health Check的组件,其功能是监控和收集操作系统级的统计信息,并把它发送给ologgerd记录。硬件变更(如扩充CPU、添加硬盘等)可能导致OSYSMOND无法识别新硬件,从而产生core dump。本文就该问题给出了相应的解决方案。

[Read More]

星期四 十二月 24, 2015

RAC之间消息传输流量控制

RAC系统中,对于节点和节点之间数据块一致性的保证是通过消息的机制来保证的,也就是我们常说的gcs和ges的这些消息来确保的。这些消息分别有LMD和LMS的进程在实例之间进行传输。

LMD负责处理message的信息,如块的状态,lock level等信息。而LMS会负责数据块的传输。我们这不讨论一致性的机制,主要关注在消息传输的流量和控制上。

[Read More]

星期三 十一月 25, 2015

大连数据库技术研讨会

Oracle数据库技术支持不定期为您提供免费技术研讨会。
我们将在这里共享技术研讨会的相关信息和培训资料,敬请期待。

******技术研讨会 Session02 on 2015-12-05******
Topic:RAC数据库的连接管理
讲师:高斌
资料:Training_Material_Session02_20151205.pdf

******技术研讨会 Session01 on 2015-08-29******
Topic:SQL语句处理的详细过程
讲师:李鑫
资料:Training_Material_Session01_20150829.pdf

星期二 十月 13, 2015

归档日志的大小比在线日志的大小 小很多


有些用户会对于归档日志的大小比在线日志小感到疑惑,对于这种情况:

首先请检查您的归档日志文件是否压缩:
SELECT to_char(first_time,'yyyy-mm-dd hh24:mi:ss'),blocks*block_size/1024/1024,compressed from v$archived_log;

如果未压缩,那么这个问题可能和您的CPU个数有关。
请查看您的CPU个数:
show parameter CPU_COUNT

归档日志的大小是真实的在线日志文件的使用量,也就是在线日志文件切换前其中写入的内容的大小。
但是为了更好的并行减少冲突,oracle会按每16个CPU分一股(strand),每一股独立从redo buffer以及redo log中分配一块空间,当这一块redo buffer用完,会写入redo log并且继续从redo log中分配相同大小的空间,如果无法分配空闲空间就会进行日志切换,而不管其他strand是否写完。
下面举例子来说明这个算法:
比如CPU的个数是64个,则会有64/16=4个strand
例1)当log buffer的大小和redo log file的大小都是256M的时候,则每个strand都是256M/4=64M。
每一个redo log file被启用时,会预先将redo log file中的大小分配出4个64M与log buffer对应,如图:

因为log buffer的大小和redo log file的大小都是256M,则redo log file没有剩余的未分配的空间了。

每个进程产生的redo会分配到log buffer上的1,2,3,4其中的某一个strand上,单个进程只能对应一个strand,
这样当数据库中只有某些进程(比如极端的情况,只有某一个进程)产生的redo很多的时候,其中一个strand会快速写满,比如图中的strand 1:

写满之后LGWR会将log buffer中strand 1的内容写入到redo log file中,并且试图从redo log file中分配一个新的64M空间,发现没有了,则将所有strand中的内容写入日志,并作日志切换。

这样,可能会导致redo log file只写入了一个strand的内容,其他部分几乎是空的,则产生的archive log会只接近64M,而不是256M。
当CPU_COUNT很大时,这个差值会更大。

例2)当log buffer的大小是256M,而redo log file的大小是1G的时候,每个strand还是256M/4=64M。
每一个redo log file被启用时,会预先将redo log file中的大小分配出4个64M与log buffer对应,如图:

这时,redo log file中还有1G-256M=768M剩余的未分配的空间。


如果strand 1写满之后,LGWR会将log buffer中strand 1的内容写入到redo log file中,并且试图从redo log file中分配一个新的64M空间,然后不断往下写。


直到redo log file中再没有可分配空间了,则将所有strand中的内容写入日志,并作日志切换。



例3)当log buffer的大小是256M,而redo log file的大小是100M的时候,每个strand还是256M/4=64M。
但是redo log file中的空间会按strand的个数平均分配,也就是每块100M/4=25M。

这样,当每个strand中的内容写到25M的时候,就会日志切换,而不是64M。相当于log buffer中的一部分空间被浪费了。

请参考以下文档:
1.Archive Logs Are Created With Smaller, Uneven Size Than The Original Redo Logs. Why? (Doc ID 388627.1)
With a high CPU_COUNT, a low load and a redo log file size smaller than the redolog buffer, you may small archived log files because of log switches at about 1/8 of the size of the define log file size.
This is because CPU_COUNT defines the number of redo strands (ncpus/16). With a low load only a single strand may be used. With redo log file size smaller than the redolog buffer, the log file space is divided over the available strands. When for instance only a single active strand is used, a log switch can already occur when that strand is filled.

<==高 CPU_COUNT和低workload(实际上数据库不一定不繁忙,只是在产生redo的进程很少的情况下)会导致 Archive Log比redo log小很多,而且日志频繁切换。

2.Archived redolog is (significant) smaller than the redologfile. (Doc ID 1356604.1)
The logfile space reservation algorithm
If the logfile is smaller than the log buffer, then the whole logfile space is divided/mapped/reserved equally among all the strands, and there is no unreserved space (ie no log residue).
When any process fills a strand such that all the reserved underlying logfile space for that strand is used, AND there is no log residue, then a log switch is scheduled.

<==log strand 和 log switch的算法在这个note中讲的更明白。

星期四 八月 13, 2015

RAC 中锁的管理--实验部分

本文是之前关于《RAC 中锁的管理—Buffer Lock》文章的继续,在这篇文章中,会通过一个简单的例子演示RAC buffer lock的工作方式。



测试环境:


Oracle 版本:11.2.0.4(2 节点)


OS : OLE 5


首先,我们创建了一个测试表,为了简化测试,测试表只包含两行数据。


SQL>create table my_test (id number, name varchar2(20));


SQL>insert into my_test values ( 1, 'hello');


SQL>insert into my_test values ( 2, 'goodby');


SQL>commit;


接下来,查看表的数据库对象,和对应的数据文件编号和块号。


SQL> select object_id, data_object_id from dba_objects where owner='SCOTT' and object_name='MY_TEST';


OBJECT_ID DATA_OBJECT_ID


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


14445 14446


SQL> SELECT DBMS_ROWID.Rowid_relative_fno(ROWID) "FILE", DBMS_ROWID.Rowid_block_number(ROWID) "BLOCK", id, name from my_test;


FILE BLOCK ID NAME


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


5 4741 1 hello


5 4741 2 goodby


看起来创建的测试表(my_test)的DATA_OBJECT_ID=14446, 其中的两行数据都保存在5号数据文件的4741号数据块。


下面介绍一下测试过程中会使用的一些视图和表。


v$bh 这个视图保存了buffer header在内存中对应的信息,它能够帮助我们找到和buffer 相关的信息。


V$GC_ELEMENT 这个视图保存了和 Global Cache element 相关的信息,我一般把它称之为LELock Element),因为这里面主要就是保存和 GC相关的锁元素的信息。


x$kjbr 这个基表(或者可以叫做内存结构的映射)记录了块资源(Buffer Resource)的更多信息。


x$kjbl 这个基表记录了和br 资源相关的锁的信息(buffer lock)。



接下来,就通过一系列的操作来说明RACGC 部分的工作方式。


步骤1:在实例1上创建一个会话并执行下面的查询,之后看一下对应的PCM锁的状况。


会话1: 


SQL> select * from my_test where id=1;


ID NAME


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


1 hello


会话2


SQL> select b.file#, b.block#, b.status, b.LOCK_ELEMENT_NAME,b.FORCED_READS, b.FORCED_WRITES, g.MODE_HELD, g.BLOCK_COUNT, g.LOCAL, g.flags


from v$bh b, V$GC_ELEMENT g


where b.LOCK_ELEMENT_ADDR=g.GC_ELEMENT_ADDR and


b.file#=5 and b.block#=4741;


FILE# BLOCK# STATUS LOCK_ELEMENT_NAME FORCED_READS FORCED_WRITES


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


MODE_HELD BLOCK_COUNT LOCAL FLAGS


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


5 4741 scur 4741 0 0


1 1 1 32


可以看到被访问的块,在本地节点处于shared current(scur)模式。


SQL> select KJBLNAME,INST_ID, KJBLLOCKP, KJBLGRANT,KJBLREQUEST,KJBLROLE,KJBLMASTER


from x$kjbl


where KJBLNAME like '%1285%5%BL%' and KJBLPKEY=14446;


KJBLNAME INST_ID KJBLLOCK KJBLGRANT KJBLREQUE


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


KJBLROLE KJBLMASTER


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


[0x1285][0x5],[BL][ext 0x0,0x0 1 323E3AB0 KJUSERPR KJUSERNL


0 1


看起来节点1的确以KJUSERPR的方式持有了这个buffer


SQL> select KJBRRESP, KJBRGRANT, KJBRNCVL, KJBRROLE, KJBRNAME, KJBRMASTER, KJBRGRANTQ, KJBRCVTQ, KJBRWRITER,KJBRSID, KJBRPKEY


from x$kjbr


where KJBRNAME like '%1285%5%BL%' and KJBRPKEY=14446;


no rows selected


这里的结果比较奇怪,实例1上显示它并没有这个块资源对应的信息。其实这是正常的,因为每个资源的信息只有在它的master节点上才能找到,而每个资源的master节点是通过hash函数计算出来的,所以它不一定会保存在节点1上。我的测试是在一个2节点的rac上做的,所以在实例2运行同样的查询就会找到这个资源的详细信息。 在实例2上运行同样的查询。


实例2


SQL> select KJBRRESP, KJBRGRANT, KJBRNCVL, KJBRROLE, KJBRNAME, KJBRMASTER, KJBRGRANTQ, KJBRCVTQ, KJBRWRITER,KJBRSID, KJBRPKEY


from x$kjbr


where KJBRNAME like '%1285%5%BL%' and KJBRPKEY=14446;


KJBRRESP KJBRGRANT KJBRNCVL KJBRROLE KJBRNAME


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


KJBRMASTER KJBRGRAN KJBRCVTQ KJBRWRIT KJBRSID KJBRPKEY


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


3B3976D8 KJUSERPR KJUSERNL 0 [0x1285][0x5],[BL][ext 0x0,0x0


1 3A6316D8 00 00 0 14446


能够看到,实例2是这个buffer资源的主节点。一般来说,一个buffer资源的名称是由[block#][file#],[BL]构成的,当然他们是16进制(hex)的,1285hex=4741dec),所以我的查询条件是“KJBRNAME like '%1285%5%BL%' and KJBRPKEY=14446;”。上面的信息显示这个资源的master在节点2,并且已经被用KJUSERPR的方式被赋权了,而对应的convert请求不存在。


步骤2:在实例2 查询表里的另一行数据。由于两行数据保存在相同的数据块,所以这两个进程访问的资源也是相同的。


会话1


SQL> select * from my_test where id=2;


ID NAME


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


2 goodby


会话2


select b.file#, b.block#, b.status, b.LOCK_ELEMENT_NAME,b.FORCED_READS, b.FORCED_WRITES, g.MODE_HELD, g.BLOCK_COUNT, g.LOCAL, g.flags


from v$bh b, V$GC_ELEMENT g


where b.LOCK_ELEMENT_ADDR=g.GC_ELEMENT_ADDR and


b.file#=5 and b.block#=4741;


FILE# BLOCK# STATUS LOCK_ELEMENT_NAME FORCED_READS FORCED_WRITES


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


MODE_HELD BLOCK_COUNT LOCAL FLAGS


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


5 4741 scur 4741 0 0


1 1 1 32


看起来实例2也同样以scur的方式持有了这个块。


SQL> select KJBLNAME,INST_ID, KJBLLOCKP, KJBLGRANT,KJBLREQUEST,KJBLROLE,KJBLMASTER


from x$kjbl


where KJBLNAME like '%1285%5%BL%' and KJBLPKEY=14446;



KJBLNAME INST_ID KJBLLOCK KJBLGRANT KJBLREQUE


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


KJBLROLE KJBLMASTER


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


[0x1285][0x5],[BL][ext 0x0,0x0 2 2F3E9770 KJUSERPR KJUSERNL


0 1



[0x1285][0x5],[BL][ext 0x0,0x0 2 3A6316D8 KJUSERPR KJUSERNL


0 1


这里显示了两行记录,其实是正常的现象,因为节点2是这个buffer资源的master节点,所以他就会有这个buffer上的所有锁的信息。而节点1不是master节点,所以它就只有自己节点所持有的所信息。


步骤3:回到实例1,对表中的第一行数据进行修改,这意味着我们要获得这个资源上更高级别的锁。


SQL>update my_test set name='hello world' where id=1;


SQL>select b.file#, b.block#, b.status, b.LOCK_ELEMENT_NAME,b.FORCED_READS, b.FORCED_WRITES, g.MODE_HELD, g.BLOCK_COUNT, g.LOCAL, g.flags


from v$bh b, V$GC_ELEMENT g


where b.LOCK_ELEMENT_ADDR=g.GC_ELEMENT_ADDR and


b.file#=5 and b.block#=4741;



FILE# BLOCK# STATUS LOCK_ELEMENT_NAME FORCED_READS FORCED_WRITES


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


MODE_HELD BLOCK_COUNT LOCAL FLAGS


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


5 4741 xcur 4741 0 0


2 1 1 32


能看到,这个数据块当前的状态变成了exclusive current(xcur),也就是说,本地实例拥有的是这个块的最新���本。我们在实例2下面的语句。


实例2


SQL>select b.file#, b.block#, b.status, b.LOCK_ELEMENT_NAME,b.FORCED_READS, b.FORCED_WRITES


from v$bh b


where b.file#=5 and b.block#=4741;


FILE# BLOCK# STATUS LOCK_ELEMENT_NAME FORCED_READS FORCED_WRITES


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


5 4741 cr 0 0


可以看到,由于实例1修改了这个数据块(虽让是不同的行),实例2对应的块也变成了cr


再来看一下资源和锁层面的变化。


实例2:


SQL> select KJBRRESP, KJBRGRANT, KJBRNCVL, KJBRROLE, KJBRNAME, KJBRMASTER, KJBRGRANTQ, KJBRCVTQ, KJBRWRITER,KJBRSID, KJBRPKEY


from x$kjbr


where KJBRNAME like '%1285%5%BL%' and KJBRPKEY=14446;



KJBRRESP KJBRGRANT KJBRNCVL KJBRROLE KJBRNAME


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


KJBRMASTER KJBRGRAN KJBRCVTQ KJBRWRIT KJBRSID KJBRPKEY


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


3B3976D8 KJUSEREX KJUSERNL 0 [0x1285][0x5],[BL][ext 0x0,0x0


1 3A6316D8 00 00 0 14446


在这个资源的master节点上,能够看到这个资源已经被以KJUSEREX方式被授权了。


实例1


SQL> select KJBLNAME,INST_ID, KJBLLOCKP, KJBLGRANT,KJBLREQUEST,KJBLROLE,KJBLMASTER


from x$kjbl


where KJBLNAME like '%1285%5%BL%' and KJBLPKEY=14446;



KJBLNAME INST_ID KJBLLOCK KJBLGRANT KJBLREQUE


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


KJBLROLE KJBLMASTER


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


[0x1285][0x5],[BL][ext 0x0,0x0 1 323E3AB0 KJUSEREX KJUSERNL


0 1


实例1KJUSEREX方式持有了这个buffer资源上的锁。


实例2


SQL>select KJBLNAME,INST_ID, KJBLLOCKP, KJBLGRANT,KJBLREQUEST,KJBLROLE,KJBLMASTER


from x$kjbl


where KJBLNAME like '%1285%5%BL%' and KJBLPKEY=14446;


2 3


KJBLNAME INST_ID KJBLLOCK KJBLGRANT KJBLREQUE


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


KJBLROLE KJBLMASTER


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


[0x1285][0x5],[BL][ext 0x0,0x0 2 3A6316D8 KJUSEREX KJUSERNL


0 1


这个时候资源主节点上也只有1行数据了,只是因为实例要求持有更高级别的锁KJUSEREX,那么之前的低级别锁KJUSERPR就需要被释放以便能够让实例1获得更高级别的锁。


步骤4在实例2当中修改表的第二行数据。


SQL> update my_test set name='goodby my love' where id=2;



SQL> select b.file#, b.block#, b.status, b.LOCK_ELEMENT_NAME,b.FORCED_READS, b.FORCED_WRITES, g.MODE_HELD, g.BLOCK_COUNT, g.LOCAL, g.flags


from v$bh b, V$GC_ELEMENT g


where b.LOCK_ELEMENT_ADDR=g.GC_ELEMENT_ADDR and


b.file#=5 and b.block#=4741;



FILE# BLOCK# STATUS LOCK_ELEMENT_NAME FORCED_READS FORCED_WRITES


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


MODE_HELD BLOCK_COUNT LOCAL FLAGS


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


5 4741 xcur 4741 0 0


2 1 0 32



可以看到,由于实例2 修改了这个块,所以实例2 上的这个块处于了xcur 模式。


实例1


SQL> select b.file#, b.block#, b.status, b.LOCK_ELEMENT_NAME,b.FORCED_READS, b.FORCED_WRITES


from v$bh b


where b.file#=5 and b.block#=4741;



FILE# BLOCK# STATUS LOCK_ELEMENT_NAME FORCED_READS FORCED_WRITES


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


5 4741 pi 4741 0 0


5 4741 free 0 0


5 4741 cr 0 0


5 4741 cr 0 0


可以看到,实例1当中出现了一个PIPast Image)类型的buffer。简单地说,当一个数据块在多个实例被修改的时候,除了最新修改该块的实例,其他实例对应的块都会变成PI。而且,再把对应的buffer标识成PI之前,还要把buffer 拷贝成另一个CR。当然,一个buffer在数据库缓冲区当中拥有的CR copy数量是通过隐含参_DB_BLOCK_MAX_CR_DBA(默认值=6)来控制的。


再来看看资源和锁的信息。


实例2


SQL> select KJBRRESP, KJBRGRANT, KJBRNCVL, KJBRROLE, KJBRNAME, KJBRMASTER, KJBRGRANTQ, KJBRCVTQ, KJBRWRITER,KJBRSID, KJBRPKEY


from x$kjbr


where KJBRNAME like '%1285%5%BL%' and KJBRPKEY=14446;


2 3


KJBRRESP KJBRGRANT KJBRNCVL KJBRROLE KJBRNAME


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


KJBRMASTER KJBRGRAN KJBRCVTQ KJBRWRIT KJBRSID KJBRPKEY


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


3B3976D8 KJUSEREX KJUSERNL 0 [0x1285][0x5],[BL][ext 0x0,0x0


1 2F3E9770 00 00 0 14446


资源的状态信息并没有太大的变化。


实例2:


SQL> select KJBLNAME,INST_ID, KJBLLOCKP, KJBLGRANT,KJBLREQUEST,KJBLROLE,KJBLMASTER


from x$kjbl


where KJBLNAME like '%1285%5%BL%' and KJBLPKEY=14446;


2 3


KJBLNAME INST_ID KJBLLOCK KJBLGRANT KJBLREQUE


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


KJBLROLE KJBLMASTER


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


[0x1285][0x5],[BL][ext 0x0,0x0 2 2F3E9770 KJUSEREX KJUSERNL


0 1


由于实例2,最新修改了记录,所以它持有了KJUSEREX级别的buffer lock



实例1


SQL> select KJBLNAME,INST_ID, KJBLLOCKP, KJBLGRANT,KJBLREQUEST,KJBLROLE,KJBLMASTER


from x$kjbl


where KJBLNAME like '%1285%5%BL%' and KJBLPKEY=14446;



no rows selected


由于KJUSEREX级别的锁是不能和其他锁兼容的,所以之前实例1持有的锁被释放掉了。



由于篇幅有限,今天的测试先到此为止。希望以上的测试有助于大家理解oracle RAC buffer lock的工作方式



如果大家对这篇文章有任何问题或者需要展开讨论,请在本贴回复。

星期三 十二月 31, 2014

只对某个特定的SQL语句开启10046 trace

最近碰到了这样一个有趣的问题: 有一条SQL语句,大部分时间它的执行时间是几十个毫秒; 但是偶尔某次的执行时间会长于2秒钟。因为应用对这个语句的执行时间非常的敏感,我们必须诊断是因为什么原因导致它偶尔执行时间长于2秒。


这个问题为什么会有挑战性呢?因为我们很难收集慢的时候的10046 trace:首先我们不知道这个问题什么时候会发生,也不知道会在哪个session里发生。如果对所有的session全天开启10046 trace, 会产生很多比较大的trace并影响数据库整体的性能。


好在这个数据库是11g的,在11gevent++的特性允许我们只对某个特定的SQL收集10046 trace. 即在运行这条SQL时开启10046 trace,在这条SQL运行完之后关闭10046 trace.这样可以显著的降低生成的trace的大小。但是因为我们无法确定哪个session会产生问题,所以只要运行过这个SQLsession都会产生一个trace文件。


开启的步骤是(要把下面的awsh60c8mpfu1替换成那条SQLSQL_ID)


alter system set events 'sql_trace [sql: awsh60c8mpfu1] level 12';


而关闭的步骤是(要把下面的awsh60c8mpfu1替换成那条SQLSQL_ID)


alter system set events 'sql_trace [sql: awsh60c8mpfu1] off';


在收集到很多10046 trace,并使用tkprof格式化后(需指定AGGREGATE=NO,这样tkprof会对每一次执行都生成汇总报告),我们最后定位到了问题发生时SQL语句读取物理块时花费了更多的时间。


关于这个主题,如果有后续的问题欢迎点击链接参与我们在中文社区的讨论。 




星期四 十二月 04, 2014

几种常见的library cache lock产生的原因


常见的library cache lock产生的原因在《高级OWI与Oracle性能调查》这本书和下面这个文档中有一般性的描述:
Troubleshooting Library Cache: Lock, Pin and Load Lock (Doc ID 444560.1)

一般可以理解的是alter table或者alter package/procedure会以X模式持有library cache lock,造成阻塞。
但是常见的问题还有以下几种原因:

1)错误的用户名密码:

一般需要通过ASH或者SSD/hang analyze去获取p3进行namespace分析。

             1.       event: 'library cache lock'
                time waited: 43 min 12 sec
                    wait id: 9               p1: 'handle address'=0x7000003117dfca0
                                             p2: 'lock address'=0x700000310866c80
                                             p3: '100*mode+namespace'=0x4f0003
             * time between wait #1 and #2: 0.000164 sec

<=================p3: '100*mode+namespace'=0x4f0003

mode=3
namespace=4f

HEX: 4f =>DEC: 79

select * FROM V$DB_OBJECT_CACHE;

SQL> select distinct KGLHDNSP,KGLHDNSD from x$kglob;

  KGLHDNSP KGLHDNSD
---------- ----------------------------------------------------------------
         0 SQL AREA
         4 INDEX
         1 TABLE/PROCEDURE
         3 TRIGGER
        52 SCHEDULER EARLIEST START TIME
        64 EDITION
        69 DBLINK
         2 BODY
        10 QUEUE
        79 ACCOUNT_STATUS
        23 RULESET
        24 RESOURCE MANAGER
        73 SCHEMA
        74 DBINSTANCE
        51 SCHEDULER GLOBAL ATTRIBUTE
        38 RULE EVALUATION CONTEXT
        82 SQL AREA BUILD
        75 SQL AREA STATS
         5 CLUSTER
        18 PUB SUB INTERNAL INFORMATION

<======79 ACCOUNT_STATUS

ACCOUNT_STATUS说明library cache lock是在account上,可能是用错误的用户名密码登录,或者是当时正有人alter user(这种几率极低)。

可以通过以下SQL去确认错误的用户名密码登录:
select username,
os_username,
userhost,
client_id,
trunc(timestamp),
count(*) failed_logins
from dba_audit_trail
where returncode=1017 and --1017 is invalid username/password
timestamp < sysdate -7
group by username,os_username,userhost, client_id,trunc(timestamp);

Or run following sql:
SELECT "USERNAME", "OS_USERNAME", "USERHOST", "EXTENDED_TIMESTAMP",returncode  FROM "SYS"."DBA_AUDIT_SESSION" WHERE returncode != 0;

当然必须确保audit 打开,并且有audit CREATE SESSION动作

To turn on audit:
Alter system set audit_trail=DB scope=spfile;
restart DB

audit CREATE SESSION;
audit ALTER USER;

检查:
show parameter audit_trail
select * from DBA_STMT_AUDIT_OPTS;

2)正在执行搜集统计信息,这是大家往往会忽略的,一般会看last_ddl_time,却忽略了last_analyzed,
检查脚本如下:

比如EMP是遇到library cache lock中的表名:
select owner,object_name,object_type,to_char(last_ddl_time,'yyyy-mm-dd hh24:mi:ss') from dba_objects where object_name='EMP';

select table_name,to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') from dba_tables where table_name='EMP';

也需要检查所有dependency的对象,因为oracle对象是相互关联的,一个对象失效会导致一串失效。
select owner,object_name,object_type,to_char(last_ddl_time,'yyyy-mm-dd hh24:mi:ss') ddl_time from dba_objects where object_name in
(
select p.name
from sys.obj$ d, sys.dependency$ dep, sys.obj$ p
where d.obj# = dep.d_obj# and p.obj# = dep.p_obj#
start with d.name='EMP'
connect by prior dep.p_obj#=dep.d_obj#)
order by ddl_time desc;

select table_name,to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') from dba_tables where table_name in
(
select p.name
from sys.obj$ d, sys.dependency$ dep, sys.obj$ p
where d.obj# = dep.d_obj# and p.obj# = dep.p_obj#
start with d.name='EMP'
connect by prior dep.p_obj#=dep.d_obj#)
order by last_analyzed desc;

比较典型的一个用户实例:
select to_char(last_analyzed,'yyyy-mm-dd hh24:mi:ss') from dba_tables where table_name='XXXXX';
--2014-11-25 16:52:50
<=============gathering statistics in the issue time

2014-11-25 16:52:52 16620 c34q5c8gf6kum library cache lock
2014-11-25 16:52:52 16643 c34q5c8gf6kum library cache lock
<======The issue starts from 16:52:52 while statistics was gathered at 16:52:50

3)错误的语句解析(failed parse)
这是通常很难注意到的一个问题,因为被解析的语句往往在AWR中找不到(因为没有通过parse),要注意查看AWR中的“failed parse elapsed time”

Event Waits Time(s) Avg wait (ms) % DB time Wait Class
library cache lock 6,714,208 363,093 54 67.14 Concurrency
library cache: mutex X 11,977,886 99,050 8 18.31 Concurrency
DB CPU   38,971   7.21 
db file sequential read 350,069 2,465 7 0.46 User I/O
log file sync 217,673 1,969 9 0.36 Commit


Statistic Name Time (s) % of DB Time
sql execute elapsed time 537,418.09 99.37
parse time elapsed 467,101.99 86.37
failed parse elapsed time 460,663.79 85.18 <===============failed parse elapsed time was high. That means the issue was caused by parse failed.

详细请参考:
High Waits for 'library cache lock' and 'library cache: mutex X' Due to Parse Failures When Using JDBC ResultSet.TYPE_SCROLL_SENSITIVE (Doc ID 1566018.1)



参与此主题的后续讨论,请回复blog,或者访问我们的中文社区,跟帖"分享:几种常见的library cache lock产生的原因"。 


了解更多博文信息请访问Oracle数据库产品技术支持-博客文章索引


星期五 十一月 14, 2014

TimesTen 常见问题答疑(科普篇)

什么是Oracle TimesTen 内存数据库?

Oracle TimesTen内存数据库是一款内存优化的关系型数据库。
该产品可使应用大幅提高响应速度和吞吐量来满足当今有实时需求的企业,
尤其适合电信,金融,互联网,旅游,在线游戏,保险等行业的企业。
部署在应用层的TimesTen数据库是一款可嵌入式或者独立的数据库。
它完全驻留在物理内存中,通过标准SQL接口进行数据库操作。
此外,该产品还包括复制技术来进行实时事务在TimesTen数据库之间的复制,
进而实现高可用性和分担负载的目的。

-----------
什么是Oracle TimesTen 应用层数据库缓存?

自从Oracle 12c 数据库推出了In-Memory功能,为了避免理解上的误解,将之前的 Im-Memory Database Cache 改为了应用层数据库缓存。
该功能是 Oracle TimesTen 数据库的一个选项,来提供实时的 对Oracle 数据库的读写缓存。
通过缓存性能敏感的表的子集从Oracle数据库到应用层,来提高应用事务响应时间。
缓存表在TimesTen数据库中的管理仍然是常规的关系型数据库表的管理方式。因此,可以提供给应用一个完全通用和功能完备的关系型数据库,与Oracle数据库保持缓存透明维护的一致,并且实时高效的内存数据库。
为了实现高可用性,Orale TimesTen 应用层数据库缓存可以通过使用actinve-standby配置的部署方案,且缓存表可以在Oracle TimesTen数据库之间进行实时复制。

-----------
TimesTen 内存数据库是否是 Oracle 12c数据库的一部分?

Oracle TimesTen 应用层数据库缓存是针对 Oracle 12c 和 11g数据库的一个数据库功能。它包括了TimesTen 内存数据库和缓存技术。可以使得TimesTen 作为一个内存缓存数据库自动将数据在TimesTen 和 Oracle 数据库同步。
Oracle TimesTen内存数据库需要单独购买License。包括TimesTen 内存数据库和复制组件。
-----------

TimesTen 数据库有哪些大小限制么?

数据库的大小受限于服务器上的物理内存大小。
在32位平台,受限于32位地址空间,因此数据库大小在2GB以内,或者更小,取决于具体平台。
对于64位平台,除了机器上的物理内存大小外,没有其他大小限制。
现有的用户在部署数据库的大小方面,从1GB 到超过2TB均有实际案例。
-----------

哪些应用最适合运行TimesTen?

TimesTen 被用在众多电信应用系统中,例如认证授权,计费,呼叫中心等。
也同样可以部署在金融应用系统中,例如安全贸易,反欺诈,股票证券,网上银行等方面。
其他应用系统包括游戏公司,CRM系统,飞机订票系统,旅游运输,国防应用系统等。

-----------
Oracle TimesTen技术都可以运行在哪些平台上?

以下列出的是当前支持的平台:
Linux x86, Linux x64, Solaris SPARC 64位,Solaris SPARC 32位客户端,Windows x64, Windows x86,
IBM AIX on POWER System 64位, IBM AIX on POWER System 32位客户端 以及 Solaris x64位。
Oracle TimesTen应用层数据库缓存功能支持 Oracle 数据库12c, 11gR2 和 11gR1。


-----------


如何获得 TimesTen 最新的小版本信息?


请参考实时更新的官方文档: TimesTen 内存数据库 (IMDB) 版本支持摘要 (Doc ID 1536728.1)


-----------

TimesTen 内存数据库可以独立作为数据库运行么?

当然。TimesTen 内存数据库被很多客户在应用层作为独立数据库来进行使用。
TimesTen对SQL操作提供全方位的事务支持,且事务日志保留在硬盘上用作恢复(数据库始终保留在内存中)。

-----------
数据是通过什么API来连接到TimesTen 内存数据库?

TimesTen内存数据库支持标准的ODBC, JDBC接口,并且还有针对应用的ADO.NET和OCI接口来连接数据库,使用标准的SQL-92。

-----------
TimesTen应用开发都使用哪些用语言?

可以使用Java, .NET, C, C++, Pro*C 和 PL/SQL来进行应用开发。
可以参考官方文档来获得程序样本。
http://www.oracle.com/technetwork/database/database-technologies/timesten/documentation/index.html
-----------

什么是嵌入式模式?

TimesTen内存数据库最初就是设计并优化运行在应用层。 数据库可以直连,即 嵌入到应用系统来优化性能。
TimesTen嵌入到应用中,SQL访问无需考虑网络或者IPC的负载问题。即便运行在嵌入式模式下,
TimesTen 仍旧提高完全的多进程,多线程访问和并行控制能力。
-----------
TimesTen 内存数据库是否支持类似Oracle 数据库的索引?

当然。TimesTen内存数据库支持索引。索引会提高数据库查询的性能,这点与Oracle 数据库没有区别。
TimesTen当前版本支持三种类型的索引:
区域查询,来提高相等或者不等区间查询;
哈希索引,提高主键和等效访问优于区域查询;
位图查询索引,用于没有太多唯一值查询和低并发下DML事务处理。
-----------
TimesTen 对软硬件有特殊要求么?

首先,TimesTen的设计都是基于数据驻留内存RAM管理的前提。
因此,最重要的是要考虑在应用服务器端,硬件是否仍有足够的内存。
除此之外,没有太多对硬件的要求。
作为任何一款应用产品,有足够数量的CPU(运行在适当的时钟速度下)也是确保应用运行速度的关键
为了利用多CPU的硬件条件,你需要或者运行多个应用,或者将你的应用写成多线程运行。
另外,事务日志和检查点文件是存储在硬盘上。因此,更快的磁盘表现也会提高整体性能。
TimesTen的Cache功能部署在应用层,通过SQL*Net与Oracle 数据库通信。
Oracle即时客户端因此需要安装在TimesTen Cache端,来连接Oracle 数据库。
-----------
数据结构的设计和创建在TimesTen 中是如何实现的?

TimesTen 支持标准SQL。创建数据结构一般使用SQL DDL语句,例如:
CREATE TABLE, CREATE INDEX, CREATE SEQUENCE, CREATE VIEW, CREATE MATERIALIZED VIEW, CREATE PACKAGE, CREATE PROCEDURE, CREATE FUNCTION, CREATE SYNONYM, ALTER TABLE 等。
这种设计均基于关系型数据库。在TimesTen中设计和管理数据库比基于磁盘优化的关系型数据库更加简单,因为它无需考虑表的扩展大小或者磁盘碎片整理等因素。
-----------
当节点宕机,由于是内存数据库,TimesTen是如何恢复的?

当整个数据库驻留内存时,TimesTen 仍旧有事务日志和检查点文件存放在磁盘上。当系统重启或者意外宕机,内存数据库可以从检查点文件和事务日志中得到恢复。另外,用户还可以通过配置复制技术来提高高可用性。
-----------
TimesTen 应用层数据库缓存在哪些平台可以被支持?

TimesTen 应用层数据库缓存对于Oracle数据库服务器来说,作为一个客户端应用程序。TimesTen 应用层数据库缓存与TimesTen 内存数据库所支持的平台相同。
-----------
是否可以将TimesTen 应用层数据库缓存允许在与Oracle数据库不同的操作系统平台?

当然可以。因为TimesTen 应用层数据库缓存是作为Oracle客户端来运行的。可以运行在与Oracle 数据库服务器不同
的平台。一般来说TimesTen 应用层数据库缓存运行在应用层,而Oracle数据库运行在企业架构的数据库层。
-----------
如果Oracle 数据库是一个TB级别的数据库,我的TimesTen 应用层数据库缓存应该设置多大?

性能敏感的数据量多少需要被缓存到TimesTen数据库完全取决应用的设计。除了可以缓存整个数据库,数据库表,列,以及行的子集都可以被缓存到TimesTen。另外一个选择,可以定义一个动态缓存,数据来自Oracle数据库中的表,且按需加载。
-----------
什么是TimesTen 复制?

TimesTen 复制是TimesTen 内存数据库和TimesTen 应用层数据库缓存的一个组件。TimesTen复制技术可以在TimesTen 服务器之间实现实时数据复制。用于创建高可用性的架构,容灾站点,在多节点分布数据。复制技术支持active/standby 或者 active/active的配置,使用同步或者异步的数据传输机制。
-----------
TimesTen复制如何保证在系统宕机时的数据可持续性?

TimesTen复制可以配置为整个数据库级别的复制到一个或多个TimesTen节点。
在一次failover后,备节点变为主节点。而发生问题的节点可以从新的主节点得到恢复。
-----------
是否可以复制选定的数据库表?

当然可以。表级别的复制和数据库级别的复制都是支持的。
-----------
TimesTen复制支持什么样的网络协议?

TimesTen 复制在复制的节点之间通过LAN或者WAN,使用的是TCP/IP socket。
-----------
TimesTen 的复制是否可以是双向的?

当然。单向和双向复制都是支持的。对于双向复制来说,建议负载要平均来避免可能发生的大量冲突。一旦复制冲突发生,即,更新同一个数据库的行,TimesTen复制支持基于时间戳的冲突检测和解决。
-----------

星期二 十月 21, 2014

在Linux上如何为TimesTen数据库设置hugepage

第一步,检查shmmax设置,使其大于需要设置的huge page的大小:
[root@nascds8 ~]# vi /etc/sysctl.conf


fs.aio-max-nr = 1048576
fs.file-max = 6815744
kernel.shmall = 2097152
kernel.shmmax = 536870912
kernel.shmmni = 4096
kernel.sem = 250 32000 100 128
net.ipv4.ip_local_port_range = 9000 65500
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048576


# /sbin/chkconfig boot.sysctl on
# /sbin/sysctl -p


cat /proc/sys/kernel/shmmax
4294967295


第2步,设置vm.hugetlb_shm_group


cd $TT_HOME
ls -l
drwxr-xr-x 4 oracle ttadmin   4096 Jan 26  2013 3rdparty
drwxr-xr-x 2 oracle ttadmin   4096 Aug 28 16:06 bin
drwxr-xr-x 3 oracle ttadmin   4096 Dec  1  2012 include
drwxr-xr-x 2 oracle ttadmin  69632 Sep  9 04:20 info
drwxr-xr-x 2 oracle ttadmin   4096 Jul 12 10:28 java


<=======TimesTen安装在ttadmin组下
-bash-3.2$ id -a
uid=501(oracle) gid=511(ttadmin) groups=501(oinstall),502(dba),504(asmadmin),506(asmdba),511(ttadmin)


<========ttadmin组的id为511
[root@nascds8 ~]# cat /proc/sys/vm/hugetlb_shm_group
0
# echo 511 > /proc/sys/vm/hugetlb_shm_group
<=======将511组写入 /proc/sys/vm/hugetlb_shm_group


vi /etc/sysctl.conf
vm.hugetlb_shm_group=511
vm.nr_hugepages=1034    <=======hugepage的个数,每个是2M。


第3步,设置memlock(max locked memory)


vi /etc/security/limits.conf


@ttadmin soft memlock unlimited
@ttadmin hard memlock unlimited


ulimit -l unlimited
ulimit -a



第4步,设置linuxLargePageAlignment为2
cat /proc/meminfo  | grep Huge
HugePages_Total:     0
HugePages_Free:      0
HugePages_Rsvd:      0
Hugepagesize:     2048 kB


vi ttendaemon.options
-linuxLargePageAlignment 2


第5步,启动TimesTen数据库,检查是否使用Hugepage,以及是否需要调整vm.nr_hugepages:
ipcs -a
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x0bf7d308 2752517    grid      660        4096       0
0xd4105d4c 3145734    oracle    660        211812352  27
0x00000000 3506192    oracle    660        4096       0
0x00000000 3538961    oracle    660        4096       0
0xdae1e6c4 3571730    oracle    660        4096       0
0x28008086 3604499    oracle    666        1048576    1
0x55000033 3702804    oracle    666        1048576    1


ttIsql -connstr "dsn=mk_rep_db1"


connect "dsn=mk_rep_db1";
Connection successful: DSN=mk_rep_db1;UID=oracle;DataStore=/home/oracle/TimesTen/tt1121/info/mk_rep_db1;DatabaseCharacterSet=AL32UTF8;ConnectionCharacterSet=US7ASCII;LogFileSize=32;DRIVER=/home/oracle/TimesTen/tt1121/lib/libtten.so;PermSize=900;TempSize=900;TypeMode=0;PLSQL_MEMORY_SIZE=16;PLSQL_MEMORY_ADDRESS=0x14000000;CacheGridEnable=0;OracleNetServiceName=R1120;LogBufMB=32;
(Default setting AutoCommit=1)
Command>


--ipcs -a
key        shmid      owner      perms      bytes      nattch     status
0x0bf7d308 2752517    grid      660        4096       0
0xd4105d4c 3145734    oracle    660        211812352  27
0x00000000 3506192    oracle    660        4096       0
0x00000000 3538961    oracle    660        4096       0
0xdae1e6c4 3571730    oracle    660        4096       0
0x28008086 3604499    oracle    666        1048576    1
0x55000033 3702804    oracle    666        1048576    1
0x02000107 3735573    oracle    666        1933422144 2 <============Here
0x03000107 3768342    oracle    666        16777216   2


1933422144/2048/1024=922


或者运行一个脚本hugepages_settings.sh来计算合适的hugepage大小:


-bash-3.2$ . ./hugepages_settings.sh
Recommended setting: vm.nr_hugepages = 1034


第6步,根据建议调整vm.nr_hugepages的大小:
vi /etc/sysctl.conf
vm.nr_hugepages=1034
/home/oracle/TimesTen/tt1121/bin/ttDaemonAdmin -stopserver
reboot


cat /proc/meminfo | grep Huge
HugePages_Total:  1034
HugePages_Free:    901
HugePages_Rsvd:    898               <=====used
Hugepagesize:     2048 kB



---------------
example:



-bash-3.2$ cat /proc/meminfo | grep Huge
HugePages_Total:  1034
HugePages_Free:    906
HugePages_Rsvd:    253  <=========
Hugepagesize:     2048 kB



Data store /home/oracle/TimesTen/tt1121/info/master1
There are 10 connections to the data store
Shared Memory KEY 0x12000105 ID 2883592 (LARGE PAGES, LOCKED)<===========2883592 LARGE PAGES, LOCKED
PL/SQL Memory KEY 0x13000105 ID 2916361 Address 0x26000000
Type            PID     Context     Connection Name              ConnID
Subdaemon       11782   0x09686340  Manager                        2032
Subdaemon       11782   0x096d8e98  Rollback                       2033
Subdaemon       11782   0x097a3f98  Flusher                        2034
Subdaemon       11782   0x097f4d98  HistGC                         2041


-bash-3.2$ ipcs -a


------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x0bf7d308 2752517    grid      660        4096       0
0xd4105d4c 2981894    oracle    660        211812352  23
0x55000033 2850823    oracle    666        1048576    1
0x12000105 2883592    oracle    666        570425344  1      <===========2883592
0x13000105 2916361    oracle    666        16777216   1
0x1656e538 3014666    oracle    640        169869312  18


从内存中卸载数据库:
-bash-3.2$ ttadmin -ramunload master1
RAM Residence Policy            : manual
Manually Loaded In RAM          : False
Replication Agent Policy        : manual
Replication Manually Started    : False
Cache Agent Policy              : manual
Cache Agent Manually Started    : False


内存被释放了:
-bash-3.2$ ipcs -a


------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x0bf7d308 2752517    grid      660        4096       0
0xd4105d4c 2981894    oracle    660        211812352  23
0x55000033 2850823    oracle    666        1048576    1
0x1656e538 3014666    oracle    640        169869312  18



HugePages_Total:  1034
HugePages_Free:    935
HugePages_Rsvd:      2
Hugepagesize:     2048 kB



参与此主题的后续讨论,请回复blog,或者访问我们的中文社区,跟帖"分享:在Linux上如何为TimesTen数据库设置hugepage"。 


了解更多博文信息请访问Oracle数据库产品技术支持-博客文章索引

星期二 十月 14, 2014

使用error stack 抓取存储过程的当前SQL

正常情况下,SQL的性能问题应该使用10046 trace进行分析,但是对于正在运行的存储过程,你却无法知道它卡在哪一步上了。
因为从v$session中只能看到最外层的存储过程执行,从10046看,因为prase阶段已经过去,也无法抓到当前的SQL语句。
以下介绍一个通过error stack分析正在运行的存储过程的实例。

对于一个正在运行的进程取errorstack和10046 trace:

sqlplus / as sysdba
oradebug setospid  14227
oradebug unlimit
oradebug Event 10046 trace name context forever, level 12
oradebug dump errorstack 3
<wait 1 minute>
oradebug dump errorstack 3
oradebug Event 10046 trace name context off;
oradebug tracefile_name

Format your 10046 trace file:
$tkprof <trace file> <output file>

For example:
$cd /u01/OracleAPP/oracle/admin/R1020/udump
$ls -ltr
$tkprof r1020_ora_14227.trc 14227.output

以下拿error stack输出做例子:
当前SQL还是最外层的调用:
*** 2014-09-29 11:19:01.723
ksedmp: internal or fatal error
Current SQL statement for this session:
call test(:1,:2,:3);



session当前正在执行的语句,也还是最外层的调用:
 SO: c000000cf3d469a0, type: 4, owner: c000000cf3aff038, flag: INIT/-/-/0x00
    (session) sid: 2154 trans: c000000cd6f2e558, creator: c000000cf3aff038, flag: (8100041) USR/- BSY/-/-/-/-/-
              DID: 0001-0E13-00C964B6, short-term DID: 0000-0000-00000000
              txn branch: c000000ccc19da48
              oct: 170, prv: 0, sql: c000000cfdbef790, psql: c000000cf8911380, user: 81/CRM_APP

<=====sql: c000000cfdbef790

      LIBRARY OBJECT LOCK: lock=c000000bf08347f0 handle=c000000cfdbef790 mode=N
      call pin=0000000000000000 session pin=0000000000000000 hpc=0000 hlc=0000
      htl=c000000bf0834870[c000000bf029f4e8,c000000c0fd03380] htb=c000000be508fd68 ssga=c000000be508fb30
      user=c000000cf3d469a0 session=c000000cf3d469a0 count=1 flags=[0000] savepoint=0x54223b5e
      LIBRARY OBJECT HANDLE: handle=c000000cfdbef790 mtx=c000000cfdbef8c0(1) lct=422374 pct=1 cdp=1
      name=call test(:1,:2,:3);

这时,我们在此文件中使用关键字"cursor pin"查询(因为正在被执行的cursor是被pin住的):

KGX Atomic Operation Log c000000c46c068b8
       Mutex c000000cb0bb3c50(0, 4) idn d1fc642e oper SHRD
       Cursor Pin uid 2154 efd 0 whr 5 slp 0
       opr=4 pso=c000000be618afd0 flg=0
       pcs=c000000cb0bb3c50 nxt=0000000000000000 flg=18 cld=0 hd=c000000cf96a06c8 par=c000000c59a406d8
       ct=1 hsh=0 unp=0000000000000000 unn=0 hvl=b0bb43f0 nhv=0 ses=0000000000000000
       hep=c000000cb0bb3cd0 flg=80 ld=1 ob=c000000c38ab25f8 ptr=c000000c16e28c18 fex=c000000c16e27f28
      ----------------------------------------
      SO: c000000cbbad7cc0, type: 53, owner: c000000cf3d469a0, flag: INIT/-/-/0x00
      LIBRARY OBJECT LOCK: lock=c000000cbbad7cc0 handle=c000000cf9f2bb00 mode=N
      call pin=0000000000000000 session pin=0000000000000000 hpc=0000 hlc=0000
      htl=c000000cbbad7d40[c000000c0f625548,c000000be618b050] htb=c000000be508ff28 ssga=c000000be508fb30
      user=c000000cf3d469a0 session=c000000cf3d469a0 count=1 flags=[0000] savepoint=0x54223b5f
      LIBRARY OBJECT HANDLE: handle=c000000cf9f2bb00 mtx=c000000cf9f2bc30(1) lct=2203 pct=125 cdp=1
      name=
SELECT * from test where c1= :B1 and c2=:B2 and C3=:B3
      hash=ac2274f043d741eddeab7ad9d1fc642e timestamp=09-18-2014 21:06:00

<=====找到你了。handle=c000000cf9f2bb00。

       Cursor Pin uid 2154 efd 0 whr 4 slp 0
       opr=4 pso=c000000c0fd03300 flg=0
       pcs=c000000cbabfc900 nxt=0000000000000000 flg=18 cld=0 hd=c000000cfdbef608 par=c000000cbabfd330
       ct=0 hsh=0 unp=0000000000000000 unn=0 hvl=babfd160 nhv=0 ses=0000000000000000
       hep=c000000cbabfc980 flg=80 ld=1 ob=c000000cbabfc510 ptr=c000000ca7f764e8 fex=c000000ca7f757f8
      ----------------------------------------
      SO: c000000bf08347f0, type: 53, owner: c000000cf3d469a0, flag: INIT/-/-/0x00
      LIBRARY OBJECT LOCK: lock=c000000bf08347f0 handle=c000000cfdbef790 mode=N
      call pin=0000000000000000 session pin=0000000000000000 hpc=0000 hlc=0000
      htl=c000000bf0834870[c000000bf029f4e8,c000000c0fd03380] htb=c000000be508fd68 ssga=c000000be508fb30
      user=c000000cf3d469a0 session=c000000cf3d469a0 count=1 flags=[0000] savepoint=0x54223b5e
      LIBRARY OBJECT HANDLE: handle=c000000cfdbef790 mtx=c000000cfdbef8c0(1) lct=422374 pct=1 cdp=1
      name=call test(:1,:2,:3);

<====当然还有最外层这个cursor

       Cursor Pin uid 2154 efd 0 whr 5 slp 0
       opr=4 pso=c000000c0ffd6730 flg=0
       pcs=c000000cb5fbe988 nxt=0000000000000000 flg=18 cld=0 hd=c000000cf7faf950 par=c000000cb5fbf3b8
       ct=0 hsh=0 unp=0000000000000000 unn=0 hvl=b5fbf1e8 nhv=0 ses=0000000000000000
       hep=c000000cb5fbea08 flg=80 ld=1 ob=c000000cb5fbe598 ptr=c000000cb5fbb710 fex=c000000cb5fbaa20
      ----------------------------------------
      SO: c000000be6194b10, type: 53, owner: c000000cf3d469a0, flag: INIT/-/-/0x00
      LIBRARY OBJECT LOCK: lock=c000000be6194b10 handle=c000000cf7fafb80 mode=N
      call pin=0000000000000000 session pin=0000000000000000 hpc=0000 hlc=0000
      htl=c000000be6194b90[c000000be508ffe8,c000000c0ffd67b0] htb=c000000be508ffe8 ssga=c000000be508fb30
      user=c000000cf3d469a0 session=c000000cf3d469a0 count=1 flags=[0000] savepoint=0x54223a54
      LIBRARY OBJECT HANDLE: handle=c000000cf7fafb80 mtx=c000000cf7fafcb0(0) lct=17870500 pct=1 cdp=1
      name=table_1_ff_159_0_0_0
<====以及一些LIBRARY OBJECT对象(可以忽略)

使用关键字“sqltxt(c000000cf9f2bb00)”查询可以找到该cursor使用的绑定变量的值:

Cursor#37(9fffffffbf3b2828) state=ROW curiob=9fffffffbf340638
 curflg=c7 fl2=0 par=0000000000000000 ses=c000000cf3d469a0
 sqltxt(c000000cf9f2bb00)=
SELECT * from test where c1= :B1 and c2=:B2 and C3=:B3
  hash=ac2274f043d741eddeab7ad9d1fc642e
  parent=c000000c59a406d8 maxchild=01 plk=c000000cbbad7cc0 ppn=n
cursor instantiation=9fffffffbf340638 used=1411529567
 child#0(c000000cf96a06c8) pcs=c000000cb0bb3c50
  clk=c000000be618afd0 ci=c000000c38ab2710 pn=c000000c46c068b8 ctx=c000000c16e28c18
 kgsccflg=0 llk[9fffffffbf340640,9fffffffbf340640] idx=0
 xscflg=c0151476 fl2=5000001 fl3=402a210c fl4=100
 Bind bytecodes
  Opcode = 1   Unoptimized
  Offsi = 48, Offsi = 0
  Opcode = 1   Unoptimized
  Offsi = 48, Offsi = 32
  Opcode = 1   Unoptimized
  Offsi = 48, Offsi = 64
kkscoacd
 Bind#0
  oacdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
  oacflg=03 fl2=1206001 frm=00 csi=00 siz=176 off=0
  kxsbbbfp=9fffffffbeed1f40  bln=22  avl=04  flg=05
  value=10001
 Bind#1
  oacdty=02 mxl=22(21) mxlc=00 mal=00 scl=00 pre=00
  oacflg=03 fl2=1206001 frm=00 csi=00 siz=0 off=24
  kxsbbbfp=9fffffffbeed1f58  bln=22  avl=04  flg=01
  value=11409
 Bind#2
  oacdty=01 mxl=128(100) mxlc=00 mal=00 scl=00 pre=00
  oacflg=03 fl2=1206001 frm=01 csi=852 siz=0 off=48
  kxsbbbfp=9fffffffbeed1f70  bln=128  avl=09  flg=01
  value="222410641"

<=====当前使用的绑定变量的值。



参与此主题的后续讨论,请回复blog,或者访问我们的中文社区,跟帖"分享:使用error stack 抓取存储过程的当前SQL"。 


了解更多博文信息请访问Oracle数据库产品技术支持-博客文章索引


星期二 六月 03, 2014

Linux平台上配置Oracle ASMLib和磁盘多路径

配置Oracle ASMLIB和多路径磁盘


以下文档描述如何在linux的平台下使用oracle的asmlib来访问多路径的磁盘,无论您使用哪种多路径的软件,该文档是建立在已经创建好了多路径磁盘的基础上的。这个文档给出的多路径磁盘的名称是" multipatha",和存储厂商无关。


涉及多路径软件的问题:

在使用多路径软件的时候,我们有两个问题需要面对:ASM无法同时看到2次同样的磁盘,这样会出现错误。每块盘在多路径的配置下会出现至少3次,如:

磁盘的第一条路径


磁盘的第二条路径


由多路径软件聚合的逻辑路径



下面是一个例子:假设一个系统有一个本地磁盘,为/ dev/ sda上,和一个磁盘通过外部存储连接.该主机拥有2条链路或者路径来访问这个外部的存储。


Linux的SCSI驱动会看到所有的这两条路径。他们会显示成/dev/sdb和/dev/sdc.系统可以通过sdb或者sdc来访问到同样的终端。


此时,如果我们启用多路径的软件来管理,会有一条多路径软件聚合出来的磁盘 ,如/dev/multipatha,它能通同时访问到这两个路径,也就是说,任何I/ O使用multipatha可以通过任何一条路径来访问磁盘。如果一个系统使用sdb路径,而这条链路上的电缆被拔出时,系统会收到错误。但是multipath的磁盘会知道切换到sdc的路径上去继续工作。


大部分的软件是无法识别出来多路径的配置的,它可以使用任何一条路径:sdb或者sdc或者是multpatha,并且是无法知道有什么区别的。ASMLIB也一样,默认的配置中,ASMLIB也是不会关心使用那条路径的。


ASMLIB会选择,并且只会选择一条路径,因为ASM不能同时管理两块相同的磁盘。这样我们就解决了第一个问题。ASM只会看到一条路径,而且可以正常的工作。


这就出现了第二个问题:ASM究竟看到的是那个路径?


默认的情况下,ASMLIB会选择第一条它找到的路径.Linux系统中给出的第一条路径,第一条路径取决于磁盘的驱动,它可能是multipath 或者是某一条单路径。


系统管理员希望ASMLIB始终使用多路径的磁盘!如果Oracle不是使用它,有什么指定的方式吗?


答案是没有,尽管如此,如果我们想让ASMLIB知道多路径软件的磁盘看起来是什么样的,那么我们必须通过配置来告诉它:


磁盘扫描顺序:


    ASMLIB是通过ASMLIB安装中描述的过程来把磁盘标识成ASMLIB使用的磁盘。ASMLIB通过一个磁盘扫描的过程来知道哪些磁盘是被标识过的。ASMLIB每次启动的时候都会运行一次这样的扫描,当然系统管理员可以通过/etc/init.d/oracleasm scandisks的命令来强制做一次扫描。ASMLIB会检查系统中的每一块磁盘。它会检查每一块盘是否被标识成了asmlib的磁盘,所有被标识过的磁盘都是ASMLIB的有效盘,通常情况下,ASMLIB通过OS的列表顺序来检查这些磁盘,大部分的OS都能提供合理的顺序。


上边我们说的情况,我们描述了一种OS的顺序不够好的情况。系统管理员希望ASMLIB在看到单路径的盘之前先扫描到多路径的聚合磁盘。这样ASMLIB会选择多路径聚合出来的磁盘,并把它交给Oracle使用。


ASMLib允许两种修改方式来控制磁盘扫描的顺序。第一种,它允许我们排除一部分不需要扫描的磁盘。换句话说,ASMLib会完全忽略这些磁盘。第二种,系统管理员可以指定哪些磁盘先被扫描.指定的这些磁盘会在系统中其它磁盘扫描之前完成扫描。


    多路径软件配置中可以使用任意一种方式,系统管理员可以选择排除所有的单路径磁盘的方式,这样ASMLib会忽略他们,只扫描多路径的磁盘。或者系统管理员可以指定多路径的盘被先扫描。这样ASMLib就会先发现聚合路径的盘,优先选择先发现的磁盘。



配置扫描的顺序:


ASMLib的配置文件的路径在/etc/sysconfig/oracleasm.它被链接到文件/etc/sysconfig/oracleasm-_dev_oracleasm 工具会读取后边的这个文件。这里包含了所有系统管理员通过/etc/init.d/oracleasm configure 命令配置的启动配置信息,但是命令不能配置扫描的顺序。


该配置文件中包含很多配置的变量。我们可以使用以下2个:


ORACLEASM_SCANORDER 参数指定了哪些磁盘被优先扫描;


ORACLEASM_SCANEXCLUDE参数指定了哪些磁盘在扫描的过程中被忽略掉;


该变量用空格分隔的前缀字符串列表来匹配.换言之,如果一个磁盘的开始部分和前缀相同,那么就是匹配。例如,前缀字符串sd会匹配到所有的SCSI驱动的设备。注意不是模糊匹配.参数里不要使用通配符,他们是简单的前置字符。另外注意 /dev/ 路径并不是前置字符的一部分。


注意:当扫描的过程中,只有内核知道的设备名才会被扫描得到。当使用device-mapper的时候,内核看到的设备是/dev/dm-XX。在/dev/mapper/XXX中的设备名称是udev创建的其它可读性的名称。无论是ORACLEASM_SCANORDER 还是 ORACLEASM_SCANEXCLUDE必须使用 dm 前置字符。


以下是一些例子:


注意:如果我们手工的编辑/etc/sysconfig/oracleasm,一定确保不要破坏该文件到/etc/sysconfig/oracleasm-_dev_oracleasm的链接。


多路径磁盘优先读取:


系统管理员配置ASMLib来有限读取多路径软件的聚合盘,在ASMLib的配置文件中,编辑ORACLEASM_SCANORDER变量,如下格式:


ORACLEASM_SCANORDER="multipath sd"


此时,在扫描的过程中,ASMLib会首先寻找以"multipath"开头的磁盘。多路径的设备/dev/multipatha 当然是符合的。这样它就会被优先扫描到。然后ASMLib开始寻在以"sd"开头的磁盘。这些是SCSI的磁盘。本地设备/dev/sda会被扫描到,但是它并非一个ASM的磁盘。


单路径的磁盘/dev/sdb和/dev/sdc也会被扫描到,他们是ASM的磁盘,但是ASMLib 会发现已经有了一条通道来访问它。ASMLib会忽略他们。接下来ASMLib会继续扫描其它没有匹配前置字符的磁盘。




排除但路径的磁盘:



系统管理员可以配置ASMLib来忽略但路径的磁盘。在ASMLib的配置文件中,编辑ORACLEASM_SCANEXCLUDE变量,如下格式:


ORACLEASM_SCANEXCLUDE="sdb sdc"


这里,系统管理员做了一些配置。ASMLib会排除掉完全匹配的磁盘/dev/sdb和/dev/sdc.它不会忽略其他的SCSI磁盘。这样,ASMLib在扫描的过程中就会忽略这2块磁盘,仅仅会看到/dev/multipath的磁盘,同样,Oracle会使用多路径的磁盘。


EMC PowerPath 和ASMLib


很多系统管理员会使用EMC PowerPatch来做多路径和ASMLib的磁盘配置。


尽管如此,PowerPath和2.4 kernels EMC是不支持的。Linux系统2.6内核,如RHEL 4或者SLES 9以及2.0ASMLib kernel 驱动是支持的。


关于EMC Power Patch的使用,请参考EMC Support Matrix的文档来校验任何/所有 兼容性的需求是否满足。


如果您有任何关于 ASMLib 和 PowerPath 在Linux 2.4 Kernel上的使用,如RHEL3 SLES8 等平台上的疑问,请咨询EMC




注: 该文档翻译自OTN的官方链接:


Configuring Oracle ASMLib on Multipath Disks






About

本博客由Oracle全球技术支持中国区的工程师维护。为中文用户提供数据库相关的技术支持信息,包括常用的诊断工具、诊断方法、产品新特性、案例分析等。此外,MOS也陆续推出各类中文内容:技术通讯统一发布在Note 1529795.1 中,中文文档列表更新在Note 1533057.1 中,网上讲座请查看MOS文档 1456176.1,在"Archived"中可以下载历史的录音和文档。

Search

Archives
« 五月 2016
星期日星期一星期二星期三星期四星期五星期六
1
2
3
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    
       
今天