koko的oracle杂货铺

 

Oracle Redo log Structure初探


 粉丝网地址

http://www.oraclefans.cn/forum/showtopic.jsp?rootid=25428&CPages=1

 
 
 
 

一部经典的电影不是你正在看的电影,而是你正在重看的电影。


QZone Editor

看了不少影评,这个叫"高斯控"的数学系的哥们,算是解读的不错的一位了,()里的是本人自己的想法。


原文地址
http://movie.douban.com/review/3462102/?start=100

 

第一个问题:为什么要潜入梦中去呢。
Cobb讲: 潜入梦中可以改变一个人的想法, 一个人就是一个想法。想法变了,它就不是它了。

第二个问题: 怎样骗过人呢?  
Cobb讲:人在醒的时候,其实有一段时间是根本分不清梦中的是真的,还是眼前的是真的。
它实际是通过一些标准来判断是己是不是在现实中。
这其实就是整个电影的最关键。也是整个论文的题目和基本假设。
那么Cobb是怎么做到的呢,这是Cobb说他是靠陀螺。如果它转不停,就是在梦境中,如果它能停下来,就不是在梦境中。
观众看到这很容易懂。实际上我要问,这说明什么,梦境有什么特点。
诺兰是建筑迷,免不了的也是几何迷,它其实是给观从上了一堂示例教学的几何课。
我们的空间是三维的,如果你把时间算进去就是四维的,如果时间这个维度上画圈,那个陀螺就转不停了。

接下来一个问题,为什么要玩非欧空间。
这个道理很简单,造梦师能想到的东西是有限的,如果你想把人困住,就要给它一种无限的错觉。
如果你把被骗的人想成是一只小虫子的话,只能在二维的世界中到处跑。
如果是欧式空间的话是个平面,设计的梦是有限,你只能设计一个很大的圆。
那这只小虫总有一天会跑出这个圆的。
但是如果这是一个球面的话,就不一样了,不管小虫如何跑,都跑不出这个球表面。
  
引申一个问题测一下你的理解,Arthur用的图腾是色子,Arthur怎么来验是不是在梦中呢?
答,如果在梦中,Arthur的色子数会以周期性重复。
(感觉说反了,其实Arthur强调了自己的骰子是灌了铅的骰子,这样骰子在现实生活中掷出去,向上和向下的面就是固定的,是有规律的,小萝莉的象棋也类似)

以一维为例,一维的欧式是直线,非欧的是圆。
如果你取出直线的一部分,再取出圆上的一部分,你得到线段和圆弧。
如果线段比较短,或是圆的半径比较大的话,这两者的差别就非常小,你就分不出来了。
但是在全局上,有则本质的区别。
直线向二端无限申展,而圆只能重复自己。
片中前者是真实世界,后者就是梦中了。

实际上这件事玩数学的己经知道了有二三百年了,最开始想这个问题的人其实是高斯  
高斯最初作过一段时间的测绘工作,于是发现在地面看的直线在塔楼上看不是直的。
于是问究竟什么是弯,什么是直,想了一下,发现这个问题会影响到许多问题,几何学要重写。  
高斯想到这个问题,便没有给答案,但他给出了几何概念的解析定义,于是创立了微分几何。
因此我们才知道非欧空间中的一个重要特性,三角形的内角合不是180度。并且方法也可以弄到高维去。
这还不算完,不久高斯的学生黎曼问了一更牛的问题,高斯只是把图形弄弯了,作标系还是直的。
黎曼问,作标系能不能是弯的呢?如果作标系是弯的,那长度角度还有什么意义吗?
在梦中,你怎么知道真实,这是一个Inception中哲学问题。
在一个曲线作标中,你怎么画直线,这就是把哲学问题转化成了等价的数学问题。
于是黎曼在曲线作标上,又搞出了一套东西,就是今天的黎曼流形和黎曼量度。

“人就是一个想法,如果想法一被人替换,就跟把这个人杀死了一样。
实际上片中的Cobb是最理解这一点的人。
他不仅知道这种想法的威力,也知道这种想法的杀伤力。
就是靠这一点,他杀死的自己的妻子,虽然他是无意的。
他只是想知道他是否能把想法植入别人的脑子中,而让他们以为是自己想法而混然不觉。
而他想植入的想法就是“让一个人把现实当成梦,而把梦当成现实”,当然他成功了。
(其实Cobb植入的想法是“对周围一切保持质疑,认清梦境”,他的目的是让妻子放弃梦中的一切回到现实中,但他显然没有想到植入的想法的副作用,妻子回到现实依然怀疑自己生在梦境需要通过自杀回到“现实”)
然后他就悲剧了,妻子就跳楼。
实际上Cobb纠结的不只是对妻子的感情,还有对想法本身的恐惧。
因为这个想法的力量太大了,他自己都跑不出来。
实际上别人也可以用梦杀死它,他也无能为力。
而且他自己也不能断定自己的想法就是真实的,没有被人植入,自己没死。
这个问题实际上正是一个在逻辑上找不到答案,“不可知”的问题。
映射着我们的现实。导演成功地用构造法证明了一个可悲的不可知论:“虽然想法对一个人重要,换掉一个人的想法就跟杀了一个人似的,但一个人的想法究竟是他自己的,还是被别人植入 的,他可能永远不知道。”
这就是在曲线的作标系中如何画直线的问题。
实际上是没有答案的。

(结局的可能性太多了,讨论下去几乎无止境,特别是有人提到其实Cobb真正的图腾不是那个陀螺,而是自己孩子的脸,我觉得这个问题再讨论就基本无解了,陷入了一个死循环,因为影片里提到是否在梦境的判断标准只有这个陀螺,骰子和象棋虽然也是但是没见使用过,所以如果陀螺一旦沦陷,那这个电影中能让人判断什么是梦境什么是现实的标准,也就不存在了,直接崩溃)

不要以为外国的作家都跟文艺青年似的。
在外国的许多作家的科学素质是很好的。
写爱丽丝梦游仙境的就是玩数学拓扑的。
像诺兰这种学建筑的,几何功底好不奇怪。
有人还说他还读图灵和哥德尔。
要是真那样,不可知论就更容易理解了,图灵就是玩混沌出名的。哥德尔就是证明公理体系存在不可知。
他们不读数学,但他们可以通过各种方法读到科学的思想和影响力。
西方的科学对文化的渗透是无处不在的。
  
不要以为没有深度的东西要挖,做梦人人都想过,
如果给你一个机会偷人东西,你会偷什么?
如果给你一个机会害别人,你最想毁掉他的什么?
大多数人会以为偷走人的钱,毁掉他的官位吧。
那种手段只对一般人有用。
真正的英雄像太祖式的人物,
没钱自己弄,被夺权了也一呼百应。
有人想过偷走人想法,植入想法吗?
这才是弄掉天才和英雄的狠办法。
(有道理,所以说洗脑才是最可怕的,想想我们的教育,哎,不说了)
  
“文治胜过武功“,不是所有人都理解的。
什么八股取士,独尊儒术,
内圣外王,礼化四夷。
老祖宗天天讲的,到时都想不起来。
中国有文化不等于中国人都是有文化的人。
玩过日不落的也会有这种见识的,
London写剧本的圈子连Nobel都拿了几回的。
人家是有玩深刻的见识的,人家玩的文化不只是通俗文化和流行文化。

世界可知吗?我们可以将认识分解为两种:
    理论性认识:认识一个规律,比如认识相对论的本质等。
    知识性认识:了解一个物体的存在状态,比如认识到太阳系有九大行星等。
    三百多年前,科学的进展,特别是物理学的进展,似乎在暗示人类:没有不可认识的事物,只有未被认识的事物。当然,那个时候,真正完备的科 学研究体系才初步形成,下这样的结论显然为时过早。
    而现在,众多的科学事实都明确指向:世界是不可知的。
    其一,不确定性原理。这个理论说明,我们不可能同时精确的测量出粒子的位置和动量。别忘了,世界完全可知才叫“可知”,当然,我并不清楚 是否这一条定律就足以完全推翻可知论,但毫无疑问,这对可知论的撼动是相当巨大的。
    诚然,这个理论至今仍然有很多疑点和漏洞,但它已经是一条公认的物理定律,历经了数十年的发展,经受了实验的考验,并在生产中有所应用, 推翻他是相当难的。至少不是那些哲学家们随便说说就能推翻的。
    其二,哥德尔定理。这个定理表述为:在任何一个包含了自然数的形式系统中,一定有不可判定的命题。这应该至少可以说明,在科学理论上,世 界是不可知的,因此整个世界也就不可知。与不确定性原理不同的是,这是一条完全基于理论推导的数学定律,他完全不可能被推翻。
    其三,关于观察和存在的关系。这一点本质上和第一条相同,薛定谔的量子猫,如果不观察就处于非死非活的状态,这是量子力学对微观的描述 (量子猫的观测对象是铀原子,不是猫,算微观)。推广到宏观物体,这种效应非常小,但并不为零。这和我国古代哲学家王守仁的看法异曲同工:“ 你未看到此花时,此花与汝同归于寂,你来看此花时,则花颜色一时明白起来,便知此花不在你的心外.”如果世界的存在状态和人们的观察状态有关,那我们显然 不可能认识一个本身都不客观存在的事物。
    物理学上有一个著名的“延迟实验”,让光子通过两条可能的路径,具体走的那一条,可以通过之后再决定。把光子推广到实物粒子仍然有效,只 是操作难度更大。请注意两点,1:这个事件发生的具体状态是在事件发生之后决定的;2:事件发生的具体状态由人来决定,我们可以主观决定。如此看来,世界 存在的客观性确实值得怀疑。
    这里有点攻击唯物主义的意思,因为唯物主义自己声称科学要与实验相结合,如果实验结果与他不符,则不排除这一巴掌打到自己脸上的可能。当 然,这个观点的漏洞很大,首先,量子力学必须正确,但量子力学在宏观上并没有被应用,只在微观上被实验证实,量子效应如果用到宏观物体上,他与承认世界客 观存在的偏差将极小极小,如此小的时空在实践上肯定是没有太大意义的。其次,量子力学之所以会得出这样的结果,是应为它采用了对世界的另一种描述方式,这 与用常规方法描述世界,再加一个“量子参数”来修正它,哪个才是对的?这不过是看哪个更好用而已。较为简单的数学过程和较为完美的物理解释选择了前者。
    其四,为什么的归结问题
    “在对自然的认识过程中,我们会提出许多的为什么,而你试图去解答一个为什么的时候,你并没有彻底地回答他,而只是将这个问题归结到另外 一个为什么上,通常后者使人更感可信,或者更难以回答。而这个过程还可以继续下去,形成了一条由为什么连成的链条。”
    ---------------------《坍缩》
    这注定了至少有一个为什么是不可解释的。
    其五,我们对物理理论,与其说是认识,不如说是猜测。除数学逻辑中既可能证明又可能证否的命题外,还有三类命题:可能证明但不能证否的, 比如“这里将发生一场灾难”。不可能证明但可以证否的,不如“没有人能登上这座山”。既不能证明也不能证否的,比如“圆周率中有无限个为零的小数位”。很 不巧,所有的物理定律都是不可能证明但可以证否的命题,我们永远也不能确定他是对的,但他随时可能被反例推翻。不要说“实践证实理论”,因该说“实践证否 理论”。对这样的理论,与其说是认识,不如说是猜测。(唯心主义或许可以避免这一问题,但他仍然免不了不可知)
    其六,我们永远不能确信我们从外界得到的信息是真实的。这一点本质上和第五点相同。我们如何才能了解世界呢?看?听?想?那不过是视觉, 听觉,和大脑中的化学反应。这些完全有可能是假的,比如,你的大脑被装到了一个瓶子里,并在特定的地方接上电极,模拟视觉,听觉,嗅觉等,而你自己还以为 自己活得好好的呢。或者,你是昨天才出生的,你大脑中的记忆不过是被人为输入的,因此你误认为你已经生活了很多年。你永远也没办法确信眼前的是真实,不过 是凭经验猜测而已。
    其七,我们不具备完全认识世界的信息基础。认识一个事物(知识性认识)的过程不过是将那一个事物的信息储存在大脑中,对于整个宇宙来说, 这不可能做到。因为整个宇宙的粒子排列总可能数比我们大脑的要多,而我们的记忆信息不可能比我么大脑的信息多,因此不可能将整个宇宙的信息装进大脑,也就 不可能认识整个宇宙。
    综上所述,世界是不可知的。

(其中第六点,我在看完黑客帝国的时候就想过这个问题,我们所认识的所有的一切,完全取决于自己的器官采集了相应的信号之后,通过某些途径传达给了大脑,而在大脑中形成的一系列化学反应。打个比方来说,你现在看到你自己的五根手指头,有血有肉有骨头,能自由活动,能感觉到疼痛,
但是事实是,你到底有没有“手”这个东西,都是无法确定的,因为你之所以觉得你有“手”这个物体,一直是你大脑中的信号“告诉”你而已,或者连所谓的“大脑”也不存在,存在的只是你的想法。你认为它在,它就在,你认为它不在,它就不在,完全取决于你的思想。
再往深层次想一点,结合盗梦和黑客两部电影,就算是思想,你如何知道你的这个想法是你自己的,还是别人告诉你的?

举个现实生活中的例子,有很多人是红绿色盲,分不清红绿,但是换个思路,如果这个世界上本身就不存在红和绿这两个颜色呢?说不定,那些色盲的人看到的才是真正的“颜色”呢?

说到底,这个问题就变成“我们如何得知自己知道的东西是真实的?”或者更彻底一点,“什么是真实?“
就像黎曼问的,如果坐标都是弯的,你怎么画直线,或者什么是直线?
也像电影的主题“我们如何判断梦境和现实?”
这基本上是无解的。)

 
 
 
 

折腾BBED


文章转到这里

http://www.oraclefans.cn/forum/showtopic.jsp?rootid=22766

 
 
 
 

关于一致性HASH


consistent hashing


普通hash算法实现分布式的时候,当节点数量发生变化时,hash重组的代价太大,于是就有了下面提到的consistent hashing.

 

 基本模型为一个2的32次方均匀分布的同心圆,首先计算出节点的hash值,将其放在同心圆对应的位置上,用同样的hash运算算出key的hash值,对应到圆上相应的位置,由此位置顺时针找过去,找到的第一个节点就为该值的接受节点,找完2的32次方后没找到,放到第一个节点上。

当增加或减少节点时,受影响的只会是上一个节点和新增加节点之间的这一部分值,其他值不会受到影响。

 
当然根据这个模型,如果节点数比较少的话,每个节点的负载是不均匀的,因此很多consistent hash算法一般会采用虚拟节点的概念,比如上面这个图,如果将这5个物理节点配置成100或200个虚拟节点,根据虚拟节点来进行分布,然后再映射到物理节点,就可以很大程度上解决分布不均衡的问题。

 



 
 
 
 

瞎想


 最近想的一些东西,记录下。

   每当我们说到应用的时候,我们到底是从什么角度出发的?什么叫应用,网络,存储,机器,OSDBAPPServJAVA它们是如何看待“Application”这个词的?比如对于一个交换机而言,在它的眼里,那一串一串的100100000100100101010100101有哪一段是属于自己可以理解可以读懂的?当它读懂了自己可以读懂的那一部分以后,剩下的那一部分它称之为“数据”的东西,到底是来自何方?在192.168.0.1的后面是一个什么类型的实体?如果是存储?那到底是HDS还是IBM或者是NetApp?如果是机器,那到底是一台570PCServer或则只是一个刀片?再比如对机器而言,当CPU从内存中取出一条指令,它知道这条指令的背后的OS是什么吗?是AIXLinux?或者是Windows? OS而言,当它接到一个命令,读取文件A上的第M到第N个块,它知道这个命令是谁发起的吗?如果是一个数据库?ORACLE,Mysql还是Postgresql? 对数据库而言,当它接到一个sql,它会知道这个sql发起方是一个Websphere还是一个Weblogic?

       当我们在思考这些问题的时候,不妨想想,我们发现某个系统“IO”存在问题, 在这里IO到底是指什么?这个IO到底会涉及到哪些环节呢?数据库,OS,机器,网络,存储,再细一点呢?比如数据库调用OS的方法例如OPEN(),读取文件X的块M到块NOS的卷管理软件VM分析这个指令后,变为读取LV
A
上的地址a到地址c,然后根据缓存中保存的VGDA的信息比如PPsize,初始偏移量,映射关系等来映射成读取“物理卷”PV B上的地址f到地址h, 当这些事情都做完以后,VM提示CPU将这个指令通过南北桥发给了在SCSI总线上的一块SCSI卡,SCSI卡在得到指令后通过网络转给了远端的某个磁盘阵列,由于OS所称的“物理卷”PV B阵列并不认识,对它来讲,PV
B
只是一个逻辑盘,它可能对应自己的很多块物理磁盘,于是阵列上RAID卡在接到这个指令后需要做一个映射,变成读取磁盘1到磁盘8上若干个stripe,首先是stripe m所对应的磁盘1上的segment 或者叫strip(m,0)所包含的block1,block2,block3,block4,接着是磁盘2上的segment strip(m,1)所包含的block1,block2,block3,block4。。。。。。然后是stripe n所对应的磁盘1上的segment
strip(n,0)
所包含的block1,block2,block3,block4。。。。。。最后磁盘1的驱动器接到指令后提示步进电机带动0号磁头开始寻道,SCAN,读取0号盘片的00盘面的第16扇区,接着是1号磁头0号盘片01盘面第16扇区,然后是2号磁头1号盘片02号盘面第16个扇区,3号磁头1号盘片03号盘面第16个扇区。。。。。。至此整个过程才算结束(当然实际情况要比这个复杂的多的多)。

       在上面这个例子里,可以导致系统“IO”出现问题的环节很多,比如通信:数据库与OS的通信(调用OS的方法)OS的卷管理程序与CPU之间的通信,CPU与内存之间的通信,CPU与北桥芯片之间的前端总线,主板上的南北桥芯片,南桥与SCSI总线之间的PCI总线,PCI总线与SCSI适配器(也就是SCSI)之间的SCSI总线,SCSI卡与网卡之间的通信,网卡与阵列RAID卡之间的网络通信(交换机,网线,防火墙,路由)RAID卡与磁盘驱动器之间的SCSI总线,磁盘驱动器与磁头臂之间的控制电路。再比如缓存,数据库的缓存机制,OS的缓存机制,阵列的缓存机制等等。这些环节里,哪些

       举个例子,我们在数据库层发现等待事件logfile sync,我们能想到的会有logbuffer大小,每秒redo大小,user
commit/rollback
次数 ,LGWR写出效率等等,除了这些我们是否还应该考虑到redo logfile所在的LV归属的VG下有哪些PV,这些PV代表的LUN所对应的存储阵列中的物理磁盘的RAID类型,所采用的缓存策略,这个LUN和另外哪些LUN一起同属于存储阵列里的N个物理磁盘,其他的这些LUN又对应成OS的哪些LV,这些LV又对应了数据库中的哪些数据文件,上面都有些什么对象等等。

 

       再举个例子,当我发现系统很缓慢,发现数据库里出现了比较多的IO等待事件,我们转到操作系统,发现操作系统vmstat wa列很高,由此判断系统此刻IO很繁忙,那么这个繁忙是否真的就代表磁盘阵列里某几个磁盘的步进电机正在疯狂的干活?如果不是,那瓶颈是在哪里?上面那些环节中哪些又可能存在瓶颈呢?是物理的可能性更高点,还是逻辑的呢?

有关RBA



有关RBA


rba = redo byte address

rba用于快速的定位redo entry(redo file->redo block->redo entry)

rba可以不唯一,比如我们用resetlogs打开数据库后,redo sequence会被重置。

buffer cache中的dirty block都可能做过很多次改动,每次改动都会有相应的redo entry生成,一个dirty block被读到buffer cache后第一次被改动时生成的的redo entry的rba叫做这个dirty block的low rba,相反最近一次更改的rba叫做high rba.

buffer cache中有条很重要的hash chain:ckpt queue list,这个list上是一个个首位相连的buffer header,这些buffer header指向buffer cache中的dirty block,这些dirty block在第一次被改动时其buffer header就被链到ckpt queue list上,每个dirty block的buffer header在ckpt queue list只出现一次,而不论这个dirty block随后是否还被更改过(改一次和改N次对于dbwr是无所谓的,dbwr只要知道是否dirty而不需要知道dirty了多少次)。ckpt queue list上所有的buffer header按照其指向的dirty block的low rba进行排序,因此最先被更改的dirty block会排在前面,由于dbwr是按照ckpt queue list上的顺序去写dirty block(只是按照这个顺序,具体写应该是从lru-w或者叫write list,dirty list上完成),所以最先被改的block最先被写出,当dbwr写完dirty block后就把其buffer header从ckpt queue list上摘掉,因此ckpt queue list的最小的那个low rba就定期的被ckpk进程记录到control file中(low cache rba),作为记录dbwr写dirty block的进度,同时也作为instance recovery开始的位置(因为在这个low rba之前的所有redo entry对应的dirty block都已经被dbwr写到data file了),而current redo log file中最后的redo entry的rba将作为on disk rba也被ckpk进程写进control file,同时ckpt进程还会写scn,heartbeat值.

instance recovery从low cache rba开始,到on disk rba结束,那么这之间的redo entry的条目数就直接决定了instance recovery的时间,也间接决定了dbwr写dirty block的速度。这个条目数由fast_start_mttr_target或fast_start_io_target等参数决定,同时还必须满足小于最小log file的90%



 
 
 
 

思维定式


一个简单比较的sql

SQL> set linesize 200
SQL> set pages 0
SQL> SELECT *
  2    FROM (  SELECT DISTINCT
  3                   hotel_id,
  4                   gisid,
  5                   chn_name,
  6                   longitude,
  7                   latitude,
  8                   chn_address,
  9                   POWER ((ABS (120 - longitude) * ABS (120 - longitude)
 10                       + ABS (35 - latitude) * ABS (35 - latitude)),0.5)AS distance
 11              FROM htl_ii.htl_hotel
 12             WHERE     longitude > 0
 13                   AND latitude > 0
 14                   AND longitude IS NOT NULL
 15                   AND latitude IS NOT NULL
 16                   AND gisid > 0
 17                   AND active = 1
 18                   AND HOTEL_SYSTEM_SIGN = '01'
 19          ORDER BY distance ASC)
 20   WHERE ROWNUM <= 5;

Elapsed: 00:00:01.47

Execution Plan
----------------------------------------------------------
Plan hash value: 997346329

-----------------------------------------------------------------------------------
| Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |           |     1 |   325 |   451   (2)| 00:00:06 |
|*  1 |  COUNT STOPKEY        |           |       |       |            |          |
|   2 |   VIEW                |           |     1 |   325 |   451   (2)| 00:00:06 |
|*  3 |    SORT UNIQUE STOPKEY|           |     1 |   117 |   450   (1)| 00:00:06 |
|*  4 |     TABLE ACCESS FULL | HTL_HOTEL |     1 |   117 |   449   (1)| 00:00:06 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(ROWNUM<=5)
   3 - filter(ROWNUM<=5)
   4 - filter("LONGITUDE" IS NOT NULL AND "LATITUDE" IS NOT NULL AND
              "LONGITUDE">0 AND "LATITUDE">0 AND "GISID">0 AND TO_NUMBER("ACTIVE";)=1 AND
              "HOTEL_SYSTEM_SIGN"='01')


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       2014  consistent gets
          0  physical reads
          0  redo size
       1468  bytes sent via SQL*Net to client
        492  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          5  rows processed

 

修改以后


SQL> SELECT gisid,
  2         chn_name,
  3         longitude,
  4         latitude,
  5         chn_address,
  6         hotel_id,
  7         POWER (distance, 0.5)
  8    FROM (  SELECT DISTINCT
  9                   hotel_id,
  10                  gisid,
 11                   chn_name,
 12                   longitude,
 13                   latitude,
 14                   chn_address,
 15                   --POWER (
 16                   --(
 17                   ABS ( (120 - longitude) * (120 - longitude))
 18                   + ABS ( (35 - latitude) * (35 - latitude))
 19                      --),
 20                      --0.5)
 21                      AS distance
 22              FROM htl_ii.htl_hotel
 23             WHERE     longitude > 0
 24                   AND latitude > 0
 25                   AND longitude IS NOT NULL
 26                   AND latitude IS NOT NULL
 27                   AND gisid > 0
 28                   AND active = 1
 29                   AND HOTEL_SYSTEM_SIGN = '01'
 30          ORDER BY distance ASC)
 31   WHERE ROWNUM <= 5;

Elapsed: 00:00:00.06

Execution Plan
----------------------------------------------------------
Plan hash value: 997346329

-----------------------------------------------------------------------------------
| Id  | Operation             | Name      | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |           |     1 |   325 |   451   (2)| 00:00:06 |
|*  1 |  COUNT STOPKEY        |           |       |       |            |          |
|   2 |   VIEW                |           |     1 |   325 |   451   (2)| 00:00:06 |
|*  3 |    SORT UNIQUE STOPKEY|           |     1 |   117 |   450   (1)| 00:00:06 |
|*  4 |     TABLE ACCESS FULL | HTL_HOTEL |     1 |   117 |   449   (1)| 00:00:06 |
-----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter(ROWNUM<=5)
   3 - filter(ROWNUM<=5)
   4 - filter("LONGITUDE" IS NOT NULL AND "LATITUDE" IS NOT NULL AND
              "LONGITUDE">0 AND "LATITUDE">0 AND "GISID">0 AND TO_NUMBER("ACTIVE";)=1 AND
              "HOTEL_SYSTEM_SIGN"='01')


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
       2014  consistent gets
          0  physical reads
          0  redo size
       1479  bytes sent via SQL*Net to client
        492  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          5  rows processed

 单从执行计划和统计信息来看这2个sql几乎没有任何分别,返回结果数,逻辑读,排序记录数等等都一样,唯一不同的就是执行时间。

说说这个sql,当我拿到这个sql的时候,1s的执行时间非常让我费解,不就才1w行记录的全表读么?70多个字段,1k的平均行长,总表大小16m,至于用1s才返回结果吗?当我发现()里的power以后,我顿时明白了,这样的问题再简单不过了,是先做运算再排序然后返回前N条更快,还是先排序然后返回前N条再做运算更快?一个power执行了1w次,一个power执行了5次,谁会更快?

 从这个问题延伸开来,当sql涉及到排序然后返回固定条数记录的时候,比如分页,我们是不是该认真考虑下这个问题:是不是有些计算,是可以在最后返回的记录数出来以后才进行而且并不影响最终结果的?比如这个例子中的power,再比如简单点的+,-,*,/,复杂点的还有trunc,to_date,to_char,ceil,substr,regexp...等等


 


 
 
 
 

生产环境修改隐藏参数需谨慎!


事情的经过是这样:

   某日某菜鸟dba在巡检生产数据库时发现alert log出现如下错误:

   ORA-00600: internal error code, arguments: [qkabix], [0], [], [], [], [], [], []

   经过检查相应的trace file和在metalink上搜索和比对相应的执行计划,发现和某一未经过确认的bug相类似

参见 Doc ID:743212.1

 

Cause

The problem could be related to a CBO ( Cost Based Optimizer ) issue when a query uses a bitmap access paths for b-tree indexes.

It is reported in Bug 5945798 but not confirmed.


Solution



One possible workaround to avoid the error is to disable the optimizer to produce bitmap plans for B-Tree indexes even if
there is no bitmap index anywhere in sight:

- at session level
     sql> alter session set "_b_tree_bitmap_plans"=false;

- or at system level 
     sql> alter system set "_b_tree_bitmap_plans"=false;

- or in the init.ora
     _b_tree_bitmap_plans = false

 菜鸟惊呼:哇塞,我的系统也能出现如此高档,如此牛逼闪闪,如此(此处为响应祖国六十华诞,自行省略若千字)。。。的bug?这不是我梦寐已久,连做春梦都会在头脑中闪现的场景么?难道上天终于开了眼,要眷顾一下我这个小菜鸟?

于是乎,他大胆的做出一个决定,修改此隐藏参数:

alter system set "_b_tree_bitmap_plans"=false scope=both sid='racn1';

故事到这里就结束了吗? 不,这显然不合乎常理,冥冥之中,菜鸟总感觉会发生点什么,但是他又说不清楚,就想看王家卫的电影一样,总感觉电影想要放个屁出来,但往往等了90分钟后,却连个屁也没等到,甚至连口臭味都没有闻到,于是觉得导演的这个屁肯定是在不经意间就放出来了,但是无奈吾等众生天资愚钝,未能领会到大师的屁意,让这人间美屁就这样流逝掉,实在是暴殄天物。但是转念一想,我们花了90分钟的生命,不管花没花银子,我们至少该得到些什么啊?浑身上下一摸,连根毛都没多,最后终于恍然大悟:原来我们是被这种欲屁还休的手段足足忽悠了足足90分钟,到头来还被电影屁服的屁滚尿流。

扯远了。。。

就在修改完参数的第二天,菜鸟像往常一样打开灰常牛逼闪闪的工具secureCRT,曾经有菜菜鸟问过菜鸟,secureCRT和CRT有什么分别?菜鸟虽菜,但是英文不烂,再加上入行也有些日子了,自然是对菜菜鸟这样的鸟问题十分不屑:“secureCRT都不知道?你英文也太烂了,CRT+secure 就是加长加宽加安全版的CRT,知道了不?”。菜菜鸟还是一头雾水:“secure是安全我知道了,但加长和加宽是如何理解呢?”,菜鸟一脸的牛逼样,手指在菜菜鸟的鼻子上点啊点的:“你个菜鸟,secure+CRT自然是比CRT要宽了吧,你再换个角度,不就比CRT要长了嘛”。

又扯远了。。。

菜鸟的手指熟练在键盘上击打着,随着手臂的移动,上上下下左左右右bbaa,仿佛是在钢琴边弹奏着一首美妙的曲子,无数个日日夜夜,当别人花天酒地灯红酒绿,当别人酣酣入睡沉入梦乡,菜鸟都依然坚守在他的键盘前,一刻也不停息的敲着打着,仿佛键盘就是菜鸟的恋人,他熟悉恋人身上的任何一个部位,任何一个细节,这些部位和细节,他都触摸过无数遍,菜鸟不用去看键盘,他甚至不用去考虑自己的手指的位置,但此刻,菜鸟的手却停住了,他的左手食指和无名指与右手的中指和食指分别停在了CaiB这四个键上。

就在secureCRT上,随着vmstat -wt 1的敲下,菜鸟看到了一个令他震惊的现象,id列居然降到了30,在早上这个时间段,id列应该是在80以上才正常啊,莫非,系统也有晨勃的习惯?ps auxw|sort -rn +2|head -30显示有一个LOCAL=NO的oracle进程一直占据着第一位,通过pid去数据库查找,发现此sql:

SQL> SELECT     sms_id, cha_content, MESSAGE
  2        FROM callcenter.t_sms_sndqueue
  3       WHERE (    sms_sta_id = 5
  4              AND on_dat > TO_CHAR (SYSDATE - 1, 'YYYY-MM-DD HH24:MI:SS')
  5             )
  6          OR     (sms_sta_id = 2 OR sms_sta_id = 6)
  7             AND on_dat BETWEEN TO_CHAR (SYSDATE - 4 * 3600 / 86400,
  8                                         'YYYY-MM-DD HH24:MI:SS'
  9                                        )
 10                            AND TO_CHAR (SYSDATE - 900 / 86400,
 11                                         'YYYY-MM-DD HH24:MI:SS'
 12                                        )
 13             AND ROWNUM < 30;

12 rows selected.

Execution Plan
----------------------------------------------------------
Plan hash value: 338642532

--------------------------------------------------------------------------------------
| Id  | Operation           | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |                |  3228K|   443M| 21616   (1)| 00:04:20 |
|   1 |  COUNT              |                |       |       |            |          |
|*  2 |   FILTER            |                |       |       |            |          |
|   3 |    TABLE ACCESS FULL| T_SMS_SNDQUEUE |  3228K|   443M| 21616   (1)| 00:04:20 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("SMS_STA_ID"=5 AND "ON_DAT">TO_CHAR(SYSDATE@!-1,'YYYY-MM-DD
              HH24:MI:SS') OR ("SMS_STA_ID"=2 OR "SMS_STA_ID"=6) AND
              "ON_DAT">=TO_CHAR(SYSDATE@!-.1666666666666666666666666666666666666667,'YYYY-MM
              -DD HH24:MI:SS') AND "ON_DAT"<=TO_CHAR(SYSDATE@!-.0104166666666666666666666666
              666666666667,'YYYY-MM-DD HH24:MI:SS') AND ROWNUM<30)


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
      97846  consistent gets
          0  physical reads
        180  redo size
       2069  bytes sent via SQL*Net to client
        492  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         11  rows processed

这个sql显然不是最近新上的玩意,如果这种用字符存储日期的表设计被菜鸟发现,菜鸟肯定会将其否决掉,这个sql显而易见是有问题的,但是问题是,既然不是新上的玩意,那为何这个sql之前没有问题呢?菜鸟想到了那个该死的隐藏参数,难道加了参数以后导致了执行计划的改变?

将参数改回原来的值后:


Execution Plan
----------------------------------------------------------
Plan hash value: 3230192025

-------------------------------------------------------------------------------------------------------------
| Id  | Operation                           | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                    |                       |  3228K|   443M|     7  (29)| 00:00:01 |
|   1 |  COUNT                              |                       |       |       |            |          |
|*  2 |   FILTER                            |                       |       |       |            |          |
|   3 |    TABLE ACCESS BY INDEX ROWID      | T_SMS_SNDQUEUE        |  3228K|   443M|     7  (29)| 00:00:01 |
|   4 |     BITMAP CONVERSION TO ROWIDS     |                       |       |       |            |          |
|   5 |      BITMAP OR                      |                       |       |       |            |          |
|   6 |       BITMAP CONVERSION FROM ROWIDS |                       |       |       |            |          |
|*  7 |        INDEX RANGE SCAN             | SMS_CHA_INS_STAID_IDX |       |       |     1   (0)| 00:00:01 |
|   8 |       BITMAP OR                     |                       |       |       |            |          |
|   9 |        BITMAP CONVERSION FROM ROWIDS|                       |       |       |            |          |
|* 10 |         INDEX RANGE SCAN            | SMS_CHA_INS_STAID_IDX |       |       |     1   (0)| 00:00:01 |
|  11 |        BITMAP CONVERSION FROM ROWIDS|                       |       |       |            |          |
|* 12 |         INDEX RANGE SCAN            | SMS_CHA_INS_STAID_IDX |       |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("SMS_STA_ID"=5 AND "ON_DAT">TO_CHAR(SYSDATE@!-1,'YYYY-MM-DD HH24:MI:SS') OR
              ("SMS_STA_ID"=2 OR "SMS_STA_ID"=6) AND "ON_DAT">=TO_CHAR(SYSDATE@!-.166666666666666666666666666666666
              6666667,'YYYY-MM-DD HH24:MI:SS') AND "ON_DAT"<=TO_CHAR(SYSDATE@!-.01041666666666666666666666666666666
              66667,'YYYY-MM-DD HH24:MI:SS') AND ROWNUM<30)
   7 - access("SMS_STA_ID"=5)
  10 - access("SMS_STA_ID"=2)
  12 - access("SMS_STA_ID"=6)


Statistics
----------------------------------------------------------
          1  recursive calls
          0  db block gets
         10  consistent gets
          0  physical reads
          0  redo size
        457  bytes sent via SQL*Net to client
        481  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

果不其然,就是这个该死的参数导致此sql执行计划改变,当然,那个sql本身是有问题的,但如果不是参数的修改,它或许根本不会浮出水面。

菜鸟终于送了一口气,虽然早点到公司小息一会并顺便做个春梦的计划泡汤,但毕竟,问题总算解决了,虽然这个倒霉的问题,完全出自自己之手。

 
 
 
 

有关grid control(2)


接上篇

在成功添加完agent以后,我们可以手动将数据库添加到OMS的targets中。

添加起来比较简单,在这里就不一一赘述。

主要介绍下遇到的主要问题:

如果之前添加过一次,然后删除了,再次添加会报错,一般有可能会遇到下面几种错:

ORA-20600: The specified target is in the process of being deleted

或者报在执行sysman下某个trigger时出错。

主要原因就是sysman下某些表未清除干净,一般是遇到了exception,这时候就需要手动来清除这些表中的记录。

先介绍几个表:

MGMT_TARGETS  --目前在GC中能看到的target都在此表中,删除了的对象不在此

MGMT_TARGETS_DELETE --记录执行过删除操作的target,如果delete_complete_time为空,则有可能删除操作正在进行中

MGMT_TARGET_DELETE_EXCEPTIONS --记录了删除失败所有可能涉及到的表名

 

首先可以先尝试用下面的方法再执行下delete target的操作:

exec mgmt_admin.delete_target('mgcdb2','oracle_database') --这里2个参数分别对应MGMT_TARGETS中的target_name和target_type

exec mgmt_admin.delete_target_internal('mgcdb2','oracle_database')

如果报错,只有用手工的方式来清除相关记录了:(参考metalink 849388.1)

1. 停止agent

2. 执行 exec mgmt_admin.cleanup_agent('racn2:3872') --这个主机名和端口号可以在emctl status agent的结果中得到,或是在MGMT_TARGETS之前的记录中得到

3.运行如下sql

select 'delete from ' || o.name || ' where ' || c.name ||
' not in (SELECT target_guid FROM MGMT_TARGETS) and ' || c.name ||
' !=''00000000000000000000000000000000'';'
from sys.obj$ o, sys.tab$ t ,sys.col$ c
where o.owner# = userenv('SCHEMAID')
and c.name like ('%TARGET_GUID%')
and c.obj# = o.obj#
and (o.name like ('MGMT_%') OR o.name like ('OCS_%'))
and o.obj# = t.obj#
and bitand(t.property, 1) = 0
and bitand(c.property,32) = 0
and bitand(c.property,512) = 0
and o.name not in (SELECT table_name
FROM MGMT_TARGET_DELETE_EXCEPTIONS)
order by o.name;

将结果copy出来直接运行。

4.清除agent下相关文件

如果是rac环境 则需要在各个node的文件夹下删除,

rm -r $ORACLE_HOME/<nodename>/sysman/emd/state/*
rm -r
$ORACLE_HOME/<nodename>/sysman/emd/collection/*
rm -r
$ORACLE_HOME/<nodename>/sysman/emd/upload/*
rm
$ORACLE_HOME/<nodename>/sysman/emd/lastupld.xml
rm
$ORACLE_HOME/<nodename>/sysman/emd/agntstmp.txt
rm
$ORACLE_HOME/<nodename>/sysman/emd/blackouts.xml
rm
$ORACLE_HOME/<nodename>/sysman/emd/protocol.ini

5. 然后resecure agent,start agent 继续执行添加数据库的操作





有关grid control(1)


我的环境 Oracle 10g Solaris 10

下面就把在安装和部署过程中碰到的问题整理下 Grid Control(下面简写为GC)



首先记住,一定要配好你的环境变量AGENT_HOME,OMS_HOME,ORACLE_SID

然后大致的步骤就是 在你用来管理的机器上安装OMS,在被管理的机器上安装AGENT,然后用AGENT上传被管理机器的信息。



问题1:安装时OMS Configuration hang

先停止这一步。修改opmn.xml,这个文件的位置往往在你的$OMS_HOME/opmn/conf下,找到如下内容在后面插入(蓝色部分)

<ias-component id="HTTP_Server">

<process-type id="HTTP_Server" module-id="OHS">

<environment>

<variable id="LD_PRELOAD" value="$OMS_HOME/lib/libclntsh.so"/> ---由于我们安装oms 的机器一般上面已经安装了oracle 所以这里的$OMS_HOME要用实际OMS的HOME代替

</environment>



然后retry,就能过去,Agent Configuration可能会出错,不管,继续。

其实GC服务器上的AGENT装不装取决与你需要不需要也用GC来管理本地的数据库或机器。(比如你安装GC的机器上原来就有一个数据库,而这个数据库也需要用GC来管理)

其实这个改动完全是用来骗过安装中的配置这步的,装完以后也可以用手动配置。所以要么就干脆不改,直接失败后继续,要么就改了骗过去以后再改回来(不改回来的话OPMN的HTTPD起不来)



问题2:opmn起不来

如果在刚才修改过
opmn.xml,则opmn是起不来的,就因为我们那个改动,把刚才的改动再去掉就行。然后执行

$OMS_HOME/opmn/bin/opmnctl startall

其他常用命令

./opmnctl stopall

./opmnctl status --DSA和LogLoader可以不用起 其他的应该都要起

./opmnctl startproc ias-component='xxx' --这里
ias-component就是status看到的 如果一个ias-component对应一个process-type 用这个起

./opmnctl startproc process-type='xxx'   --这里process-type就是status看到的 如果一个ias-component对应多个process-type 用这个起



问题3:手工配置OMS

如果在安装software的时候,出错后选择了跳过,是需要手工配置OMS的。

用$OMS_HOME/oui/bin/runConfig.sh进行配置

语法如下

./runConfig.sh ORACLE_HOME=$OMS_HOME ACTION=Configure MODE=Perform



问题4:启动OMS

启动OMS一般不会有问题,除非你的配置不对或者你的opmn没起来

$OMS_HOME/bin/emctl start oms



问题5:启动AGENT

1    如果你要管理的机器上没有装过AGENT,那就比较方便,直接按照文档装。

2    如果之前装过,而且你的OMS服务器换了(比如换机器了或者重装了等等)那么就稍微麻烦点。看下面



首先是清除之前的信息

$AGENT_HOME/emctl stop agent

1. rm -r <AGENT_HOME>/sysman/emd/state/*

2. rm -r <AGENT_HOME>/sysman/emd/collection/*

3. rm -r <AGENT_HOME>/sysman/emd/upload/*

4. rm <AGENT_HOME>/sysman/emd/lastupld.xml

5. rm <AGENT_HOME>/sysman/emd/agntstmp.txt

6. rm <AGENT_HOME>/sysman/emd/blackouts.xml

7. rm <AGENT_HOME>/sysman/emd/protocol.ini

然后再用命令清除一遍

$AGENT_HOME/emctl clearstate agent

重新配置一遍

$AGENT_HOME/emctl secure agent --这里的密码就是在安装software的时候 要求填的其中一个

启动

$AGENT_HOME/emctl start agent



然后更改AGENT原来配置的OMS upload目录的url

在这个位置:

$AGENT_HOME/sysman/config/emd.properties

找到如下部分
修改蓝色部分

#

# OMS Upload URL

#

# if there is no receiving OMS or if you wish to disable the UploadManager

# please set this value to empty or comment out below line

#

REPOSITORY_URL=https://mgdb01:1159/em/upload



这个地址如果你忘记了还有个方法,就是用OMS所在机器上的AGENT来看(默认的GC OMS服务器也安装了AGENT),命令$AGENT_HOME/bin/emctl status agent 然后找到Repository URL这一项就是。



最后上传本地信息到OMS

$AGENT_HOME/emctl upload agent



问题6:配置AGENT

如果需要手工配置AGENT,和OMS类似。

用$AGENT_HOME/oui/bin/runConfig.sh进行配置

语法如下

./runConfig.sh ORACLE_HOME=$AGENT_HOME ACTION=Configure MODE=Perform



主要的几个log目录

$OMG_HOME($AGENT_HOME)/sysman/log --存放运行emctl emca时的log

$OMS_HOME($AGENT_HOME)/cfgtoollogs/cfgfw
--存放运行runConfig.sh时的log

 
 
 
 

记录下 ORA-00600: internal error code, arguments: [qkabix], [0], [], [], [], [], [], []


Applies to:


Oracle Server Enterprise Edition - Version: 10.2.0.2 to 10.2.0.3

This problem can occur on any platform.

Oracle Server - Enterprise Edition - Version: 10.2.0.2 to 10.2.0.3

Symptoms


In the alert log is reported the following internal error:
    ORA-00600: internal error code, arguments: [qkabix], [0], [], [], [], [], [], []

The error is reported running a Select statement.

The call stack looks like:

   qkabix qkaix qkatab qkajoi qkaqkn qkadrv opitca kksFullTypeCheck rpiswu2 kksSetBindType kksfbc
   kkspfda kpodny kpoal8


Cause


The problem could be related to a CBO ( Cost Based Optimizer ) issue when a query uses a bitmap access paths for b-tree indexes.

It is reported in Bug 5945798 but not confirmed.


Solution



One possible workaround to avoid the error is to disable the optimizer to produce bitmap plans for B-Tree indexes even if
there is no bitmap index anywhere in sight:

- at session level
     sql> alter session set "_b_tree_bitmap_plans"=false;

- or at system level 
     sql> alter system set "_b_tree_bitmap_plans"=false;

- or in the init.ora
     _b_tree_bitmap_plans = false

 

 有关 BITMAP CONVERSION TO ROWIDS

 


Answer: The "bitmap
conversion to ROWIDS" execution plan step was generally
introduced in Oracle 9i when the default for _b_tree_bitmap_plans
changed from "false" to "true".  The "BITMAP CONVERSION (TO
ROWIDS)" plan is not always an optimal step when converting from
b-tree indexes, and it can be very inefficient access plan in
some cases.

 



Bitmap conversion to ROWIDS does
not require bitmap indexes, and it's sometimes found in cases of
SQL with complex WHERE clause conditions.



 



The bitmap conversion to rowids is
sometimes seen with star transformations (by setting
star_transformation_enabled = true
).  You can also
turn-off bitmap conversion to ROWIDS in your init.ora by
re-setting this hidden parm:



 



_b_tree_bitmap_plans=false



 



You can also turn-off bitmap
conversion at the session level, for testing:



 



alter session set
"_b_tree_bitmap_plans"=false


 



As always, notify Oracle technical
support before employing any hidden parameters, as they can make
your database unsupported.


 

 
 
 
 

标记下 使crs_stat -t显示完整的resource name


脚本参考 

http://www.itpub.net/viewthread.php?tid=1111260&elevator=18044

做了一点点改动

crs_stat.sh

awk \
  'BEGIN {printf "%-30s %-10s %-10s %-10s\n","Name                          ","Target    ","State     ","Host   ";
          printf "%-30s %-10s %-10s %-10s\n","------------------------------","----------", "---------","-------";}'

crs_stat | awk \
'BEGIN { FS="=| ";state = 0;}
  $1~/NAME/ {appname = $2; state=1};
  state == 0 {next;}
  $1~/TARGET/ && state == 1 {apptarget = $2; state=2;}
  $1~/STATE/ && state == 2 {appstate = $2; apphost = $4; state=3;}
  state == 3 {printf "%-30s %-10s %-10s %-10s\n", appname,apptarget,appstate,apphost; state=0;}'

 oracle@racn1[/home/oracle/wangxi]#crs_stat -t
Name           Type           Target    State     Host        
------------------------------------------------------------
ora.mgcdb.db   application    ONLINE    ONLINE    racn2       
ora....vsrv.cs application    ONLINE    ONLINE    racn1       
ora....db1.srv application    ONLINE    ONLINE    racn1       
ora....lsrv.cs application    ONLINE    ONLINE    racn2       
ora....db2.srv application    ONLINE    ONLINE    racn2       
ora....b1.inst application    ONLINE    ONLINE    racn1       
ora....b2.inst application    ONLINE    ONLINE    racn2       
ora....rv01.cs application    ONLINE    ONLINE    racn1       
ora....db1.srv application    ONLINE    ONLINE    racn1       
ora....tsrv.cs application    ONLINE    ONLINE    racn2       
ora....db2.srv application    ONLINE    ONLINE    racn2       
ora....N1.lsnr application    ONLINE    ONLINE    racn1       
ora.racn1.gsd  application    ONLINE    ONLINE    racn1       
ora.racn1.ons  application    ONLINE    ONLINE    racn1       
ora.racn1.vip  application    ONLINE    ONLINE    racn1       
ora....N2.lsnr application    ONLINE    ONLINE    racn2       
ora.racn2.gsd  application    ONLINE    ONLINE    racn2       
ora.racn2.ons  application    ONLINE    ONLINE    racn2       
ora.racn2.vip  application    ONLINE    ONLINE    racn2       
oracle@racn1[/home/oracle/wangxi]#./crs_stat.sh
Name                           Target     State      Host      
------------------------------ ---------- ---------  -------   
ora.mgcdb.db                   ONLINE     ONLINE     racn2     
ora.mgcdb.devsrv.cs            ONLINE     ONLINE     racn1     
ora.mgcdb.devsrv.mgcdb1.srv    ONLINE     ONLINE     racn1     
ora.mgcdb.htlsrv.cs            ONLINE     ONLINE     racn2     
ora.mgcdb.htlsrv.mgcdb2.srv    ONLINE     ONLINE     racn2     
ora.mgcdb.mgcdb1.inst          ONLINE     ONLINE     racn1     
ora.mgcdb.mgcdb2.inst          ONLINE     ONLINE     racn2     
ora.mgcdb.srv01.cs             ONLINE     ONLINE     racn1     
ora.mgcdb.srv01.mgcdb1.srv     ONLINE     ONLINE     racn1     
ora.mgcdb.tktsrv.cs            ONLINE     ONLINE     racn2     
ora.mgcdb.tktsrv.mgcdb2.srv    ONLINE     ONLINE     racn2     
ora.racn1.LISTENER_RACN1.lsnr  ONLINE     ONLINE     racn1     
ora.racn1.gsd                  ONLINE     ONLINE     racn1     
ora.racn1.ons                  ONLINE     ONLINE     racn1     
ora.racn1.vip                  ONLINE     ONLINE     racn1     
ora.racn2.LISTENER_RACN2.lsnr  ONLINE     ONLINE     racn2     
ora.racn2.gsd                  ONLINE     ONLINE     racn2     
ora.racn2.ons                  ONLINE     ONLINE     racn2     
ora.racn2.vip                  ONLINE     ONLINE     racn2    

 
 
 
 

ora-600问题一则


一开发人员在用java程序调用数据库一个包A里的某个存储过程时,报以下错误

ORA-00600: internal error code, arguments: [kcbz_check_objd_typ_1], [0], [0], [1], [], [], [], []
Current SQL statement for this session:

select * from tmp_hotelinfolisttest a where salesprice > 0 order by   decode(a.hotel_comm_type,4,6,nvl(a.hotel_comm_type,5)),a.hotel
star,a.lowestprice ,a.hotelid,a.ROOM_TYPE_ID,a.CHILDROOMTYPEID,a.PAY_METHOD,a.able_sale_date,a.salesprice

存储过程简单调试了下没什么问题:从一些表里取到数据,先暂时放在tmp_hotelinfolisttest这个临时表里,最后用一个游标类型的返回参数返回给java,上面报错的sql就是游标所使用的sql.

代码截取如下:

.....

v_sqlstr := 'select * from tmp_hotelinfolisttest a where salesprice > 0 order by '|| v_tempstr;  
open return_list for v_sqlstr;
    --------
commit;

.........

把开发人员提供的输入参数传入,直接在sqlplus下调用,没错误,但用java调用就报错。

google metalink上search了一把,没发现和这个情景一模一样的案例。

据开发人员描述,这个存储过程和另一个包B里的同一存储过程相似,但B不存在这个问题。

仔细比对2个存储过程,没发现有特别之出,除了2个存储过程分别采用了2个不同的临时表.

比较2个临时表的区别,发现A包里用的临时表是on commit delete rows.而B包里的是on on commit preserve rows.

问题就在这里:

如果采用事务级的临时表,那么java在调用完存储过程以后(存储过程最后有commit),临时表里的数据会被delete掉,但是它拿到的那个游标返回参数却需要这些数据,这样就产生了冲突。

而如果采用会话级的临时表,由于java在调用完存储过程后,会话并未结束,数据会一直保存到会话结束为止,因此就不会有问题。

把临时表改成on commit preserve rows 问题解决。

还有3个疑问:

1 当返回一个游标类型的参数时,oracle返回的到底是一个指向sql的指针,还是一个指向数据的指针?

2 为什么在数据库直接调用该存储过程就不会报错?

是不是只有在真正要取游标里的数据时,oracle才会做校验?

还是在 open return_list for v_sqlstr做了校验 然后数据被delete,最后拿数据的时候再次校验的时候报错。

3 从报错误的字面上理解,kcbz_check_objd_typ_1应该是在做check object type

这个check究竟是在check哪个object type是游标的,还是临时表的,还是数据?




 
 
 
 

select count(*) into 会出现 no_data_found吗?


select count(*) into 会出现 no_data_found吗?

很久以前就遇到这个问题了,今天又碰到了,记录下。

在遇到这个问题之前,我会非常肯定说:不可能。

看个测试:

SQL> desc t
 Name                                      Null?    Type
 ----------------------------------------- -------- ----------------------------
 ID                                                 NUMBER

SQL>
SQL>
SQL>
SQL> select * from t;

        ID
----------
         1
         2
         3
         4
         5
         6
         7
         8
         9
        10

10 rows selected.

SQL> select count(*) from t;

  COUNT(*)
----------
        10

SQL> select count(*) from t where id =0;

  COUNT(*)
----------
         0

SQL> select count(*) from t where id = 0  group by id; 

no rows selected



SQL> select count(*) from t where id=1 group by id;

  COUNT(*)
----------
         1

 

事实就是这样,没有什么不可能。

补充一句,这里要区分“空值”和“空记录”。

 
 
 
 

一个小技巧


在生产环境里,很多情况下需要更新一些频繁访问的procedure,package,function等数据库对象。如果这些对象的访问频繁到一定程度的时候,在做create or replace的时候就会遇到很大的麻烦,经常会导致数据库出现大量的latch,严重的时候会导致数据库瘫痪。但是采用下面的方法就不会有这种麻烦:

假设现在有一访问非常频繁的procedure:prc_tst

1.利用prc_tst建立和prc_tst一模一样的prc_tst1和prc_tst2

2.drop procedure prc_tst;

3.create public synonym prc_tst for prc_tst1;

4.需要做更新的时候,更新prc_tst2,然后create or replace synonym prc_tst for prc_tst2;

5.视情况决定更新prc_tst1,需要回滚则不更新,不需要回滚就更新。

6.下次再做更新的时候,更新prc_tst1.

 

在我们的环境中,原来更新此类对象的时候是需要在数据库端做操作对应用有影响的,现在就非常简单了。





 
 
 
 
 

Valid XHTML or CSS?

[This is a Roller site]
Theme by koko.
 
© koko