December 2005 Archives

出处:PConline社区    作者: Rameses (斯西美拉)    责任编辑:lujiezhen


  原文链接——http://thekaran.com/iStuff/companyNames.html

  译者按:比较有意思的东西,没看见中文版,翻译了。对原文所述未经证实,望知者不吝赐教。

  Yahoo!
  《格列佛游记》的作者Jonathan Swift发明了yahoo这个单词。在小说里,它代表了一个在外表和行为举止上都令人厌恶的家伙,简直都不能算是一个人。Yahoo! 的创始人杨致远和David Filo选择这个名字的原因是他们觉得自己是yahoo。

  另一种说法,Yahoo是"Yet Another Hierarchical Officious Oracle"的首字母缩写,不过David Filo和杨致远坚持他们选择这个名称的原因是他们喜欢字典里对yahoo的定义:“粗鲁,不通世故,粗俗。” (来源: http://docs.yahoo.com/info/misc/history.html)
  

  Xerox
  xer是希腊文字根,代表“干”。由于Chestor Carlson发明的产品是干式复印,和当时占优势的湿法复印有显著的差别,所以他用Xerox命名。
  

  SUN Microsystems
  由斯坦福大学的四个家伙创建。SUN 是“Stanford University Network”的首字母缩写。


  Sony
  来自sonus和sonny的组合。sonus是拉丁词,代表声音。sonny是美国俚语,用来称呼聪明伶俐的少年。


  SAP
  代表"Systems, Applications, Products in Data Processing"。四个IBM的前雇员组建了SAP。他们为IBM工作时属于的团队叫“Systems/Applications/Projects”。
  

  Red Hat
  公司创始人Marc Ewing念大学的时候,他祖父给了他一顶康奈尔曲棍球队的帽子。帽子上有着红色和白色的条纹。他不小心把帽子弄丢了,不得不拼命去找。红帽子Linux beta版的用户手册里面有一段话,央求用户如果找到了他的红帽子,请归还!


  Oracle
  Larry Ellison 和 Bob Oats 曾经为中央情报局的一个咨询项目工作。这个项目的代号就叫 Oracle。
  

  Motorola
  创始人Paul Galvin是在公司开始生产车用无线电的时候让公司叫现在这个名字的。原先它叫Victrola。
  

  Microsoft
  Bill Gate起了这个名字。为了代表MICROcomputer SOFTware,就叫做Micro-Soft,后来把中间的 “-” 去掉了。


  Lotus
  从莲花式盘坐(padmasana)中得名。创始人Mitch Kapor 曾经是Maharishi Mahesh Yogi的超脱静坐教师。
  (译者注:Mahesh Yogi, Maharishi,印度宗教领袖。)
  

  Intel
  Bob Noyce和Gordon Moore想把他们的公司命名为“Moore Noyce”,可是这个名字已经为一家连锁旅馆注册了。Intel是INTegrated ELectronics的缩写。

  
  Hewlett-Packard
  Bill Hewlett和Dave Packard丢硬币来决定他们的公司叫Hewlett-Packard还是Packard-Hewlett。

  
  Hotmail
  创始人Jack Smith想出了最初的主意,要建立一种任何计算机都可以通过网络访问的电子邮件网络服务。当Sabeer Bhatia参与起草商业计划书的时候,他尝试了各种以mail结尾的名字。最后,他选择了Hotmail。因为Hotmail包含了html。Hotmail最早的形式是HoTMaiL。
  (译者问:Hotmail是不是第一个基于网页的电子邮件服务?)
  

  Google
  名字来自于一个关于搜索引擎到底能搜索多少信息的玩笑。最早它叫“Googol”,代表1后面跟100个0。创始人Sergey Brin和Larry Page曾经向一位天使投资人演示他们的项目,最后他们收到了一张给“Google”公司的支票!
  

  Cisco
  San Francisco的最后五个字母。公司的徽标像极了金门大桥。
  

  Apple Computers
  Steve Jobs最喜欢的水果。他本该早就为公司申请一个名字,可是三个月过去了,还没有注册。Jobs威胁大家,如果五点钟之前还找不到一个比“苹果电脑”更好的名字,那么公司就叫“苹果电脑”了。
  

  Apache
  创始人是从给NCSA httpd后台代码打补丁起步的。结果,他们得到了“A PAtCHy” server(打过补丁的服务器),于是,就叫Apache了。


  Adobe
  创始人 John Warnock家后面有一条叫做Adobe Creek的河。

奋斗5年 从月薪3500到700万!


    编者按:本文转载自阿里巴巴贸易论坛,网友“心晴*_*”上传。文中主人公记述了在上海5年的事业及生活经历。曲折离奇,但心得颇多,在此与各位淘友分享,希望各位朋友能从中有所感悟。原帖如下—— 

偶的忠告:要想学点什么,首先学会有耐心

阅读准备:眼药水+眼镜+耐心+一颗平淡的心

   

    来上海整整五年了,事业上已有了突飞猛进的飞跃,生活方面有过一段段的辛酸。然而,如今回首看来,这五年来也这是这些苦恼最终成为我前进的机遇,让我拥有了目前还算可以的生活境遇—700万身价,对有些兄弟来说可能是微不足道,但是我想大多数朋友还可能暂时没有达到这个状态---没有半点炫耀的意思,我知道朋友们很多都会成功,会比我强得多---所以会对我的经历感兴趣,我决定定下心来,好好写点文字,希望不会让朋友们失望。

   今天我的心里有一个想法更加清晰,那就是:爱,只有爱,才是一个男人成功的最好动力、最合适的动力。而绝不是自己的虚荣心,或者所谓的雄心壮志。作为一个男人,首要的一件事是你要有你的真正所爱。它会像原子弹一样激发你的能力,让你爆发无穷的动力,上帝也会为你感动。这样的状态,就是每个人梦寐以求的状态。

   朋友们,也许你们不同意我的看法,我们先不忙争论,您先看看我的经历,看看是不是有道理。    

   1, 上海

    1999年中,我辞去了刚刚分配的国家机关的工作,从新疆来到了上海。当时我踌躇满志,认为凭借自己的力量和努力一定能够在这个大都市里站稳脚跟,创下一片属于自己的天空。

   我是1976年出生在新疆,新疆的日照和高原气候,让我的身材像白杨一样挺拔,相貌虽不敢说英俊非凡,但也让绝大多数人不讨厌。我从小学习可以说是优异的,大学考上了国家排名前5的重点大学,当时分配是98年,父亲害怕工作难找,一定要我回去做个清闲稳定的机关公务员。我觉得自己也可以历练以下为人处事,就回到了新疆自治区政府。工作了几个月后,和本部门的同事混得极熟,喝酒、吹牛、查颜观色的本领提高飞快,但是觉得工作实在是研磨青春,浪费生命,就决定辞职,去上海打拼一下。呵呵,现在我的同学在新疆的也都混得很好。这是个性不同了。

   我的专业是经济管理类的,当时不懂事,自视颇高,到了上海我就傻了:这种人企业根本不要,他们要的是有一定技能的人,能干事的人,像我这种实际工作没做过的人根本没人提供培训的机会。同学和朋友一个个工作都找到了,就我搞不成低不就的,眼看带来的钱慢慢要见底了,这心里越来越急—难道这里还真没有我的用武之地了吗?

    3个月后,我终于找到了一个让自己暂时满意的工作,但远远不是自己的专业了。我这个人兴趣比较广泛,精力也充沛,大学里涉猎很多领域,想法也多,文字功底还可以。正好有一个广告公司招策划文案,我觉得自己能行,结果一试,公司面试者说我虽然没有做过,但是思路和功底还不错,再说毕业的学校名声不错,就留下我了---现在我还是很感激那位前辈,后面的工作也证明了他的眼光。月薪3500,还好,生活问题暂时解决了。

   很快我的生活进入了工作状态,我觉得很快乐。2个月过后,一件让我猝不及防发生了,没想到由此开始,我的生活发生了这么大的变化。        

   2,邂逅

   上班后我对工作极其热忱,也非常努力,一两个月后我已经做过了3个Case,客户和老板还有上司都比较满意。当时我一则是刚从机关出来,一心想好好干个工作,二则是想报公司识人用人之恩,做事情时即不惜努力,又谦虚肯学,另外因为经过机关的历练,做人上路又大方,经常请同事喝酒吃饭,他们也愿意帮我,所以很快上手成为部门的骨干。到现在我还在劝年轻的朋友们,工作是应该用全身心来投入的,这项投入从理财的角度说对任何人来说都不会亏本。呵呵,不过,那段时间存款为0。

   有一天我去上班,那天早上下小雨,从住的地方要打车去公司那里,要车的人多,根本打不到车。刚刚轮到我就要上车的时候,一个女孩子从路边冲过来,头发已经淋得不像话了,拉开后门就要上车。我回头刚想出口请她下车,看看她淋得那样,再说让一个女孩子出去我还说真不出来,她也好像也实在没办法了,看着我脸红红的。我就对她笑了一下,退了出去。 

第二天早上,我们又在同一个地方见面了。那天是晴天,大家都在等公交车,她一见我就主动向我报以歉意的笑容,我指着快来的公交车笑着说:“你不会把这辆车也抢走吧?”,她呵呵笑了,说:“今天就让给你了!”。

   就这样,我们认识了。

   3,热恋

   她叫芸,来自湖南。她不仅有湘妹子的美丽温婉,也有湖南女子的泼辣和善解人意。她也是刚到上海,在一家贸易公司工作。

   我们迅速的认识,相知,然后热恋。也许热恋还在相知之前。我至今也有点不明白,为什么会忽然爱的一塌糊涂。也许是刚到一个陌生的地方,刚刚离了生存的威胁,也许是我工作后一直嘻嘻哈哈惯了,忽然有个好女孩出现了,也有了真实的感情我就缴械了。

   我们因为住的近,下班后每天都在一起,芸说我第一次拥抱她时,她就离不开我了,她说我的体味让她无比迷恋。热恋时我感觉我的精力无穷,每天陪我的芸到夜里11点12点,灵感来了还去公司加班,那段时间工作效率也很高。朋友们都说我的眼睛熠熠闪光。我们一天不见就如隔三秋。看着她的眼睛我会忘了饥饿,有很多次我心里碰碰跳着回到住所时,忽然发现自己已经饿得受不了了,呵呵。

   有一次我去崇明跟项目,因为晚了船班次停了回不来,所以给她打电话说不回来了。我们一晚上竟然通了50多个电话,不是她打过来就是我打过去。第二天一早我一下船,居然在码头上发现了我的芸---要知道那里打车也要1个小时的路,她流着眼泪说一夜没睡,一早就来等我了。我们相拥而泣,幸福异常。

   很快我们双方都认为对方是自己未来家庭里的另一半。到年底的时候,芸说让我去她家见见她家人。我很紧张,但是很高兴,开始准备见面礼。呵呵,那时我们都爱昏了头,根本没有存钱的想法。好在我的薪水涨到了5500,她也有2500,我们还够花。

   然而没多久,一个消息把我的心情打入了十八层地狱。          

   4,彩礼

   到年底了,我的礼物也准备的差不多了,一共花了大概4000多。半年多来,我已经成为公司的干将,老板也比较看好我。因为我一直是西北人的性格,豪爽但不失明智,工作从不计较加班,补助什么的。年底老板还多发了不少,买好礼物手边已经有1万了,感觉自己有钱了,所以根本没想到钱的事。

   这时候她的一个表妹从她的老家来了,说是来看看。我想可能主要是她家里人让她来看看我这个未上门的女婿的。她早就给我说过,她家里她妈市老大,决定一切事宜。我们不敢怠慢,带她表妹在上海好好的玩来一遍。最后我感到她表妹对我还是比较满意,我的心也放下来了。

   到了临走的前几天,芸忽然告诉我说,这次上门可能比较正式,语言有些闪烁其词。我有点不明白,心里想可能她妈已经初步考察通过了吧。一天,我们三个人在的时候,她表妹开玩笑的样子对她说,姐,你这么好的条件,彩礼可不能少要啊!姨说了,前街的老李家的闺女都要了男方8万呢,我们决不能少于15万的。说着还看看我。 

   天啊,我像被电打一下,呆住了。说实话,我从小在新疆长大,风气很开明的,结婚男方有送钱的一般不过4~5万了不起了,而且还是说明给孩子的。彩礼这个概念只有读小说时接触过,万万没有想到会有朝一日到自己头上。她家里人现在说出这个话,绝对是当真的,说话的方式都掌握的这么有技巧。我该怎么办?让她嫁改变做法想法?省省吧!凭什么?家里的底子我清楚,决不能向家里伸手。那该怎么办?我还是笑着看看芸和她表妹,芸有点紧张,我心里更不忍了。“呵呵!看来我要表现诚意了。”,我笑着不置可否的回答。

   我该怎么办?回去后我翻来覆去地想这个问题。

5,诺言

   这是痛苦的3天,我几乎没怎么睡觉。芸也看出来了,她小心翼翼地不敢惹我。我心里很憋火:怎么弄得嫁女儿跟卖女儿一样?有时候想干脆吹了算了,可是一想到我们要分开,心里就像刀割一样,眼泪就不由自主的下来。家里一直是清贫的家庭,弟弟还在上大学,不可能向家里伸手的;自己的工资?天啊,我现在都觉得钱不够话,手边只有1万块钱,这次去还要准备出血,再说我就是攒钱,也要为我们结婚买房作准备啊,15万给了她家,我们将来怎么办?。。。

   这么多年来,我对自己的了解是,我喜欢出奇招。想了3天,我有了一个办法,心就定了。芸有时看着我,不知所措—她知道我的脾气,家境和经济状况,可是,她也知道她无力改变她妈的想法,而且关键的是,她还有一点想法是彩礼是应该给的。我告诉她,别担心,我有办法了。

   很快,到了她家了,见面,递上礼物,聊天。。。她母亲和蔼而精明,父亲稳重而慈爱。很快两天过去了,我们也该走了,这时该来的也该来了。最后的晚餐,她的母亲说话了:“小D,你在我们这里已经2天了,我们对你还是比较满意的。你是个不错的孩子。如果没有意外,希望你们能今年(新的一年)把婚定了。你看什么时候把礼节办了?你们商量一下,也和你家里商量一下,好吗?对了,我们这边的风俗你可能还不清楚,也不知阿芸小月给你讲了没有。”

   我马上接住了话题,笑着说:“谢谢阿姨,伯父,小月和我说了。”这时我看到阿芸紧张的脸都变了,看着我怕得要命。是啊,最后一段千万别搞砸了。我笑笑让她放心。

    “阿姨,伯父,你们的心情我我理解,养女儿不容易,再说只有一个女儿,我觉得15万如果比比投入,不算多,甚至还根本不够。这个钱我们家应该给。”

    “我想阿芸也把我家里的情况告诉二位老人了,我是这么想的,也不一定合适,您二位先听听。

    “15万应该给。但是我觉得既然我工作了,我自食其力了,而且是我娶阿芸,同时你们也觉得我合适,那么这个15万应该由我来给,而不是我家里来给。          

    “你们和阿芸看中的人,不应该仅仅需要家里有15万,还要有能力,有能力给阿芸将来的生活带来幸福。我想,我有这个能力。我自己不仅要有15万,而且应该向你们证明,我有能力给阿芸幸福。

    “我只有一个要求,就是给我不长的时间,两年吧。我们还小(阿芸比我小2岁),晚一点结婚也没关系。两年后,我会拿出15万,而且会证明给你们看,我和阿芸有能力生活的幸福。”

   其实,当天晚上我的语言远远比我的文字精彩,因为有爱在心里,我打动了她家所有人,阿芸的脸也红扑扑的。我们走的时候,他家里人很开心,当然也许只是表面上是,但是至少他妈默认了我的要求。当然从此后,我感觉有个巨大的大山压在了我的心里,我的生活改变了。


6,开端

   回到上海以后,我的心情没有低落,反而有种大战来临时的平静和激动。我心里暗暗下定决心,为了我的爱人,我的未来幸福生活,我要付出比别人几倍的努力,实现我的诺言。我全身心地渴望这样做,而且相信自己一定能够成功。

   芸反而很担心,她和我说要不我们搬到一起,生活上可以节省一些,她和我一起攒钱。我拒绝了她。虽然我们早就有了肌肤之亲,但是我不想让她家里人知道,这样对她不好。而且我也不愿让她一起攒钱,毕竟我说了,这是我的事。我知道一个女孩,生活、衣服、化妆品等等,每个月的花费怎么说也要2000块左右的。我说,芸这段时间我可能就不能给你买很多衣服和化妆品了,她郑重地点点头。我不知道,以后我是否会为这个决定而后悔。

   我的初步想法是这样的:因为我只工作了7个月,而我的薪水已经涨到了5500。如果依照这个速度,半年后我的薪岁至少应该到8000,一年后最不济也应该到10000左右。我可以什么都作,而且可以往管理方面发展,这样,我每月存下70%的工资,2年下来加上年终奖,也就差不多了。而且,那时候即便把15万都“上供”了,我的年收入也能够让我们生活的小康。

   现在回想我那时候想法,心里只有两个字:幼稚。事态的发展果然证实了那句话:计划在现实面前永远是无用的。


   7,失败

   很快,现实给了我重重一击。一个偶然的机会,我和大老板聊起来,他告诉我策划和创意人才可以很快赢得中等偏上的薪资,但是要达到5位数,只有2年的工作经历基本不可能。因为国内的商业条件还不成熟,客户的能力也有限。所有的公司愿意付出一些成本搞定客户,在策划和创意上达到80%的满意就可以了。而且,公司愿意把高薪给业务人员和管理人员,一个只有2年工作经历的人基本不具备它所需要的人脉资源、操作能力和管理能力。

   我明白了老板的意思。我开始在市场上寻找其他的公司。但是现实很快让我失望,要在一年内获得万元以上的月薪根本是不可能的。好的公司有,但都说2到3年内有希望,如果做得好的话。老天,我的时间不够了!同时,公司知道了我在外面找工作的事情,老板们很不开心,因为平心而论公司觉得已经待我不薄了。说实话,这条路成功的可能性很大,但是时间不够啊!

   怎么办?

   我决定辞职。        

   8,艰辛

   既然已经证明此路不通,再留下去就是浪费时间。我的时间不多了。而且我认为自己如果辞职,就有的是大块的时间,能够接触更多更深的社会,机会也相应的多了。阿芸不同意,她说这样太不稳定了。我没法说服她,她也没办法说服我。这件事我还是做了,我知道,只能破釜沉舟了。

   临走时和老板深谈了一次,请他原谅。也把我的处境部分告诉了他。我们谈得很好。老板很惋惜,让我以后有可能还回来工作,我也很依依不舍,但是我已经没有退路了。

   我开始了在上海滩到处漫游的经历,骑着一辆破自行车到处在上海转,到处找有限的熟人,问有没有项目做。我身边有1万2千多块钱,觉得还可以支撑半年吧。我想,这半年里如果有策划项目做,我就辛苦点,把所有的事情都自己做了,应该可以挣个2到3万,多做几个项目就比打工好了。呵呵,如果朋友们谁有我那时一样的想法,今天我一定劝你千万别!事后想,我太自信了太着急了,真是应该边工作边找机会,时机成熟再干的,否则下海99%是被淹死。我就这样风里来雨里去,跑了2个月,一个单子也没有跑到,加上有一次丢了包,损失了1000多块钱和手机。住宿、吃饭、交通花了3500块钱,身边只剩7000多块钱了。可是一点没有转机的迹象出现。 

9,机遇

   就在这时候,一个令人不敢相信的、非常好的机会出现了。我以前的一个客户找到我,说是他的一个朋友在上海嘉定那边的一个镇里做镇长,他们镇上3个月后要办一个“水乡情思”的活动,主要是吸引港台和外籍人士的资金投资。他们要我构思起草一个大型活动的策划书,价格是4万元。这个客户说以前在我们公司和我合作过,觉得我有这个能力,而且拿到公司去做策划,价格一般要到8万以上。我们合作空间更大,而且如果策划书做的好的话,活动组织和制作我们还有机会。我很开心,明白他是想自己也赚一些,立刻给了他2000元的好处费。不知道这个习惯有没有影响我,直到现在我都认为机会来了一定要投入,而不是大多数人认为的不见兔子不撒鹰。

   我废寝忘食地工作了20多天,每天夜里干到2点,稿子改了4次。然后又自己贴了400多块钱制作了3本样本。交给那朋友的时候,他非常赞赏,连声说做的太好了,看来后面的制作也没问题了,一周之内我就等着拿钱吧。我也心里感叹投入没有白投,连忙把这个好消息告诉了芸,她也非常开心。毕竟这是我的第一笔收入啊!而且金额还算不少。

 
   10,被骗

   我万万没有想到,这次看起来不错的机会竟然实际上是碰上了一个骗子。这个客户拿到了我的方案以后,竟然人间蒸发了!我苦苦等了一周以后,这家伙死活不再和我联系了。我打电话,手机已经停机,跑到他原来公司去找他,公司的人说他早就不做了,现在在和一个人合作开公司。我又跑到嘉定的那个镇上去找我们以前一起见过的他的镇长朋友,镇长说这个项目早就签约了,他和我那个客户也不是朋友,只是签约公司说策划书部分包给他,他又找到了我,说我是他的助手。现在策划书已经通过,钱都已经付了。我马上又找到了那家公司,公司说我那个客户不是他们公司的人,只是他让公司把策划书部分包给他,钱公司和他刚结清了。知道我的情况后,他们表示同情,但没办法:现在他们也找不到人,钱也结清了。

   这个打击对那时的我是致命的,让我的处境雪上加霜。我已经花了大量的精力不说,原来剩下的7000多块钱已经被我花去了大半,只剩3000多了。更可怕的是我的时间又用去了一个多月。

   这是后话:那个客户我这几年就再也没有见过。后来听说他过得很不好,很多人都在找他,他又让合作伙伴坑了一次,基本上就再也没有听说在这个行业里做过什么了。

   11,灰心

   万分沮丧的我把情况告诉了芸,告诉她的时候我分明听到了一个美丽的泡沫在她心里破碎的声音。她表面上没有说什么,但我知道她失望极了。我们相拥无言,我只能从她这里得到一丝温暖和安慰。她说,你别急,没关系,我们从头再来。可是,我的爱人,你知道吗,这个打击甚至让我回头审视自己,怀疑自己:我这样的一个北方人,是不是适合在上海打拼?

   尽管万分失落和失望,可我不能让我的女孩对我失望。第二天我强打精神对阿芸说我要重新开始。我考虑了一夜,因为我已经没钱了,不能再租原来的房子了,我必须去找一个民房住,每个月可以省7 ~ 800元左右。但是这样就不能和芸象以前那样离的那么近了。我说我不能停下来,时间不多了。芸哭着抱着我说,我一定要多来看她,她会很想我,我有经济困难一定要来找她。我笑着说,你有经济困难也要来找我啊。

   朋友们,尽管时间已经过去了那么久,可是今天我回忆到这里的时候仍然泪流不止。那时候我已经处于最低谷,生存也成问题,可是我仍然愿意回忆那时的事情。我怎么可能想到,命运老人会让以后的我和她发生那么大的变化?     
 
   12,初醒

   我搬到的一个民居是个私房,就是农民自己盖的房子,房子里面夏天热冬天冷,而且只有10个平房大小。我已经很满足了,这里每个月租金才200元,比以前我已经省了800块钱了。

   搬过来以后,我有很长一段日子不知自己干什么好。我想这是载过跟头的人的通病吧,相信有过类似经历的朋友会有同感。可是不做事情我心里又焦急万分。这种矛盾的感觉真是让我每天心里都不好受。

   转眼一个月就要过去了,这个月里我基本上是馒头就咸菜,肚子里油水实在缺的厉害。我决定去买点熟肉解解馋。我这个民房周围有几个新改成的小区,因为离市区比较远,基本上是一些市内动迁户迁到这里来的,真的购买这里房子的人也都没什么钱,但是这样的人在上海很多,小区外人气还是不错的。这里不像高价房,高价房是开盘很久了还没见几个人烟。小区之间有条街,人很多但大都是些老人孩子在转悠。熟肉店生意好象不是很好,我要了一些肉又买了一瓶啤酒,在旁边小店的简易桌上坐下来吃。

   多年以后我回想那个时刻,还是认为那是上帝给处于绝境的我的一个机遇。就在那时,忽然有人和熟食店老板说话,在说老板,你这生意不行啊!是啊,那老板说,我下礼拜农忙,准备回家了,不做了。那人说,那你这店怎么办?那老板说,转了呗,这半年没赚什么钱,还不如做点别的。忽然我有一种苏醒的感觉,我到处找钱赚,可是好高骛远,忽视了这身边的机会,难道自己一直没看见?我马上站起来,让老板再给我一点牛肉,然后漫不经心地问他转让店面的情况。

   不过十分钟,我就清楚了:这个店也就10个平方左右,月租金1200,租金他多付了两个月。转让费他要求不高,不亏就行,带一点简单的设施,2万块钱吧。我说我想接手,但是价格太高,他降到了1万8。我说1万5我今天就要,他回去和他老婆商量了以下,同意了。我立刻回房拿了我仅剩的3000块钱作为订金付给他,然后当晚立下转让书,当然他同意我7天内把余款付清。


13,努力

   我找到以前公司的老板,请他借给我钱。我还带去了我做的那份策划书,说我送给公司的。老板也多少听说了我的事情,他详细地了解了我的境况,二话没说借给了我1万5千块钱。我笑着说:“老板,我把身份证押在你这里吧?”,老板也笑着说:“你要不要我的身份证,1万5我押在你那里?”其实到现在我都一直敬佩我的老板。他的事业现在也做得很好,家资3000多万了。

   能让我的店面生意大为改观呢?首先,我回忆到以前的鸡粥店,觉得上海人爱吃鸡,特别是白斩鸡,还有烤鸭,决定经营品种适当变化;另外,饮食业最重要的是卫生(卫生许可证一年一办,已经有了),我决定彻底打扫店面一天,店面重新贴开业标志,另外买了一个二手的消毒柜,特意摆到台面上让客户看到消毒设施的过程;然后,我找了一个上海老师傅来指导制作工艺(退休了返聘,很便宜的),再找了2个勤快的四川妹帮忙,允诺给他们业绩5%的提成,但是不行我就换人;等等大概有20多条措施吧,我当时可是写满了2页纸的,全部做完已经过了近10天了。最后,我买了一些鞭炮,噼哩啪啦一放,人气立刻被我吸引过来了。呵呵,当天忙到夜里11点,一盘点营业额居然有500多!

   14,曙光

   做过生意的朋友都知道,开业的当天生意好不见得以后生意一直会好。因为刚开始客户是好奇,试一试,一旦没有什么特别吸引之处,他们就会立刻忘了你。而你要再吸引他们的注意力就困难得多了。

   我明白这个道理,所以第二天开始就在店面前不停的拉人聊天,问味道怎么样,然后不由分说要送他们一些熟食。上海人内外分的很清楚,他们决不会白要别人的东西,绝大多数都付点钱,当然他们也不会白给别人东西。当然我明白,生意的关键是我的货品要合客户的口味。慢慢的我的小店人气就有了。我还请人在几个小区里张贴了我们店的广告,也请人故意拎我们的烤鸭在几个小区人多的地方走动,相互之间含喧,巧妙吸引人们注意。通过很多这样的方法,一个月后我的店每天的营业额可以达到800元左右,而且还在不断上升中。呵呵,我以前的策划功底全部用在这上面了。

   我这样起早贪黑的忙碌,每天大概干14、5个小时吧,完全把心思扑在了店面上。作了第一个月的生意后,我盘点了一下,我一共赚了9000元钱;第二个月我赚了12000。把欠的债还掉后,我又没钱了。但是我感到,我生命中久违的曙光已经来了。说实话,这种感觉真的很美妙。          一个业务员某天的外贸心情

   15,做梦

   我就这样经营着自己的小店,时间又过了3~4个月。其间我忙得每天只睡5、6个小时,一躺下就昏迷不醒的样子。我和阿芸通过几次电话,她也忙,因为她升职为资深业务了。我们见过几次面,她都让我好好休息一下,我笑着说,把你娶回来再说吧。她说你靠那个门脸赚到钱了?我笑笑,决定几个月后给她一个惊喜。

    4个月后,我已经攒了5万块钱,可是也快到年底了。算算我的时间只剩13个月多一点了。如果按照现在这个模式发展下去,我完成目标15万的可能性是稳稳的。我每个月只要保持现在的状态,那么一年以后我应该用18~20万。钱是够了,还可以办个像样的婚礼,不过买房子是暂时不用想的。呵呵,看到这里,不知道又有多少朋友在笑我—楼主的幼稚病又犯了!是啊,如果没有房东的收租事件,我想我会把这样的梦做下去吧。

   房东来收过几个月租后,就到年底了。有一天房东忽然出现说是要签明年的租房合同,但是价格贵了一倍。气得我差点翻脸,这分明是看我生意好了眼红嘛!可是我知道人在屋檐下,不能不低头啊。再说我现在可是一点问题也不能出。我和他好说歹说,又送给他了一些熟食,房东还是加了我1000块钱。

   这件事让我意识到危机已经显现。生意做得好了以后,第一房东的房租会涨价,不可能再跌价,各种费用也会涨;第二,很快竞争者就会出现,出现以后和我的小店是同样规模,势必会分流客户。所以这种赚钱的状态是不会持久的。如果我不动作,最后的结果我想也想得出:小店几个月后就回到维持生计的地步。那么我该怎么办呢?我一夜没睡,苦思对策。

   第二天一早,我下定了决心,决定孤注一掷,冒一把大险!


16,冒险

   我的计划是这样的:第一步,在附近的小区再开几家这样的熟食店。地段只要和我现在的店面地段差不多就行了,但是不能太近了,然后用一样的装修、一样的名字、一样的策划手段,建立起小区居民心目中品牌形象,这样进货价格会便宜很多,还可以逼迫后来者提高投入。这个计划实施的越快越好。第二步,我觉得现在这个商铺的价格不高,2000多交租不如我把它买下来。上海的朋友都知道,2000年底上海郊区的房子价格只有2000多,商铺也只有3000多。这一步必须稳步实施,一个一个来。但是这样我就是必须投入我现在所有的5万块钱,如果一旦失败,我的时间、金钱投入可能会让我的目标彻底无法实现。但是我又想,我不去做,就把希望寄托在别人别来抢生意上,我去做了,希望在我自己身上。相比一下,我愿意把希望寄托在自己身上。

   但是我以前所想的给我的芸一个惊喜的计划只能延时了。我心里对自己说,为了她,拿出你所有的劲吧!那是无比艰辛的一个月。我不仅要照顾一号店的生意,又要为二号店、三号店选址、选人、买设施、店面布置等等。后来我提高了一个一号店店员的提成比例,封他为店长,告诉他1个月后店里的营业额如果下降5%以上,立刻换店长。这样我就全身心投入到新店的开张。1个月过后,我的二号店、三号店相继开张,我还是无法清闲,又开始了以前那样的策划造势,而且开始了四号店的准备工作。

   后面的一个月,我一号店的盈利状况还是不错,达到了12000元,二号店5000元,3号店最好,居然有10000!要知道这是头一个月,人员还不熟呢!我发现原因是一个女孩店员做生意很有天赋,也会招睐客户,我二话没说给她工资翻倍,直接提升为店长。

   年底如期到来,我和芸只在一起度过了半天,就不得不忙着自己的店面了。芸要回家去,我不能走,目标没有完成我怎么能见她家人呢?不过我和她妈通了一个电话,她妈笑着说:“小D,我们知道你是个好样的孩子,我们都盼着你把我家芸芸早点娶走呢!”我知道这话里的意思,也笑着回答说:“我会的,谢谢阿姨和伯父的信任。”

   年底年头的2个月,因为过年,节日也多,我的生意好的一塌糊涂。四号店也赶在春节前开了。这两个月每个店平均一月能赚15000,2个月后我身边的现金达到了12万。元旦前还有一件事,原来的老板给我打电话说,他公司还有一个转入户口的名额,问我要不要,我说要。他说我什么都不用管了,把资料给他就行了。为了好好感谢他,过年时我去他家给他的孩子送了一个5000块的红包。年后不久我的户口办下来了。我开始逐步的和各个东房谈要购买铺面,如果他们不卖,我就找别的房东谈,那是很多房子是物业的,比较好拿。而且那时候房价低,再说我找房子前就打的有伏笔,另外我价格给的稍高一些,前面3家都谈的很顺利,单价大概在3700一个平方吧,一共13万,我全部给的是现金。第四家以一共要5万(生意好啊,房东要挟我),我没钱了,但是抵押了前面的一家店作为3万先签了意向书,等到一个月后,资金回笼了,把钱凑齐了把店拿了下来。

   这时候已经是3月底了,我还剩8个月。生意好象在稳步进行,目标好像越来越近。可是我没想到,一个足以摧毁我的重创也越来越近了。直到今天我回想到这个让我记忆深刻的时间段,还觉得眼眶里泪水未干。


   17,重创

   时间又过了3个半月,马上要到7月10日了,我之所以记得这个日子,因为这是芸的生日。我决定在这个日子之前攒足15万,并把这个消息作为生日礼物送给她。想到她得到这个礼物时候的开心,我的心里别提多激动了。这几个月店面也争气,每个店都能够达到10000多的利润,这是因为我店多了,进货成本低了,而且房租也不用交了,还有一个最主要的原因就是我用了一个很好的店长—小成。

   小成就是我前面破格提拔为店长的那个女孩子。这女孩是从浙江来的,只有19岁,人长的清秀漂亮(因为要招徕客户,这是一个比较重要的因素,招人的时候我就特别注意要找看着舒服的女孩)。因为一般的外来妹大多不是浙江来的,所以我特别留意她。没想到这个女孩在做生意方面真的很有天赋,她一直是很开心的样子,从没见过她烦过,会说话,人很甜,客户缘很好。而且她很有脑子,开业没几天就把所有的常客的名字记熟了(我估计她是问周围的店主和客户的),还建议我,天气热了,店面里配点素菜,啤酒,买点简易桌椅,晚上让客户边吃边纳凉。她还把周围的几家饭店的电话弄到了,把饭店的生意也拉了进来。后来我们熟食店里的生意饭店进货居然占了30%!


不过她也有一点不好,就是好像身体太单薄,力气活干不了多久就累得脸发白、出虚汗。小店生意好的时候,这也挺影响的。我考虑了几天,决定扬其长,避其短,在店里又招了一个身强力壮的小伙子给她打下手,告诉她只管招徕客户,管理帐务。

   这时候我的一个朋友打电话给我。原来他不知道从什么地方得知我开了几个店,做得还行,而他正在做房产销售,代理一个别墅的盘子,非要我去看看。上海的朋友都知道,2001年的时候上海的房产还远远不热,房产销售尤其是高价房的销售很难做。他代理的那个别墅房型有180多个平方,周边的配套还不完善,再说总价要80万朝上,我不想买,就告诉他没那么多钱。他说,你来看看吧,看了肯定喜欢,再说钱的事情好办,贷款就行了。我说那还要首付呢,我首付也没有。他说没关系,他可以在合同上做点手脚,让我零首付,全部贷款。我没办法只好去看看,没想到看了以后特别喜欢别墅下面的花园,因为我记得芸曾经告诉我说,她的梦想就是住在花园的上面,每天早上打开窗户就能闻到花的清香。朋友看我有意,就拼命鼓动我说,买了这个房子这个优惠,那个免费的,每月只要付6000多就可以了。我还是有点犹豫,说我不想每月跑银行。他说,我帮你办,每月自动划款,不用你操心的。我没什么再挑的了,想想就定了一套。不过后来知道,这小子还是打了埋伏,有些言过其实:窗户就不是他说的双层的,车位也不是免费的,呵呵。

   7月9日,我拿着那份15万元的存折卡,兴冲冲地拿着一束花,拎着一品瓶红酒(蛋糕明天叫人送来)赶往芸的住处。之前,我已经给她妈打了一个电话,向她父母亲问好。同时告诉他们,我已经提前5个月实现了诺言,很快就会娶她家女儿了。我决定先给芸一个惊喜,然后今晚就住在她那里。我特意赶在她下班前一点赶到,准备突然出现,吓得她快乐的大叫。

   可是让我始料不及的事情出现了,芸下车时不是一个人,而是和一个男孩一起。他们手拉着手,好像很亲昵。我一下傻了,不知道怎么办好,他们一起进了小区,我傻乎乎地跟在后面。在光线阴暗处,那男的还一把搂住芸亲了一下。我的脑袋轰的一下,再也受不了了。我大叫着芸的名字,冲上前去一把抓住芸,然后就要打那个男的。芸吓了一跳,拼命地拉住我,对那个男人说快走,你先走,我跟他解释。男的走了,芸还是拉住我不放,我叫到解释什么?解释什么?一边眼泪就快下来了。芸看着我,很冷静,冷静的我们好像不认识。她对我说对不起,早该告诉我。但是我今天太不冷静,她希望我先冷静下来,现在的气氛我们没法谈。我没办法冷静,说不行,今天你就必须给我一个说法。她被我纠缠的没办法了,对我说,D,一直以来,我以为你的素质很高,你今天这样会让我很失望。我停了下来,看着她,眼泪慢慢地流下来,最后对她说,好,我走,明天来再谈。出了小区,发现花和红酒居然还在手中,一把把他们扔进了垃圾箱。

   那夜我一夜无眠,盯着外面发呆,怎么也想不明白事情怎么会到这种地步。第二天一早我在芸的楼下等着。芸下来说我们找个地方吧。我们到了一家茶室,我呆呆坐下,等她解释。那天她说了很多,我都有些记不清了。她说,其实从我搬走我们就很少在一起了。她知道我很努力,很辛苦,但是经历那么多波折,真的很怀疑我是不是能够实现15万的诺言。她心里开始很怕,但是又没机会和我说。我的压力又不和她分担。在上海这么长时间,她和我一样做得很辛苦也都没有归宿感,觉得很累。这时候她的上司,就是那个男孩出现在她身边,男孩是上海人,比她大4岁,在公司职位不错,家里条件也好。芸说和他在一起,她会觉得很安心,很安定,很有安全感,不像和我在一起,虽然感情曾经很热烈,但是总是不知道我们的将来在那里。她说对不起,真的对不起。我激动的浑身乱颤,说不出话来。好容易稍微平静一些,我告诉她说,我现在有15万了,你还会爱我吗?她说,对不起,我觉得现在很好,我不能再对不起他了,我们不会再在一起了,希望你将来幸福。出门的时候我发现了那个男孩,心里又一阵刺痛。约在这里,一定是他们商量的结果。


   18,怀疑

   这真是一个巨大的讽刺。一直以来,我以她为努力奋斗的动力,可是等我奋斗到了目标跟前,却发现目标忽然消失了。我记得那时候,我开始失眠,希望自己赶快入睡,然后梦见芸。可是我一次也没有梦见她,倒是我清醒的时候一刻也没有停止想她。我经常觉得心里刺痛,头皮发麻。一直以来,我那么小心翼翼地把她放到我心里的一个最温暖、最柔软的地方,没想到最痛苦的打击却由这里产生。

   有一个朋友曾经回贴问我,怎样才能获得不爱你的女孩的爱,我没有回答。不是我不愿回答,而是我不知道怎样回答。我真的不是这方面的专家,我也曾痛苦无比,希望能够改变我爱的女孩的心。可是我没有什么办法,只有自己默默地退回,独自一人舔着自己的伤口。 

那段时间我对自己过去的所作所为产生了怀疑,我这么做到底有什么意义?如果我还在公司工作,每天还有时间,情况就不会这样。如果我不搬家,事情也不会这样。如果我不开店,就有时间陪她,情况也不会这样。就是开店了,如果我不开分店,也有时间去看她,应该也能阻止她情变。每天我这样乱七八糟的想法充斥了我的脑海,让我对生意根本提不起兴趣。 

   店里的员工都看出来了,他们小心翼翼的不敢惹我。几个店长都很称职,生怕店里的事情会引得我大发雷霆。尤其是小成,她主动找到我说她来每天到个家店里盘点,让我忙我自己的事。我很感激她,也相信她的能力,就告诉几个店以后由她来查店。我知道自己这个状态如果硬让我去,非出事不可。小成很有手段,也有能力,查店每天要多做2个小时,她很快让其他人服服帖帖。还好,有小成和他们的帮助,我的生意没有什么影响。

   但是我自己知道,我已经迷失了前进的方向。我不知道怎么再找到这个方向。


   19,迷失

   有人说工作累的时候,家里压力大的时候很辛苦,我却不是这样认为。我觉得一个人迷失方向的时候最痛苦,因为你不知道自己应该做什么,这种状态每天无时无刻不深刻地提醒你不过是一具行尸走肉罢了。那个时候就是我迷失方向的时候。我就像一个被抽去发条的时钟钟摆,每天不过是由惯性推动我在摆动。我不知道什么时候会停摆。也许在我的内心深处还在暗暗期盼那停摆的时刻。

   芸的妈妈给我打了一个电话,接到电话知道是她,我心里真的不知道是什么滋味。她妈对我说,孩子,阿姨知道你很难过。你们年轻人的事真不知怎么搞的。但是阿姨告诉你,你是个好孩子。你的前途还很远大。阿芸不能和你在一起,是她没福。好好的,我们全家都祝福你。听了这话,我的眼泪又留下来了。以前觉得她是那么固执和势力,今天怎么觉得她的话那么温暖。我终于能够真正站到一个父母的角度上来看彩礼这件事,是啊,那是要把自己女儿未来幸福生活尽量多地抓到手里的感觉。

   在这里我要感谢我的一位大学同学枫,如果不是他凑巧来到上海,要我陪同的话,我不知道我这种状态要持续多久。枫来上海玩,指定我陪,而且说陪得不好当即给所有哥们打电话说上海没我。我强打精神,枫还是有所察觉。枫一见我就说,你小子怎么减肥减的那么明显,不行不行,我们不能一起照相,否则班花见了照片,我一点想头都没了。他就是这样,那几天逗得我开心了一些。要走的时候,枫说,说说吧,怎么了。我这才知道,他早看出我有事,所以一直在让我开心。从芸变心以来,我从没有向人倾诉过。枫听过了之后,很久没有说话。后来一开口就是一句:“好!这是好事!”我听的愣了。

   枫接着解释说,我和芸现在分开始好事。因为就是现在不分开,我们早晚要分开。因为我们不是一路人。芸的内心深处时那种安分守己的人,经不起动荡,分开的时间主要视我波动的强度而定;而我是那种不安分守己的人,越是不利、越是艰难,越能激发我的能力。我适宜在变数中求生存,求发展。而且我不是很在乎物质,所以要的感情是非常纯粹的,女孩子大多到了要结婚的关键时刻,生活现实和抚育后代的本能让她们不得不物质起来。这不能说不对。这也是为什么当初芸自己也不反对彩礼的原因。他说,我这样的人,只有物质生活到了一个水准后,交往的女孩子才会有安稳的感觉。现在还不行。但是我应该感谢芸,她激发了我,她放了我是我的幸运,否则我们在一起,芸一定会成为我的桎梏。他还说,你的奋斗动力就是她?那你的家人,朋友呢?我们呢?你以前的老板呢?你的员工呢?我们还一直以为你能成大气,为了我们这份信任,你也不应该放弃。而且,说实话,你的这点家业还很小很小,一不小心,很快就败了。

   他还告诉我要留意小成,这小姑娘太聪明。我就是对女的太迟钝了才栽的跟头。以后绝对不能让她独掌财务大权,我一定要控制住她。最后,他拍拍我说,兄弟,醒过来吧,外面的世界很残酷,也很精彩,但是绝对不是为这个样子的你准备的。

   枫,今天的你也在看这份贴子吗?如果是的话,我想对你说:哥们,真的谢谢你!

20,心意

   因为那一场直抒胸臆的倾诉和枫的精到劝慰,我终于慢慢开始摆失恋的阴影。我特地给家里打了电话,给弟弟也打了电话,同时也和同学朋友纷纷联系,又去拜访了以前的老板,他们都为我在上海的奋斗状态和所得高兴。我之所以这样做是想提醒自己,我的世界还在,我的生活还在,我要主动地让他们把我拉回到我的世界里。他们对我的爱也会成为我的动力,这是更绵绵不绝,更持久的动力。 

   同时我也听取了枫的建议,重新收回了店面的管理权限和财务权限。我把小成和另外一个店长互换了位置,然后仔细的查询了最近的账目,还悄悄地私下和其他人谈了谈,侧面问了问他们对小成的看法,大家都没说什么有价值的话,除了一号店店长,他的资格最老。一号店长说小成太跋扈,太不尊重人,什么事情都自己定,也不和老板商量,更别说其他人了。每天的财务帐、现金全是她管,根本不让别人插手,也不知道她是怎么想的。因为我暂时没有查到什么小成的把柄,所以只能安慰一下他,也没有做什么动作。

   这时候4号店的小徐(他就是我招的为小成打下手的伙计)找到我,要求要换地方,他要跟小成到一个店里去,否则就辞职。我一开始很奇怪,后来恍然大悟,明白了小徐的心意:原来小徐已经喜欢上了小成。我同意了小徐的要求,同时更为警惕,因为公司里有一对的话,容易形成小集体,而且他们容易一起跳槽,成为我新的竞争对手。我不得不暗自多留心小成和小徐。


   21,真爱

   我的心意逐渐回到了生意上。不得不承认,小成有一套。她总结出一些管理规范和待客方法很有用处。她的做法比我原来的做法更细,我比较倾向于策划一些活动和办法,短期效应比较明显,但长期的发展还是需要细化的管理。生意还是缓步发展,我们基本上每半年利润提升20%,这一方面因为管理的细化,人员的熟悉;另一方面还是得益于这里的人气渐渐旺起来了。这样过了年,到了2002年4月份,我的手头已经有了超过50万的资金。经过和小成交谈,了解了她的很多想法,我觉得我暂时还时离不开小成。这段时间我发现小成对小徐也是淡淡的,他们的关系好像并没有变得密切起来。

   因为对小成的留心,我发现了小成身上的越来越多的细节:她一个人住,爱干净,爱笑,爱看书,很怕冷,尤其害怕感冒,不喜欢猫狗等等。因为生意的缘故,我和小成的交流越来越多,也就越来越了解她的聪明和能干。有时候我想,这么聪明的女孩因为家庭的原因不能上大学真是可惜了!又转念一想,就是上了大学又怎么样呢?大学生我自己不就是吗?我见得还少吗?原来戒备心理也可以让人如此留意一个人。

   有一天我去查店,发现小成没来上班。我们一般上班很晚,下班也相应晚一些,因为生意一般是在下半天。写到这里,我想到有的朋友怀疑一个10几平方的熟食店一个月的利润怎么会有10000块钱,我想说,生意人人做,关键看你怎么做。我们的每个店周围都有1000户左右的小区,很多是租户,他们不愿开伙。我们每天晚饭时段一般要做50笔生意,每笔十几元,这样营业额就有700元左右。食品行业一般利润率一半左右。节假日更好做,还不算饭店的生意。当然,我们不用交房租。而且现在的生意也不如那时了,这是后话。言归正传,我发现小成没来,就问了一下,有员工说她不舒服,今天不来了。小成没来,小徐也没来,我想想反正上午每什么事,应该去看看小成是不是病得很严重,就向他们问了地址,出来买了点水果,打车往小成住的地方赶去。

   小成住的地方我没有来过,到了小区门口我才发现是个比较高档的小区,这里一室一厅的房子一个月要1000块吧,我边走边想,一边又很不解为什么小成会把月收入的一小半用来租房,尤其是想想自己才刚从私房里搬出不久,现在的房子也不过是1000元左右。正在胡思乱想,忽然发现小徐从一个门洞里出来,急匆匆的样子,我连忙回避在一旁,看着小徐跨上自行车往店面的方向赶去。

   忽然在这里看见了小徐的片刻,我的心里产生了一种很奇怪的滋味。一种很不舒服、心头微酸--好像是吃醋的感觉,同时觉得一阵懊恼。这种感觉没有经过理智,完全好像是自然而然产生的,只是片刻之后,我忽然一阵震惊---难道我如此在意小成?难道我不知不觉已经爱上了她?这是一个连我自己都吃惊的发现,因为失恋的很久以来,我一直觉得自己好像已经不会爱、不能爱了,有时候我会接触到一些女孩,可是我根本无法提起感觉。没想到,我爱的感觉会在小成这里复苏?小成可是我一直提防的人啊!

   刹那之间,我的脑海里风起云涌,万种思路好像被同时激活:是我失去了芸,把小成作为一个感情的替代者了吗?不是,和小成在一起的感觉完全和芸不同,我们的交流更平和,因而更交融,我也感到更轻松。和芸在一起完全是被激情和冲动淹没,我们心灵层面的交流显得更少---如果更多的话,也不致有那样的结果;是我因为她病了而怜惜她吗?不,怜悯和爱我是分得清的,现在我的心里分明有一种心痛而且甜蜜的感觉;难道是见到小徐引起的男人本能的异性排他性不满?也不是,因为我清清楚楚的知道,我决不是一个把身边所有女孩都看成情人的情圣…..你呀你呀,你经历过感情的痛苦,所以你一定要分辨清楚,这是你的真感情,你的真爱吗?你不要糊里糊涂的再带给自己或别人痛苦了!

   可是我越是想,小成的笑脸、话语和我们交流的场景等等印象就越清晰,我就越觉得小成是真正适合我的女孩。她的开朗,她的平和,她的聪明能干,她的善解人意,还有她为我的事业作的努力和成效,当然还有她可爱的、惹人怜惜的样子---这些我以前都没有明显地感觉到,可是今天我感觉对我来说就象空气一样不可缺少!

   爱情的幼苗一旦破土,成长的速度真是惊人!在我伫立楼下不到30分钟的之后,我已经感到我的心胸开始无法承受它的奔涌,必须要向她倾诉才能缓解。可是我不是一个语言表达爱意的能手,尤其是现在这个令人激动的时刻,我觉得我现在激动的别说讲话了,连一口气都不能顺畅的呼出。我忐忑不安,但又决定立刻向她说出来—就是现在!


敲开她的房门的时候,她的脸色有些苍白,可是她的目光那么平静,柔和,一点也不吃惊。我反而更加慌张,不管了,我必须要说--- “我,我……你,你,你病了……我发现我离不开你!我发现我爱你!小成,你听我说,我爱你。我喜欢你。我要给你说,我离不开你了!”

   那天我说了很多吧?不知道,记不得了。可是结果我却记得,小成拒绝了我。

   22,原因

   在感情方面,我是一个脸皮很薄的人。小成不声不响地听完我语无伦次的表白后,低着头平静地摇头表示不能接受,我就不知道该怎么做了。为什么?因为你和小徐?我问。她摇摇头,没有说话,但我看到她有眼泪流下。呆了一会,我不知该怎么做,一直惶惶惑惑地。最后,我还是离开了她的住处。再见到小成,是2天后了。她来上班,我早早等在店里,远处一见她的身影,心里就怦怦跳个不停,可是见了她的面又不知该怎么说话。她看见我,好像脸红了一下,就再没和我说话。说实话,我觉得她是喜欢我的,尤其是回忆到她以前帮我时那种自告奋勇和尽心尽力,我越发这样认为,但是她为什么拒绝我呢?我想不明白,哎,真不理解女孩子的心思啊。她工作起来还是那样井井有条效率很高。我不愿打扰,就去其他店了。

   到了4,5月份,天气有点热了,因为刚过了年,生意是属于淡季。我们希望再热一些,这样人们愿意出来吃饭;不过因为天热,食品行业风险很大,绝对不能出现食品变质,否则对生意的伤害是很大的。我们这时候一般加紧和饭店联系,因为饭店要量大,而且可以预知,这样风险小。因为这方面一直是小成负责,所以现在淡季反而她会比较忙,我也比较放心。没想到,不久小成忽然出了事情---她累得晕倒在了店里。

   当时我接到电话飞速赶到店里,小徐已经把小成扶在椅子上坐着,根据小成的指点正在给她味药。小成坚决不同意去医院,小徐他们也没办法,看见我来了,都像看到救星一样。我不由分说,对小徐说:你出去打车,我们两把她送医院!小徐一出门,我一把抱起小成就走。

   小成在边挣边说不去,我根本不停。我知道,不让小徐他会和我急的,但是我也要和小徐公平竞争。很快送到了市八院---离我们那儿打车要30分钟吧,我们等在旁边,护士就要开始测血压、测血、停诊了,对站在旁边谁都不肯离去的我和小徐说:“女孩子衣服你们小伙子也在旁边吗?”没办法,我们只好出去。

   我们等在外面,小徐一直不和我说话。大概他感觉出我对小成的意思,他有些戒备吧。大概过了几十分钟吧,医生出来小声说:“成**,同事还是家属?”我们都站了起来,医生责备的对我们说,小成有先天性心脏病,根本不能工作劳累、激动,更不能感冒。她的心脏已经比普通人大了,因为小时候没有手术治疗,现在手术的可能性很小,只能静养。

   这时候我的脑海里如电光火石一般,一下明白了为什么她一累就脸色发白;为什么她不能干体力活;为什么她怕冷,不能感冒;为什么她住那样的房子---因为医院近;甚至,我也明白了---为什么她拒绝我。小徐显然也不知道这个真相,他愣在一旁一时有些不知所措。我抢先冲进急诊室,小成也看见了我,她显然也听见了医生叫我们。她的目光平静,柔和,还有---期待。我走到小成身边,抓住她的手,对她轻声说:我知道了。你该早点告诉我。

   我和你一起,我们一起面对,好吗?说着把她的手贴在了自己脸上,小成的眼泪刷地下来了。这时候,小徐进来正好看见。护士着急地说,她不能激动的,你们出去!出去!

   我终于得到了小成的认可。她后来对我说,其实她开始是觉得我失恋了,很可怜,愿意帮我多做点事,后来就慢慢喜欢上了我;可是后来她发现我在防她,很让她伤心;她拒绝我一方面是因为这个---女孩子的报复心,她也有;另一方面,她早知道自己的病,也不想拖累我。最后她在病床边倚着我,泪光闪闪的对我说:“你知道吗?一个女孩子在外面,很多时候真累啊。我晕倒的时候,心里想,真去了,别的没什么,就是好后悔啊,我应该和你爱一场啊。我是不是好自私?我真的是不甘心。”我什么也没说,只是把她紧紧的搂在怀里。


   小成还告诉我,其实她是出生就有这个病了,他父母亲一直在做生意,家里人其实不缺钱。

   家里人让她读书读到高中,考大学已经考上了,但是担心远没人照顾,死活不让她去上。小成很不愿意自己成为家里人的累赘,自己跑了出来打工,决心自己养活自己。她以前就和家里人耳濡目染,所以对生意很在行。正好我把她招了进来。她说,小徐一直对她很好,她加班小徐一直陪着,可是她知道他们不可能。

   没几天小成坚持要出院,她说住了多少次院了,还是家里舒服---不就是静养吗。我们搬在了一起。这是我的坚持要求,我说我一定要照顾好你。小徐要辞职,我没说什么同意了。

   最后,我和他一起吃了顿晚饭。他深情黯然的说,没想到她有那么严重的病,我就是愣了一会,哎,你先跑进去了。后来喝了点酒,他又说,你比我有钱,她当然选你。我一般抓住他,对他说,你胡说,小成不是那种看重钱的人。至于钱,小徐,好好努力,你还年轻,你也会有钱,也许比我还有钱。到那时也许你会明白小成。

    3年以后的一个偶然的机会,我又在闵行体育公园附近见到了小徐。不过他早已今昔非比,他对我说,他一直没忘我的话,也自己憋了一口气。辞职了以后,他先是自己骑三轮车从七宝蔬菜批发市场批蔬菜到小区卖,后来自己租了个摊位,后来卖猪肉,再后来自己买了一辆二手嘉宝,自己去江苏进猪肉卖。3年以后,刚刚挣了50万,在附近买了一套80平方的房子。他最后说,还是要谢谢你。我想起身边和网上很多朋友不停地抱怨房价飞涨,抱怨没有工作,抱怨辛苦赚不到钱,抱怨这里抱怨那里---其实他们连一个高中都没有读完的小徐都不如!


23,乏术

   我看到有人在怀疑我的经历的真实性,想要向他们争辩,想想又算了。每个人的生活轨迹不同,想法不同,就是向他们证实了又能怎么样呢?能改变生活现状吗?我还是写下去,就算是经历了这么多的总结吧。但愿有朋友在看的时候能够获得共鸣,获得激励,产生力量,进而改变你们自己的人生。如果不信,也没什么,因为我们生活不同,而且都要继续。

   小成和我的关系定了以后,我们会经常长时间的交谈。她读书很多,尤其喜欢古诗词。我们很多事情都谈的津津有味,可以就一个事件谈上几个小时。现在我在想,谈恋爱谈恋爱,说谈是有道理的吧。她有时候会从梦里醒来,一声不响地看我半天。我问她为什么,她说她高兴,睡不着。有时候她会流泪,说是想家了。我要和她家联系,她又不让。我不再让她查店,每天带着她看看就行了。可是她闲不住,对我说,我要闲着就在家耗着,跑这来干嘛?

   我也没办法。本想生意就这么发展下去,我们也不会担心未来钱的事。可是这时候生意忽然被一件没有料到的事情影响了。

   过了几个月,我们这里要听说要修路了,要打通和大马路接上。因为我们有2家店面是属于临时房,肯定会被拆掉。临时商业房拆掉,市政会补一点钱,但是对我们来说并不划算,因为附近的铺面已经涨价了,客户也熟悉了。我考虑了很久,也没有什么办法。为了不让小成知道担心,我并没有在她面前表现的压力很大。

   同时我也暗暗留心小成的病情,我觉得好像越来越严重了。我也到处查找她的这个病的原因,治疗方式和注意事项。大夫给我说的是对的,这个病一般不能结婚,更禁止生育,因为她的心脏会受不了。一般在婴儿时期手术解决,成人后手术成功率很低。目前除了静养,不能劳累,尤其不能感冒。除此之外,还没有比较好的治疗办法。我觉得这个障碍比我以前碰到的任何一个都艰巨、困难,有一种一筹莫展的感觉。


   24,诀别

   也许很多朋友的感情经历比我复杂的多,但是一直以来我都认为命运待我不公,一直以来我也在问上苍:为什么不给我一段长一点的真爱,比如说一辈子。直到不久以前,我才解开这个心结(请看后续章节)。看到这一节的标题,朋友们想必已经知到了结果。原谅我写得这么慢,我不能平静自己的心情。

   小成自己也有感觉。她有时候会搂住我说,真不想把你交给另一个人,我让她别胡说。有时候她会说,我走了以后,你一定要找一个好的。你看,她在不停的矛盾。我觉得她真是普通人,一个平凡女孩的心思和想法她都有,正是这些让我觉得她一个让我无比怜惜的人。她的心跳越来越快,也不规则了。我不再让她跟我去店里,还找了一个阿姨照顾她。有一天,她对我说,不行,我帮你赚了那么多钱,从来没有做过主妇的感觉,你要把钱都交出来,我要管钱,做做主妇。我笑着把存折、密码、身份证、房产证都交给了她。有什么不能呢?这些我失去了相信还可以赚回。
   到了秋天,天气冷了,小成好象更不好了。她脸色不好,心跳过快,我还是把她送进了医院。我觉得一定要把她的家人叫来。她这次没有拒绝,但是她说她先和家里人打个电话,不让我听。电话不到2天,她的父母亲就赶来了。不知道她和她的父母说了什么,她的父母见了我特别的亲,一个劲在我面前流泪,还说这孩子脾气太倔了。我们3个人的时候,她的父母亲会象我自己的父母一样,不停的让我注意身体,多吃一些,多穿一些。

   我真的不愿意回忆那个日子,12月21号,她住进医院2个月半月的时候。其实她走的时候,心脏已经很大了。医生说,这样的病一般是心脏忽停,突然死亡,象她这样的比较少,她也属于比较严重的了。我留着泪在她床前听到最后的一句话是:难受,胸好闷。谢谢。


25,礼物

   我送走了小成。我不知道怎样描述当时我的悲痛欲绝的心情。因为我不能在她的父母面前表现出来,否则她的母亲根本没有办法控制自己的感情。想起前面有个朋友问我,如果用我的全部身家去换取真爱,我会怎样选择?我想我在这里可以回答了:朋友,如果你的一只手要离你而去,代价是你的全部身家,你会怎样选择?如果你有犹豫,那答案很简单---这不是你的真爱。我感觉到我的心已经是不再完整的了。

   在她的遗物中我发现了以前给她的存折,但是已经少了一个房产证---我的别墅的房产证。

   当然,我还发现了一封信。其实我早就知道她在写遗书,只是不忍在内心承认罢了。她这么聪明的女孩,一定会想到这些的。

   遗书里说:对不起,我不能和你一起忙下去了。别太难过,以后就是你要经常想我。遇见你很好,我本来害怕就这样糊里糊涂地走了,现在知道我的生命比我以前的想法好多了,我不那么遗憾了。就是会带给你和我父母痛苦……

    ……

   你要坚强,要挺住,你还要走很长的路吧。我把你的别墅给卖了---这是你给另外一个女孩买的,是吗?我做主了,你会怪我吗?因为我们的熟食店不是长久之计,你也不会甘心一辈子卖肉,是吧?我去定了一个商铺,首付就用别墅卖的钱,剩下的2个店,卖了吧,还有拆迁的店,拿到了补偿,和我们(我用了我们,你愿意吗?)以前的钱,不少了吧,别乱花。然后到我家去,和我爸交流一下,也许你能够找到机会。他会帮你的,我和他们说过了。你应该有更大的事业。

   如果我这样替你做主,真的赚了钱,就算是我留给你的礼物吧。亏了,就当我以前为你忙碌卖命,我应得的钱我又拿走了。呵呵,我不想要钱,只想你过的快乐一些,就看你自己的努力了……


   26,转型

   小成的事情之后,我的生意大不如前了,可能也和我的心情有关。2003年1月底,我卖掉了我的2个店。又过了3个月,我拿到了市政补助的资金。加上我手里的钱,一共109.5万。我的别墅,小成以8500左右的单价卖出,用80万左右做首付买了一个300平方左右的商铺,但是要4个月以后交房。这个地方的商铺,近一年后我在2003年12月时以每平方每天7元出租,一个月能收回6万多块钱,扣除还款我每月还能剩余4万块钱。这已经基本相当于我以前4个店一个月的盈利了,今年年初,我让评估师估了一下价格,已经到19000左右每平方了。

   小成,你又一次让我见识了你的聪慧。

   想到以前小成每天那么开心,那么充实的样子,现在我明白了:其实她一直处在生命随时会停止的阴影下,所以她的生活态度反而那么豁达,开朗,而又忙碌充实。这才是生命本来应该有的态度。我也应该这样生活。而且我不能仅靠收租为生。我又开始想着新的事业了,我决定如小成所说,到她家里去一次。我和她父母联系了一下,他们很热情,让我随时都可以去。我虽然比以前多了100万现金,可是我心里面一点也不轻松,因为这一次我面临着从饮食业到其他行业的转型,其实也是一种重头再来。

    2003年4月,我去了小成家。小成的父母在做皮革生意,他们一直在为国外的汽车和家具提供定制的真皮座椅和包垫。真没想到,他们生意做得很大。而且他们那里家家是作坊,户户是工厂,浙江真是让我见识了民营经济的力量。和她的父母交流之后,我才知道自己这100万现金根本不够做这个方面。她家人对我说,可以提供资金帮助,我也可以和他们合股做,我愿意留下来也行。但是我拒绝了。我有种感觉,这不是我要找的那个行业,另外我还是愿意自己奋斗。她的父母认了我为干儿子,我走的那一天,在她家吃饭,我喝醉了。她的母亲又哭了。 


27,尝试

   我最终没有接受小成父母的美意,不知道远在天国的小成知道我的这个选择后是满意还是不满意。我想她是理解我的吧,我一直那么独立,一直以为自己的事情要自己做。虽然没有做她父母的那个行业,但是她父母临走时说的一句话倒是让我思索很久。她父母说,现在他们的产品慢慢地国内的汽车厂家也开始要货了,这是不是说明这个大行业内还是有机会的呢?

    2003年4月底我回到上海以后,又以70万总价70%贷款买了一套商品房,毕竟自己也要住的,付房租不如付贷款了。然后我就主要在考虑下一步的努力方向了。饮食业我是不再考虑了,可能有点伤心的原因在里面吧。我希望有个崭新的事业,崭新的我。IT业我也认为不好,原因是我看到这几年身边的年轻人开公司有80%选择IT业,竞争太激烈了,而且经营状况并不理想,我估计还要至少几年淘汰这个行业才会正常。电子加工,服务业什么的,我都考虑过。想来想去比较了很长时间,我决定尝试代理国外品牌做汽车机油和高档润滑油。我觉得小成的父母给我的启示还是有几分道理的:国内的汽车市场现在才刚刚开始,还会有10几年的高速发展期,这个行业就像10几年前做计算机行业一样,是值得我投入的。

   我的习惯是:想法一经决定,行动决不迟疑。5月初,我找好了办公地点,开始招人;5月底,办公家具和人员进场;6月份,我拿到了营业执照和发票。我开始熟悉这个市场的渠道、客户、产品。那个时候我几乎每天都去吴中路,每天都上网查资料,每天都向国外写电子邮件询问产品性能,报价,索要样品等等信息。到了8月份的时候,我公司终于定下了一个全权代理和4项一级代理的产品。然后我开始在江浙一带的城市里不停地奔波,寻找、拜访代理和零售商,以及和他们洽谈。我是这样认为,以我目前的实力在上海的这个行业里撕开口子太难了,我应该先从周边入手。开始我是租车开,后来10月份的时候,我自己贷款卖了一辆马自达-福美来。我的现金我认为还是应该留着公司发展用。

   虽然2003年下半年我做的很辛苦,但是到了年底一算,我的这个公司并没有赚钱,反而亏损了12万–平均每个月2万的亏损。可能有的朋友会问,汽车行业2003年是最热了,你怎么还亏了呢?这个亏损我却一点也没有心痛和意外,一方面是因为我已经经历了很多生意上的风雨,更重要的是因为这都在我的预想之内。


   做生意有很多种,有的人是以长时间积累的技巧、经验、关系和渠道挣钱—这是以时间换空间;有的人是一招鲜、吃遍天—这是垄断或是以技术制胜;还有的人是用钱换取技巧、经验、关系和生意流通的渠道,这是以空间换时间–我就是这么做的。我刚进入这个行业,经验、关系、客户基础和渠道都不行,一进来就赚钱是不太可能的。但是更不能害怕花钱而停止脚步,生意一定要走出去,开发的流程不能停止。这半年来,虽然我出货不多,远远不能养活公司,但是我一是组织了团队,熟悉了团队,锻炼了团队的力量;二是建立了销售渠道,江浙一带我们开发了70多家下级代理,我们让他们试用先打开市场,还要熟悉竞争对手,客户公关等等,这一切都进展顺利。2003年汽车销售是很热,但是我认为我们这一块属于汽车保养和维修类会有一个滞后期。我们2003年底的业绩已经大大好于8月份。对于即将到来的2004年,我胸有成竹。


28,归宿

   公司的实际经营果然是按照我的预想发展。2004年1月份,我们的销量获得了突破,我们已经有些许的盈利了。2月份因为过节,生意比1月份下降5%。3月份获得30%的大幅增长,这样我们已经净盈利4万了。我加大了激励力度,我的团队志气如虹,一个个宣称今年底要比3月份的销量翻番。我知道,这是有可能的。因为我们前期搭就的平台完全可以承载这个销量---- 70~ 100个有规模的下级代理,每个月每个代理的销量达到8000 ~ 10000元并非难事。

   我的公司里招了几个上海的女孩子。原来我很少和上海女孩打交道---其实我就很少和女孩打交道,阿芸和小成而已。但是通过和我们公司的上海女孩沟通,合作,熟悉之后,她们让我以前对上海女孩的看法大为改观-----我以前是心里有偏见了。她们初看打扮时髦而又干练,说话快而利落,脑子清楚毫不拖泥带水,对价格非常敏感,你以为她们很势力很在乎金钱。是的,对普通人陌生人是的。可是交往久了,我觉得她们工作尽职尽责----加班从来都是自己要求的,自己的事自己做完;做事很有责任心----对公司的财物,以及用水用电完全像对自己家的一样;很重感情----我们公司有不只一个女孩为了男朋友、同学而付出了金钱,时间,甚至家庭的埋怨。也许,外人对他们的误解只是因为大家做事情的方法不同罢了,毕竟,人更重要的是心灵和思想。

   可是我的感情生活依旧空白。我觉得现在的我不可能再发展一段恋情---在我的心里小成一刻也不曾离开。每天我都会看小成给我的那封信,那信其实写得很长。看了之后我总觉得她离我不远,我的心里也觉得很温暖。小成,你的心灵和思维离了肉体的羁绊,应该飞的更快更远了吧。这段时间由于小成的离去,我每天努力的工作回家之后,会觉得失去了归宿感。有时候我会忽然想,我来这里干什么?哪里是我的归宿呢?我努力奋斗,努力挣钱,挣了很多钱又怎么样呢?

   这是我第一次考虑这个问题----金钱对我意味着什么。以前生存和事业的压力,以及一个接着一个的打击和磨砺让我始终无暇顾及这个具有终极意义的话题。是啊,虽然我现在还不是很有钱,但是我有钱了以后怎么办?以前我国传统的精神也只讲过:君子爱财,取之有道。可是如果取到了有怎么样呢?原谅我的陋学,我没有看到这方面的阐述。很多中国人有钱了以后,生活奢靡、大讲排场、意志低落、胡乱花钱,很多还丧失了生活的动力,多少人在贫*时坚持的修身养性,成仁取义,在富贵来临时烟消云散。更有很少的人捐钱给慈善事业和救助他人,我想这一切也和我们的传统文化有关。我坚决不要这样的生活。可是为什么西方人有那么多有钱人,给慈善事业捐钱呢?而且他们一些穷人也有给慈善事业捐钱的习惯呢?

   一个偶然的机会我看到了《圣经–马太福音》,里面的阐述让我如梦初醒。那里面说,虽然富人因为上帝给予的机会和能力获得了财富,但是那财富并不是富人的,只是上帝因为看到财富由于在富人手中增值而让那些富人代为保管的,一旦有需要,应该把财富还给所有人。这就是我所要寻找的原因。我于是如饥似渴地每天看《圣经》,那里面的文字让我的安静,安定,安心。在这里面,我找到了和我心灵合拍的仁爱心、慈悲心、谦卑心和使命心。

   我进一步了解到我以前毫无信仰,或者以自己为信仰时的无知、自以为是、狂妄自大和故步自封。朋友,也许你和我信仰不同,请不要在这里争执孰是孰非。也许只有每个人只有经历苦苦思索和重重磨砺,才能接近你所认为的真理。最终我在这里找到了归宿,也找到了问题的答案。

   我在徐家汇教堂受了洗,成为主的信徒。受洗之后,我每周都要去教堂坐坐。我知道,小成一定会成为天使,主一定也会指引我。我以前认为的爱是我前进的动力,这爱字,今天我才体会到更广泛更宏大的意义。它已经成为了我的使命。


   29,疑问

    2005年的1月,我在徐家汇附近,漕溪路旁的那块大空地上停好车出来的时候,忽然意外地发现了芸和她的男朋友----现在应该已经是老公了吧,因为他们手里还抱着一个2岁大小的孩子。他们显然也发现了我,但是显然双方都有点错谔。我先打招呼,笑着说,这是你们的孩子啊?真漂亮!我们之间的气氛一下融洽了。交谈中我得知,他们2001年底结婚,2002年底有了这个可爱的女儿。他们的生活不错,买车买房也是2004年的事。我衷心的祝福他们。

   他们问我的情况,我也告诉了他们,我也得到了他们的祝福。我们还约好下次一起吃饭。

   我曾经以为,如果我再见到芸,我绝对不会保持平静,甚至我不知道怎么见她。可是我做到了,我不仅做到了心情平静,还做到了如常交流,更做到了绝对真心地祝福他们,理解他们。经历了那么多,看到了那么多,失去了那么多,我也得到了那么多。穿破围墙,我的心灵获得了更大的空间和放飞的舞台。 

我公司的生意到了2004年的9月份已经能够保持每个月70万左右的营业额,12万左右的利润了。10,11,12三个月我们又在原来的基础上开拓了30家左右的零售店面,基本能够实现每个月15万左右的利润。到年底的时候,我手上的资金加上商铺出租收入,公司原有资金和盈利,已经达到了180万。我的一个专门做公司投资的朋友说,像我们这样的小公司,只要我能保持公司连续盈利36个月,那么公司的价值一般就是公司60个月的利润总和。他笑着说,算算你的公司也值四五百万了吧,如果你保持现在的盈利状况。

   我的心中不相信“保持现状”这句话,以前的经历屡屡说明这一点:没有人能够保持现状。

   只有改变现状,才能保持不败。可是我经过粗粗一算之后,心里产生了疑问。因为我要提升目前的经营水准,势必重新打造一个更大更快速的经营平台,管理要上新台阶,还要进行更严密更系统的市场推广计划---我叫它“重生”计划。这个计划我粗粗算了一下,要求我投入300万左右的资金。我陷入了思考:这样的计划风险是否太大?如果失败,我会失去现有的所有公司盈利和手上资金,还有我部分的不动产。那么我应该保持现状,这也没什么不好,这样总有其他竞争者先做,然后我再静观事变吗?如果我实施“重生”计划,完成后如果发挥100%的效果,我9~10个月可以收回成本,公司随后还有应该有更大的发展。如果发挥70%的效果,我15~18个月可以收回成本。如果发挥50%以下的效果,那就是失败。

   可是奋斗这种东西已经进入了我的血液,变成了我的基因。我实在不能忍受自己什么也不做而失去这个成为自己领域内前几位的机会。为主,为小成,为我,为我所有的朋友和家人,还有我的员工,我决定放手一博。我把买的商品房(现在已经涨价了,达到150万了)和汽车做了二次抵押,贷了120万资金,这样我手上的资金已经有300万了。

   2004年12月21日夜里11点,我终于完成了17万字的详细的“重生计划”的策划报告。我没有忘了这一天,我一定要在这一天完成这报告。

   半夜里我开车从主干道下来,到了以前我和小成三号店的旧址----她是在这里爱上我,我也是在这里爱上她的。这里一切已经今昔非比,再也见不到路边的临时房了,全部都是宽宽的马路和人行道,谁也不会再关心这里曾经发生的事情了。我停下车,下车来靠着车点燃一只烟。看着天边半满的月亮,我清清楚楚地看见了小成妍妍的笑脸。我也笑了,只是脸上已经流满了泪水。

   朋友们,我在上海的奋斗岁月-----结束了吗?不,我心里知道,一切才刚刚开始!


   30,经验(大结局)

   下面是我自己的感悟和我的经验,权做参考:

    1,人生就是投资和收益的人生。如果你有钱,就投入金钱;如果你没有金钱,而有经验和能力,就投入经验和能力;如果你既没有金钱,也没有经验和能力,但是你有热情、勤奋和努力,那就投入热情、勤奋和努力。如果你既没有金钱,也没有经验和能力,连热情、勤奋和努力也没有,那就别想这些了。

    2,比赚钱更重要的是找到你自己的赚钱动力;

    3,比金钱重要的是时间,比时间重要的是时机,比时机重要的是你要抓住时机的决心,动力和准备!

    4,别好高骛远,机会一般都在你看不起眼的角落里藏着;

    5,舍得投入;

    6,决定一下,行动要快;

    7,永远尽可能准备好资源,随时准备抓住机会,要快!

    8,待人以诚,对人以善。有时候,机会是别人给的;

    9,给别人的比别人期待的多一些(这是我抄李嘉诚的,我很喜欢);

    10,赚钱有个普遍的法则:多做,快做,动脑筋变着花样做,就是别跟着别人一样做。

    11,合理规划有钱以后的日子,会让你走的更远;

    12,有信仰,有原则,有爱心。    


再次声明,这篇文章转载自阿里巴巴论坛。感谢您看完,相信您像我一样学到了些什么,领悟了些什么。奋斗无止境。 

出处:PConline    作者:漩草    责任编辑:huangpeidan


  Photoshop是迄今为止世界上最畅销的图象编辑软件。它已成为许多涉及图像处理的行业的标准。并且是Acobe公司最大的收入来源。然而Photoshop的开始却是名不经传,如果不是Michigan大学一位研究生学生延迟毕业答辨,Photoshop或许根本就不可能被开发出来。


  1987年秋,Thomes Knoll,一名攻读博士学位的研究生,一直尝试编写一个程序,使得在黑白位图监视器上能够显示灰阶图像。他把该程序命名为Display。但是Knoll在家里用他的Mac Plus计算机编写这个编码纯粹是为了娱乐,与他的论题并没有直接的关系。他认为它并没有很大的价值,更没想过这个编码会是Photoshop的开始。



  他的程序引起了他哥哥John的注意。当时John正效劳于Iindustrial Light Magic(ILM)公司——一家影视特效制作公司。随着《星球大战》的诞生,Lucas向世人证明,真正的酷效,配以英雄人物,将创造出惊世巨片!当时John正在实验利用计算机创造特效,他让Thomas帮他编写一个程序处理数字图像,这正是Display的一个极佳起点,他们的合作也从此开始。

  John通过他父亲--Michigan大学的教授--购买了一台新的Macintosh II计算机。Thomas用它重新编写Display代码,使之支持彩色功能。随后,在John的力促下, Thomas开发了图像处理例程(即后来的滤镜插件),以及增加了读写各种文件格式的功能。其独创的创建软化边缘选区功能亦在此时得以实现,另外,还增加了如下功能:色阶,色彩平衡,色相及饱和度等。

  1988年夏天,John决定实现这个程序的商业价值。尽管将很艰难,但天性乐观的他认为它值得努力。当时,在MacWeek上刊登的一种图象应用软件PhotoMac引起了John的关注。他到SIGGRAPH(计算机绘图专业组)大会去调查这种新的软件。最后他告诉Thomas他们无需担心,事实上PhotoMac缺乏他们的程序的很多重要功能。




  Thomas好几次试图更改这个软件的名称,但每次都没有成功。有趣的是,正所谓踏破铁蹄无觅处,得来全不费工夫,在一次偶然的演示时,他采用了一个人的建议,把这个软件命名为Photoshop。从此,Photoshop正式成为了这个软件的名称,直至今日。

  与此同时,John四处奔走,寻找公司投资Photoshop。SuperMac,Alcus,Adobe都因为种种原因没有成功。他继续在硅谷寻找投资者,并鼓励Thomas继续编写新的功能。他甚至编写了一本简单的手册介绍这个程序。最后,一家扫描仪公司采用了这个软件。大约200份0.87版本的Photoshop拷贝随着扫描仪捆绑出售。Photoshop首次发行即是与Banreyscan XP扫描仪捆绑发行的。





  后来,John重返Adobe进行另一次演示。Russell Brown,Adobe的艺术总监,完全被这个程序所打动。Adobe以极大的热情果断地买下了Photoshop的发行权。1988年11月,Knoll兄弟与Fred Mitchell,Adobe的首脑,口头议定合同,并于次年4月完成真正的法律合同。合同上的关键词是“license to distribute(授权销售)”Adobe公司当时并没有完全买断这个程序,直到若干年后Photoshop取得了巨大的成功。签订了合同后,Thomas和John两兄弟开始研发新的版本以发布销售。而Adobe公司则决定保留Photoshop这个名字。

  Thomas在Ann Harbor编写所有的程序,而John在California编写插件。Adobe的一些人认为John的插件过于花俏,不适合于严肃的应用程序。他们的观点是他们的产品仅作为一种润饰的工具,而非为了特殊作用。所以John只能偷偷地把这些插件编写进去。正是这些原来为很多所不齿的插件,却成为日后Photoshop成功的一大因素。时至今日,插件已经成为Photoshop不可或缺的重要功能。1989至1990年,Russell Brown和John,Tussell和Fred提供建议,Thomas编写代码,增加软件的新特性。

  1990年2月,Photoshop1.0版本发行。它优秀的编码和简单便捷的使用给了它的竞争者ColorSrudio狠狠的打击。它给计算机图像处理行业市场带来巨大的冲击。除了其他软件没有的特点外,它还获得了天时。当时正值计算机桌面革命炒得火热,桌面的发展更为它创造了有利条件。此外,Adobe还有一个制胜的秘密武器-RussellBrown。他善于让人觉得这个软件容易使用且有趣。在一次演示会上,他幽默的演示突出了Photoshop的优点也使得参展的人把Photoshop竟相宣传出去。




 



  而Photoshop 1.0显然仍需改进。当时,Photoshop的优势是容易使用,虽然Fractal Design开发的ColorSrudio具有一些它所没有的优点,但总体而言,ColorStudio却存在更多的缺陷。
Letraset把ClolorStudio定位于专门人士使用的专门工具。而Adobe把Photoshop定位于所以电脑拥有者可以使用的工具。这两个冤爱死对头竞争非常激烈,当时MacWorld的一篇文摘体现了这两个公司的交锋。John和效力于ColorSrudio的Macr Zimmer分别使用他们自己的软件对图象进行润饰及合成。结果最后Photoshop是赢家。

  当时Thomas是编写这个软件的唯一支柱。为了扩充工程师队伍,公司聘请了Mark Hamburg。Mark曾从事于Ashton Tate。路径即是他提出加入到Photoshop里的。路径也成为了Photoshop2.0版的新特性。2.0版最重要新功能包括支持栅格化Adobe的矢量编辑软件Illustrator文件,支持CMYK,Duotones以及新增钢笔工具。此外,Photoshop的最小分配内存也由原来的2MB增加到4MB,这个小小的改动无疑对程序的稳定性及运作性能的提高起了非常大的作用。Mark声称他对这个软件的第一个贡献是建议最低内存需求从2MB增加到4MB,可见其作用绝非由2到4那么简单。




  Sreven Guttman当时担任首任产品经理,给Beta版起代号即是从那时开始。Photoshop 2.0的代号是Fast Eddy。2.0正式版于1991年2月发行。从此,Adobe成为行业标准。2.0的发行引起了印刷业的重视,并引发桌面印刷革命。

  Adobe公司开始设立销售部门,并聘请了更多的软件工程师,包括Kevin Johnston。此时Adobe公司决定开发一个Windows视窗版本。Guttman把软件开发分成两个小组,由JeffParker领导的Mac小组以及由Bryan Lamkin领导的Windows小组。这次开发进展很慢,因为他们必须重新编写Thomas最初的编码。尤其是Windows版本,似乎是一个完全分离的程序。Mac版本开发代号是Merlin,Windows版本则是Brimstone。Adobe决定把下一个版本标注为Photoshop2.5,至今无人知道为什么不标注为3.0。通常标注为.5都不会好销,因为人们觉得小数点后的数字通常留给修改升级。2.5版本增加了一些新的显著特征,调色板和16-bit文档支持。尽管这个版本因为是Windows版本的第一版而备受瞩目,但是对于Windows系统,它有一个强大的对手,Aldus公司的PhotoStyler。虽然Windows的使用者可以使用Photoshop,但是它并不包括那些新特点。同时,内存处理的一些错误很快便从市场反馈回来。当这些内存错误bug被查出并改进后,原来的版本升级为2.5.1。




  此时Photoshop在Mac版本的主要竞争对手仍是Fractal Design的ColorStudio,而Windows上面则是上文提到的Aldus的PhotoStyler。Photoshop从一开始就遥遥领先于ColorStudio,而Windows版本则经过一段时间改进后才赶上对手。


  下一个版本3.0的研发在2.5还没完成便已开始,代号为Tiger Mountain。在这一版中,将着力加入图层这一新特性。Thomas主要即致力于图层的研发,同时与Hamburg和Johnston一起研发其他的新特性功能。Stern优化Power Mac版本Photoshop,而Seetha Narayanan则使Windows版本能与Mac版本同步。
当时研究Layers的还有LivePicture,是Photoshop劲敌。Live Picture的Layer具有将单独分离的元素多重地堆叠起来。当时也有谣言说Photoshop的工程师抄袭了LivePicture的Layers特征,事实上,早在Thomas还未听说过LivePicture的时候,他便已开始研究Layer这一概念。对他来说,这个概念仅是为了方便在编辑图片的时候可以把物体单独分开。Photoshop3.0的Mac和Windows版本分别在在1994年9月底和11月发行。




  3.0版从研发到发行都充满了磨难。在它未发行之前,Jeff Pakler去度假了,留下一个没有管理人员的摊子。JohnLeddy必须一步一步地接替这个位置。在Beta检测过程中,又出现了Q&A (质量评估)麻烦。许多3.0版本中的特征几乎不能通过甚至完全不能通过。当时有谣言说Browm捏造了一些特征只是为了引起市场的轰动效益,缺乏证明使得Adobe的各个部门在信息业中几乎瘫痪。在版本3.0发行之后,程序出现了更大的故障。不知何故,beta终止编码没有响应。Adobe收回了出售的3.0版本。3.0.1版本迅速发行。不幸的是那些试用者并没有归还软件,这个程序在1995年12月1日终止了运行。许多用户都意识到了3.0版的问题,这在用户中引起恐慌。Adobe尽最大的努力去替换3.0版的CD。通过网上服务, 3.0.1版更新3.0版。同样不幸的是,95年2月1日,日本版本同样出现beta终止警报。Adobe试图用版本更新的3.0.3版本解决这个问题,但这仍造成了很糟糕的影响。许多工程师离开了Adobe。这点小障碍并没有减小3.0版本使用者的热情,特别是对它的Layer(图层)功能。

  不管怎么说,Photoshop3.0(包括它5个升级的版本)仍是一个成功的产品。许多人无论是否Adobe的工作人员都在想没有什么能超越这个版本。虽然那时候有相当大的一支设计队伍(包括苹果公司的Sean Parent,来自IBM公司的Marc Pawliger),但是继续开发Photoshop新版本的决心动摇了。工程师们开始把注意力分散到其他的项目。Photoshop的发展似乎陷入泥潭,直至Lamkin加入。他聘请了一个界面设计师重做Photoshop的界面,目的是使Adobe所有的产品都具有相似的外观和操作方法。并且他说服Hamburg重返Photoshop设计小组。此举给Photoshop的用户带来了新的惊喜。这即是4.0版本的开端,代号为Big Electric Cat。

  当第一张beta磁盘出现,引起了测试者们的骚动。为什么Photoshop有了这么多的改变。一些使用者提出抗议。测试完成后,测试者们都已经适应了这种改变,但是一些媒体包括一些网上服务CompuServe和AOL都充斥着一些使用者的怨言。1996年11月Photoshop4.0发行,很多用户认为Photoshop被破坏了。最后,当他们了解了这些变化,并且明白了Photoshop改进的良苦用心,这些争论才烟消云散,新界面逐渐被大家所接受。
Photoshop 4.0的成功给Adobe带来了很大的商业利益,也为当初那些大胆改革的工程师们作了最有力的辩护。此时,Adobe意识到Photoshop的发展前景,与Knoll兄弟重新签订合同,买断了Photoshop的所有权。




photoshop各版本的tools面板

  在4.0版仍未发行,5.0版已提上日程。在4.0版发行期间,5.0版的一些新功能已开始着手研究,有些已经成功地编入程序。1997年9月,Herasimchuk以及另一位界面设计师Katjatimmi和一些alpha测试者商讨5.0版的新功能。最后决定增加一个重要的History Palette(历史面板)功能,这是一个实现多重撤消操作的完美方法,其中的非线性历史操作可以说令人耳目一新,毫无疑问,这也一个重大的升级。另外,色彩管理功能也是一个重大的新增功能,尽管在当时引起了一些争议,但后来被证明这亦是Photoshop历史上的一个重大改进。“图层样式”也是在此版本中加入的新功能。1998年5月Photoshop 5.5正式发行。时隔一年,Photoshop 5.5发布,此次升级,就Photoshop本身而言,并没有什么特别升级,主要是增加了支持Web功能,以及将Image Ready 2.0捆绑到Photoshop中一起销售,以此填补Photoshop在web功能上欠缺。Photoshop 5.5一经推出即取得了巨大成功。




  2000年9月,Photoshop 6.0发布,经过改进,Photoshop与其他Adobe工具交换更为流畅,此外Photoshop 6.0引进了“形状(Shape)”这一新特性。但真正的重大改进是在2002年3月的7.0版。在数码相机流行起来之前,Photoshop处理的图片绝大部分还是来自于扫描, Photoshop大部分功能基本与数码相机没有什么关系。到20世纪90年代末,数码相机大行其道,Photoshop 7.0版适时的增加了Healing Brush等图片修改工具,还有一些基本的数码相机功能如EXIF数据,文件浏览器等。Photoshop在享受巨大商业成功的同时,也开始感受到来自同行的巨大威胁,特别是专门处理数码相机原始文件的软件,包括各厂家提供的软件和其他竞争对手如Phase One(Capture One)。已经退为二线的Thomas Knoll亲自负责带领一个小组开发了PS RAW(7.0)插件。





  2003年9月,Adobe再次给Photoshop用户带来惊喜,新版本Photoshop不再延续原来的叫法称之为Photoshop 8.0,而改称为Photoshop Creative Suite,即Photoshop CS,它与Adobe其他的系列产品组合成一个创作套装软件,与兄弟产品的融汇更加协调通畅。CS版本把原来的原始文件插件进行改进并成为CS的一部分,更多新功能为数码相机而开发,如智能调节不同地区亮度,镜头崎变修正,镜头模糊滤镜等。




photoshop各版本的tools面板


  Photoshop之所以取得成功,与其准确的定位及其适时的出现关系紧密。photoshop正遇上了桌面印刷革命这个大好时机,其成功可谓时事造就英雄。Adobe公司对市场的敏锐洞查以及及时的调整策略使之走在了最前端。最初的Photoshop只支持苹果电脑的麦金塔平台,并不支持Windows。但看到Windows在PC机上的出色表现,Adobe公司也紧跟发展潮流,推出Windows版本(包括Windows95和Windows NT);随着全球电脑的普及,Photoshop逐渐推出多国语言的版本。例如,看到中国无限广阔的市场,Adobe公司推出了Photoshop 5.02中文版,并且开通了中文站点,成立了Adobe中国公司。而photoshop一开始的良好市场定位,亦为其成为行业霸主奠定了良好的基础。

出处:PConline   作者:PhotoshopNews/原著 Tommy/编译   责任编辑:xietaoming


  PhotoshopNews 公布了由 Jeff Schewe 收集的,Photoshop 历年以来——从 Display 0.07 (Photoshop 的前身) 到目前为止最新版 Photoshop CS2 ——各个版本的启动画面及彩蛋。而我们 PConline软件资讯栏目 曾经在《傲视群雄——平面设计霸主Photoshop辉煌十三载》一文章中介绍过 Photoshop 带有传奇色彩的发展成长故事。现在就让我们通过这些图片一起再来回顾一下 Photoshop 的演变历史。


1、Display 0.07 (即 Photoshop 的前身)



Display 0.07 启动画面


2、Photoshop 0.87 启动画面 (Barneyscan XP)



Photoshop 0.87 启动画面



Photoshop 0.87 彩蛋


  译者说明:原文是“Alt Screen”,即“两者间进行切换的屏幕”。这里我们统一称之为“彩蛋”(Easter Egg)。


  提示:如何显示彩蛋?


  对于 Windows 系统:点击“帮助”菜单,按住 Ctrl 键不放,再从弹出下拉菜单中点击“关于Photoshop”命令即可。


  对于 Mac OS 系统:点击“帮助”菜单,按住 Cmd 键,再从弹出下拉菜单中点击“关于Photoshop”命令即可。


3、Photoshop 1.07 零售版启动画面,1.0 版发行日期:1990年2月



Photoshop 1.07 零售版启动画面



Photoshop 1.07 彩蛋


4、Photoshop 2.0.1 零售版启动画面。2.0 版发行日期:1991年6月,2.01 版发行日期:1991年12月。



Photoshop 2.0.1 零售版启动画面



Photoshop 2.0.1 彩蛋


5、Photoshop 2.5 零售版启动画面。2.5 版发行日期:1993年2月,2.5.1 升级版日期:1993年7月。



Photoshop 2.5 零售版启动画面



Photoshop 2.5 彩蛋


6、Photoshop 3.0 零售版启动画面。 3.0 版发行日期:1994年9月,3.05 升级版发布日期:1995年6月。



Photoshop 3.0 零售版启动画面



Photoshop 3.0 彩蛋 (by Mark Hamburg)


7、Photoshop 4.0 零售版启动画面。 4.0 版发行日期:1996年11月,4.01 升级版发布日期:1997年4月。



Photoshop 4.0 零售版启动画面



Photoshop 4.0 彩蛋 (by Joseph Kelter)


8、Photoshop 5.0 零售版启动画面。 5.0 版发行日期:1998年5月,5.01 升级版发布日期:1998年6月。



Photoshop 5.0 零售版启动画面



Photoshop 5.0 彩蛋 (by Jeff Schewe)


9、Photoshop 5.5 零售版启动画面。 5.5 版发行日期:1999年7月。



Photoshop 5.5 零售版启动画面



Photoshop 5.5 彩蛋 (by Jeff Schewe)


10、Photoshop 6.0 零售版启动画面。 6.0 版发行日期:2000年10月,6.01 升级版发布日期:2001年2月。



Photoshop 6.0 零售版启动画面



Photoshop 6.0 彩蛋 (by Mike ‘The Cigarette Smoking Man’ Shaw)


11、Photoshop 7.0 零售版启动画面。 7.0 版发行日期:2002年4月,7.01 升级版发布日期:2002年7月。



Photoshop 7.0 零售版启动画面



Photoshop 7.0 彩蛋 (by Mike ‘Tabletmeister’ Shaw)


12、Photoshop CS (8.0) 零售版启动画面。 CS (8.0) 版发行日期:2003年10月。




Photoshop CS (8.0) 零售版启动画面




Photoshop CS (8.0) 彩蛋 (by Jeff Tranberry)


13、Photoshop CS2 (9.0) 零售版启动画面。 CS2 (9.0) 版发行日期:2005年4月下旬(原定5月,但Photoshop CS2 提早出货)。




Photoshop CS2 (9.0) 零售版启动画面




Photoshop CS2 (9.0) 彩蛋 (by Chris Smith)

Linux 打包解包压缩解压缩命令

tar
解包:tar xvf FileName.tar
打包:tar cvf FileName.tar DirName
(注:tar是打包,不是压缩!)
---------------------------------------------
.gz
解压1:gunzip FileName.gz
解压2:gzip -d FileName.gz
压缩: gzip FileName
.tar.gz
解压:tar zxvf FileName.tar.gz
压缩:tar zcvf FileName.tar.gz DirName
---------------------------------------------
.bz2
解压1:bzip2 -d FileName.bz2
解压2:bunzip2 FileName.bz2
压缩: bzip2 -z FileName
.tar.bz2
解压:tar jxvf FileName.tar.bz2
压缩:tar jcvf FileName.tar.bz2 DirName
---------------------------------------------
.bz
解压1:bzip2 -d FileName.bz
解压2:bunzip2 FileName.bz
压缩: 未知
.tar.bz
解压:tar jxvf FileName.tar.bz
压缩:未知
---------------------------------------------
.Z
解压:uncompress FileName.Z
压缩:compress FileName
.tar.Z
解压:tar Zxvf FileName.tar.Z
压缩:tar Zcvf FileName.tar.Z DirName
---------------------------------------------
.tgz
解压:tar zxvf FileName.tgz
压缩:未知
.tar.tgz
解压:tar zxvf FileName.tar.tgz
压缩:tar zcvf FileName.tar.tgz FileName
---------------------------------------------
.zip
解压:unzip FileName.zip
压缩:zip FileName.zip DirName
---------------------------------------------
.rar
解压:rar a FileName.rar
压缩:r ar e FileName.rar


TAR
命令名
tar - tar 档案文件管理程序的 GNU 版本。下面将逐个介绍其含义
总览
tar [ - ] A --catenate --concatenate | c --create | d --diff --compare | r --append | t --list | u --update | x -extract --get [ --atime-preserve ] [ -b, --block-size N ] [ -B, --read-full-blocks ] [ -C, --directory DIR ] [ --checkpoint ]
[ -f, --file [HOSTNAME:]F ] [ --force-local ]
[ -F, --info-script F --new-volume-script F ] [ -G, --incremental ] [ -g, --listed-incremental F ] [ -h, --dereference ] [ -i, --ignore-zeros ] [ -I, --bzip ] [ --ignore-failed-read ] [ -k, --keep-old-files ] [ -K, --starting-file F ] [ -l, --one-file-system ] [ -L, --tape-length N ] [ -m, --modification-time ] [ -M, --multi-volume ] [ -N, --after-date DATE, --newer DATE ] [ -o, --old-archive, --portability ] [ -O, --to-stdout ] [ -p, --same-permissions, --preserve-permissions ] [ -P, --absolute-paths ] [ --preserve ]
[ -R, --record-number ] [ --remove-files ] [ -s, --same-order, --preserve-order ] [ --same-owner ] [ -S, --sparse ] [ -T, --files-from F ] [ --null ]
[ --totals ]
[ -v, --verbose ] [ -V, --label NAME ] [ --version ]
[ -w, --interactive, --confirmation ] [ -W, --verify ]
[ --exclude FILE ] [ -X, --exclude-from FILE ] [ -Z, --compress, --uncompress ] [ -z, --gzip, --ungzip ]
[ --use-compress-program PROG ] [ --block-compress ] [ -[0-7][lmh] ]


filename1 [ filename2, ... filenameN ]
directory1 [ directory2, ...directoryN ]


 



描述
tar 程序用于储存或展开 tar 存档文件。存档文件可放在磁盘中 ,也可以存为普通文件。 tar是需要参数的,可选的参数是A、c、d、r、t、u、x,您在使用tar时必须首先为 tar 指定至少一个参数;然后,您必须指定要处理的文件或目录。如果指定一个目录则该目录下的所有子目录都将被加入存档。
应用举例:


1)展开 abc.tar.gz 使用命令: tar xvzf abc.tar.gz 展开 abc.tar 使用命令: tar xvf abc.tar


2)将当前目录下的 man 目录及其子目录存成存档 man.tar tar cf man.tar ./man
参数说明
运行tar时必须要有下列参数中的至少一个才可运行


-A, --catenate, --concatenate
将一存档与已有的存档合并
-c, --create
建立新的存档
-d, --diff, --compare
比较存档与当前文件的不同之处
--delete
从存档中删除
-r, --append
附加到存档结尾
-t, --list
列出存档中文件的目录
-u, --update
仅将较新的文件附加到存档中
-x, --extract, --get
从存档展开文件



其他参数


--atime-preserve
不改变转储文件的存取时间


-b, --block-size N
指定块大小为 Nx512 字节(缺省时 N=20)


-B, --read-full-blocks
读取时重组块(???!!!)


-C, --directory DIR


转到指定的目录


--checkpoint
读取存档时显示目录名


-f, --file [HOSTNAME:]F
指定存档或设备 (缺省为 /dev/rmt0)


--force-local
强制使用本地存档,即使存在克隆


-F, --info-script F --new-volume-script F
在每个磁盘结尾使用脚本 F (隐含 -M)


-G, --incremental
建立老 GNU 格式的备份


-g, --listed-incremental F
建立新 GNU 格式的备份


-h, --dereference
不转储动态链接,转储动态链接指向的文件。


-i, --ignore-zeros
忽略存档中的 0 字节块(通常意味着文件结束)


--ignore-failed-read
在不可读文件中作 0 标记后再退出???


-k, --keep-old-files
保存现有文件;从存档中展开时不进行覆盖


-K, --starting-file F
从存档文件 F 开始


-l, --one-file-system
在本地文件系统中创建存档


-L, --tape-length N
在写入 N*1024 个字节后暂停,等待更换磁盘


-m, --modification-time
当从一个档案中恢复文件时,不使用新的时间标签


-M, --multi-volume
建立多卷存档,以便在几个磁盘中存放


-N, --after-date DATE, --newer DATE
仅存储时间较新的文件


-o, --old-archive, --portability
以 V7 格式存档,不用 ANSI 格式


-O, --to-stdout
将文件展开到标准输出


-p, --same-permissions, --preserve-permissions
展开所有保护信息


-P, --absolute-paths
不要从文件名中去除 '/'


--preserve
like -p -s
与 -p -s 相似


-R, --record-number
显示信息时同时显示存档中的记录数


--remove-files
建立存档后删除源文件


-s, --same-order, --preserve-order
???
--same-owner
展开以后使所有文件属于同一所有者


-S, --sparse
高效处理


-T, --files-from F
从文件中得到要展开或要创建的文件名


--null
读取空结束的文件名,使 -C 失效


--totals
显示用 --create 参数写入的总字节数


-v, --verbose
详细显示处理的文件


-V, --label NAME
为存档指定卷标


--version
显示 tar 程序的版本号


-w, --interactive, --confirmation
每个操作都要求确认


-W, --verify
写入存档后进行校验


--exclude FILE
不把指定文件包含在内


-X, --exclude-from FILE
从指定文件中读入不想包含的文件的列表


-y, --bzip2, --bunzip2
用 bzip2 对存档压缩或解压


-Z, --compress, --uncompress
用 compress 对存档压缩或解压


-z, --gzip, --ungzip
用 gzip 对存档压缩或解压


--use-compress-program PROG
用 PROG 对存档压缩或解压 ( PROG 需能接受 -d 参数)


--block-compress
为便于磁盘存储,按块记录存档


-[0-7][lmh]
指定驱动器和密度[高中低]

    一位美国强人的简历 



  1809.2.12,生日 
  
 
  1818(9),母亲去世。
 
  
 
  1831(22),经商失败。
 
  
 
  1832(23),竞选州议员落选。
 
  
 
  同年 (23),工作丢了。想就读法学院,但未获入学资格。
 
  
 
  1833(24),向朋友借钱经商。
 
  
 
  同年年底(24),再次破产。接下来,他花了16年时间才把债还清。
 
  
 
  1834(25),再次竞选州议员,这次赢了。
 

  1835(26),订婚后即将结婚时,未婚妻死了。
 
  
 
  1836(27),精神完全崩溃,卧病在床六个月。
 
  
 
  1838(29),争取成为州议员的发言人——没有成功。
 
  
 
  1840(31),争取成为选举人——落选了。
 
  
 
  1843(34),参加国会大选——又落选了。
 
  
 
  1846(37),再次参加国会大选——这回当选了。前往华盛顿特区,表现可圈可点。
 
  
 
  1848(39),寻求国会议员连任,失败。
 
  
 
  1849(40),想在自己州内担任土地局长的工作,遭到拒绝。
 
  
 
  1854(45),竞选美国参议员,落选。
 
  
 
  1856(47),在共和党内争取副总统的提名——得票不足100张。
 
 
 
  1860(51),当选美国总统。成为美国历史上最伟大的总统之一。
 

  生下来就一无所有的林肯,终其一生都在面对挫败。他曾经绝望至极,但从没有放弃人生这场跳高比赛  

千年悬空寺的不倒之谜



悬空寺的木头用桐油泡过,这样使它能够1000多年以来仍然坚实地插在岩石上



当时工人们首先要把横梁布置完成



然后再在山脚下,利用这些木材,制造出来每一个建筑上使用的木质构件



当把所有的构件都造完之后,把它们搬运到山顶上



到达山顶之后,再用绳索把工人和这些部件都放到山腰



然后工人再把这些部件拼成单独的建筑



当所有个体的建筑都完成之后呢,这个工作还没有结束



还要再铺上栈道,把单个的建筑连接成整体,这样便成了悬空寺



当年的工匠仅凭一些简单的铁制工具,就足以开凿出用于放置横梁的27个石孔



如今当年古栈道的横梁已不复存在,但这些石孔打凿的痕迹却还清晰可见


    补充介绍:


山西恒山悬空寺位于山西浑源县,距大同市65公里,全国重点文物保持单位,是国内仅存的佛、道、儒三教合一的独特寺庙。


悬空寺始建于1400多年前的北魏王朝后期,历代都对悬空寺作过修缮,北魏王朝将道家的道坛从平城,今大同南移到此,古代工匠根据道家“不闻鸡鸣犬吠之声”的要求建设了悬空寺。


悬空寺距地面高约50米,悬空寺发展了我国的建筑传统和建筑风格,其建筑特色可以概括为“奇、悬、巧”三个字。  


值得称“”的是,建寺设计与选址,悬空寺处于深山峡谷的一个小盆地内全身悬挂于石崖中间,石崖顶峰突出部分好像一把伞,使古寺免受雨水冲刷。山下的洪水泛滥时,也免于被淹。四周的大山也减少了阳光的照射时间。优越的地理位置是悬空寺能完好保存的重要原因之一。


”是悬空寺的另一特色,全寺共有殿阁40间,表面看上去支撑它们的是十几根碗口粗的木柱,其实有的木柱根本不受力,所以有人用“悬空寺,半天高,三根马尾空中吊”来形容县空寺。而真正的重心撑在坚硬岩石里,利用力学原理半插飞梁为基。


悬空寺的“”体现在建寺时因地制宜,充分利用峭壁的自然状态布置和建造寺庙各部分建筑,将一般寺庙平面建筑的布局、形制等建造在立体的空间中,山门、钟鼓楼、大殿、配殿等都有,设计非常精巧。寺内有佛像八十多尊。


唐开元二十三年(735年),李白游览悬空寺后,在石崖上书写了“壮观”二字,明代大旅行家徐霞客称悬空寺为“天下巨观”。

一、查看数据库运行模式  
可以用超级用户(INTERNAL)在SQLPLUS中使用命令ARCHIVE LOG LIST查看  
SQL> archive log list  
Database log mode       No Archive Mode  
Automatic archival      Disabled  
Archive destination      /export/home/oracle/product/8.1.7/dbs/arch  
Oldest online log sequence   28613  
Current log sequence     28615  
或者用:  
SQL> SELECT NAME,LOG_MODE FROM V$DATABASE;  
  
NAME    LOG_MODE  
--------  ------------  
BIGSUN   NOARCHIVELOG  
如看到如上情况,则证明是非归档(NOARCHIVELOG)模式。  
  
二、关闭数据库  
通知相关人员后,发布如下命令关闭数据库:  
SQL> shutdown immediate  
  
三、设置相应的初始化参数  
参数文件一般存放在$ORACLE_HOME/dbs目录下,格式为:initSID.ora,其中SID为数据库名。可以使用VI命令进行编辑。  
1、设置归档路径  
a)LOG_ARCHIVE_DEST和LOG_ARCHIVE_DUPLEX_DEST参数  
这两个参数指明了归档日志存放的两个路径,如果只设置第一个,则归档日志只存放到一个路径。  
例:  
log_archive_dest=/disk1/archive  
log_archive_duplex_dest=/disk2/archive  
  
b)LOG_ARCHIVE_DEST_n参数  
其中n为1-5的整数,必需从低到高设置(注:9i 中已经调整为 10 个),下面举例说明:  
log_archive_dest_1="LOCATION=/archive MANDATORY REOPEN"  
log_archive_dest_2="SERVICE=standby_db1 MANDATORY REOPEN=600"  
log_archive_dest_3="LOCATION=/archive2 OPTIONAL"  
  
LOCATION关键字说明是本机的一个目录,而SERVICE关键字说明是已经在Net8中进行了配置的其他数据库主机的别名。  
  
MANDATORY关键字说明联机日志文件必须要成功归档到这个目录后才能被覆写(联机日志文件是重复使用的文件)。缺省为可选(OPTIONAL),即即使归档不成功也可以覆写。在设置时应该至少有一个本地(LOCATION)强制(MANDATORY)归档目录。  
  
REOPEN关键字说明如果归档不成功时系统要重新尝试归档,缺省每300秒尝试一次直到成功。可以通过=n来指定尝试的时间间隔,如log_archive_dest_2中的时间间隔为600秒,而log_archive_dest_1中的时间间隔为300秒。  
  
a)和b)两种方式是排斥的,即只能设置其中的一种,a)和b)的不同之处在于:  
a)最多只能设置2个归档路径,而b)最多可设置5个。  
a)中只能指定本地目录,b)中可指定远程服务目录。  
如果使用a)方式,则log_archive_dest是强制(MANDATORY)归档目录,而log_archive_duplex_dest为可选(OPTIONAL)目录。  
a)中不能使用REOPEN关键字。  
所以推荐使用b)方式。  
  
2、设置归档日志文件名格式  
例:  
log_archive_format=arch%S.arc  
其中%S为日志序列号,则生成的归档日志文件名为arch001.arc、arch002.arc等。  
  
3、设置最小归档成功数  
例:  
log_archive_min_succeed_dest=2  
此参数说明至少有2个归档路径归档成功后才能覆写联机日志文件,此参数和归档路径参数联用。  
如归档路径参数设置为:  
log_archive_dest_1="LOCATION=/archive MANDATORY REOPEN"  
log_archive_dest_2="SERVICE=standby_db1 OPTIONAL"  
log_archive_dest_3="LOCATION=/archive2 OPTIONAL"  
则log_archive_dest_1必须归档成功(MANDATORY),log_archive_dest_2、 log_archive_dest_3中必须有一个归档成功(log_archive_min_succeed_dest=2)后才能覆写联机日志文件。同样,如果log_archive_dest_n中的MANDATORY关键字个数大于log_archive_min_succeed_dest,则 log_archive_min_succeed_dest的设置不起作用。  
  
4、控制归档路径是否可用  
例:  
log_archive_dest_state_1=DEFER  
log_archive_dest_state_2=ENABLE  
此参数和log_archive_dest_n参数配对使用,缺省值为ENABLE,如果想停止使用一个归档目录,只需将其对应的log_archive_dest_state_n参数值设置为DEFER。  
  
5、实现自动归档(可选)  
log_archive_start=true  
log_archive_max_processes=2  
在ORACLE中,自动归档的进程名为ARC0、ARC1等,log_archive_start参数说明是否采用自动归档,值为true表示采用,为 false时必须采用命令来手工备份。log_archive_max_processes表示在log_archive_start为true时运行几个归档进程来完成归档工作,取值范围为1-10。  
  
四、更改数据库运行模式  
在SQLPLUS中执行命令:  
SQL> startup mount  
SQL> alter database archivelog;  
SQL> alter database open;  
  
至此,模式转化工作已经大功告成。但需要注意的是,由于更改了数据库结构,如有数据库安全方面的需要,必须关闭数据库并完全备份。

http://www.matrix.org.cn/thread.shtml?topicId=25412&forumId=36

Windows 2000 telnet服务简明教程


这篇文章主要是讲解了关于2K的NTLM验证,大家可以看一看,增加一下大家的知识积累。


  Telnet是一种字符模式的终端服务,它可以使用户坐在已上网的电脑键盘前通过网络进入远程主机,然后对远程主机进行操作。这种连通可以发生在局域网里面,也可以通过互联网进行。被连通的计算机称为Telnet Server,你自己在使用的机器称之为客户机或者终端。win2000系统中有一个称为终端服务的组件,那是一个图形化的终端服务,功能更加强大,但是对系统的要求也高一些。有时我们只是想通过网络来进行一些简单的远程管理,那么使用Telnet仍然是一个不错的选择。


  Win2000中的Telnet服务默认是不启动的,我们可以通过多种方式来启动它。首先是手工启动的方法:


  1、在命令提示符下键入 net start telnet。


  2、单击开始,指向程序,指向管理工具,然后单击 Telnet 服务器管理。在命令提示符下键入 4 启动 Telnet 服务。


  3、单击开始,指向程序,指向管理工具,单击服务,右键单击 Telnet 服务,然后单击启动。


如果希望win2000启动时自动启动Telnet,也可以这样做。打开"计算机管理"工具,单击服务,找到Telnet 服务,右键单击,然后单击属性。在启动类型框中单击自动,确定。


  下面我们再来看看如何使用Telnet服务,最简单的方法就是直接在命令行模式下输入:
  telnet computername(or IP) Portnumber


  Telnet服务默认使用23号端口,如果服务器端没有修改的话,客户机连结时也可以不输入Portnumber。如果客户机使用win98操作系统,那么可以使用一个专门的Telnet客户端,在开始菜单运行中输入Telnet就可以启动它了。


  上面是一个基本的使用方法,接下来我们再看看一些使用过程中的常见问题。首先一个是关于客户端登录验证的问题。我们在客户端上连结Telnet服务器时,经常会看到这样的错误信息:
  Server allows NTLM authentication only
  Server has closed connection


这是因为默认情况下,win2000的Telnet服务使用NTLM的验证方式,这种验证方式避免了明文密码的传送,提高了安全性。但是win98、nt4.0等系统的Telnet客户端客户端不支持这种方式,这样就带来了不便。有时我们希望在登录Telnet时,提示我们输入用户名和密码,那我们可以这样设置:


  开始菜单|程序|管理工具|Telnet服务器管理(或者运行tlntadmn),选择3 显示/更改注册表设置,然后选择7 NTLM,进行修改。可接受的值为0-2,2是NTLM only,0是NTLM not available,1是二者都支持,默认值是2。修改后需要重新启动Telnet服务。


  为了提高安全性,有时我们也在服务器端修改服务的默认端口号,这样客户机连结时就需要提供端口号信息了。修改的方法是:


  开始菜单|程序|管理工具|Telnet服务器管理,选择3 显示/更改注册表设置,然后选择8 Telnetport,输入你要设置的端口号。注意输入的端口号不要和你的服务器上正在使用的端口冲突。修改后同样需要重新启动Telnet服务。

使用 LogMiner

1.创建DBMS_LOGMNR
SQL>@$ORACLE_HOME/rdbms/admin/dbmslm.sql

2.
创建相关数据字典
SQL>@$ORACLE_HOME/rdbms/admin/dbmslmd.sql

3.
修改初始化参数UTL_FILE_DIR,指定分析数据的存放处
SQL>alter system set UTL_FILE_DIR='/opt/oracle/logminer' scope=spfile;

4.
重启数据库
SQL>shutdown immediate
SQL>startup

5.
创建数据字典文件


SQL>execute dbms_logmnr_d.build(dictionary_filename =>'sqltrace.ora',dictionary


_location =>'/opt/oracle/logminer/log');

6.
建立日志分析表


SQL> execute dbms_logmnr.add_logfile(options =>dbms_logmnr.new,logfilename =>'/opt/oracle/ora92/rdbms/ARC00009.001');



7.添加用于分析的日志文件


SQL> execute dbms_logmnr.add_logfile(options =>dbms_logmnr.addfile,logfilename=>'/opt/oracle/ora92/rdbms/ARC00010.001');


SQL> execute dbms_logmnr.add_logfile(options =>dbms_logmnr.addfile,logfilename =>/opt/oracle/ora92/rdbms/ARC00011.001');


删除


SQL> execute dbms_logmnr.add_logfile(options =>dbms_logmnr.removefile,logfilenam


e =>'/opt/oracle/ora92/rdbms/ARC00011.001');



 8.启动LogMiner进行分析


SQL> execute dbms_logmnr.start_logmnr(dictfilename =>'/opt/oracle/logminer/log/sqltrace.or


a',starttime =>to_date('20040625 09:00:00','yyyymmdd hh24:mi:ss'),endtime =>to_d


 


http://www.zahui.com/html/8/16003.htm

Oracle LogMiner终结版

Oracle LogMiner 是Oracle公司从产品8i以后提供的一个实际非常有用的分析工具,使用该工具可以轻松获得Oracle 重作日志文件(归档日志文件)中的具体内容,特别是,该工具可以分析出所有对于数据库操作的DML(insert、update、delete等)语句,另外还可分析得到一些必要的回滚SQL语句。该工具特别适用于调试、审计或者回退某个特定的事务。

LogMiner分析工具实际上是由一组PL/SQL包和一些动态视图(Oracle8i内置包的一部分)组成,它作为Oracle数据库的一部分来发布,是8i产品提供的一个完全免费的工具。但该工具和其他Oracle内建工具相比使用起来显得有些复杂,主要原因是该工具没有提供任何的图形用户界面(GUI)。本文将详细介绍如何安装以及使用该工具。

一、LogMiner的用途

日志文件中存放着所有进行数据库恢复的数据,记录了针对数据库结构的每一个变化,也就是对数据库操作的所有DML语句。

在Oracle 8i之前,Oracle没有提供任何协助数据库管理员来读取和解释重作日志文件内容的工具。系统出现问题,对于一个普通的数据管理员来讲,唯一可以作的工作就是将所有的log文件打包,然后发给Oracle公司的技术支持,然后静静地等待Oracle 公司技术支持给我们最后的答案。然而从8i以后,Oracle提供了这样一个强有力的工具-LogMiner。

LogMiner 工具即可以用来分析在线,也可以用来分析离线日志文件,即可以分析本身自己数据库的重作日志文件,也可以用来分析其他数据库的重作日志文件。

总的说来,LogMiner工具的主要用途有:

1. 跟踪数据库的变化:可以离线的跟踪数据库的变化,而不会影响在线系统的性能。

2. 回退数据库的变化:回退特定的变化数据,减少point-in-time recovery的执行。

3. 优化和扩容计划:可通过分析日志文件中的数据以分析数据增长模式。

二、安装LogMiner

要安装LogMiner工具,必须首先要运行下面这样两个脚本,

l $ORACLE_HOME/rdbms/admin/dbmslsm.sql

2 $ORACLE_HOME/rdbms/admin/dbmslsmd.sql.

这两个脚本必须均以SYS用户身份运行。其中第一个脚本用来创建DBMS_LOGMNR包,该包用来分析日志文件。第二个脚本用来创建DBMS_LOGMNR_D包,该包用来创建数据字典文件。

三、使用LogMiner工具

下面将详细介绍如何使用LogMiner工具。

1、创建数据字典文件(data-dictionary)

前面已经谈到,LogMiner工具实际上是由两个新的PL/SQL内建包((DBMS_LOGMNR 和 DBMS_ LOGMNR_D)和四个V$动态性能视图(视图是在利用过程DBMS_LOGMNR.START_LOGMNR启动LogMiner时创建)组成。在使用LogMiner工具分析redo log文件之前,可以使用DBMS_LOGMNR_D 包将数据字典导出为一个文本文件。该字典文件是可选的,但是如果没有它,LogMiner解释出来的语句中关于数据字典中的部分(如表名、列名等)和数值都将是16进制的形式,我们是无法直接理解的。例如,下面的sql语句:

INSERT INTO dm_dj_swry (rydm, rymc) VALUES (00005, '张三'); 

LogMiner解释出来的结果将是下面这个样子,

insert into Object#308(col#1, col#2) values (hextoraw('c30rte567e436'), hextoraw('4a6f686e20446f65')); 

创建数据字典的目的就是让LogMiner引用涉及到内部数据字典中的部分时为他们实际的名字,而不是系统内部的16进制。数据字典文件是一个文本文件,使用包DBMS_LOGMNR_D来创建。如果我们要分析的数据库中的表有变化,影响到库的数据字典也发生变化,这时就需要重新创建该字典文件。另外一种情况是在分析另外一个数据库文件的重作日志时,也必须要重新生成一遍被分析数据库的数据字典文件。

首先在init.ora初始化参数文件中,指定数据字典文件的位置,也就是添加一个参数UTL_FILE_DIR,该参数值为服务器中放置数据字典文件的目录。如:

UTL_FILE_DIR = (e:\Oracle\logs) 

重新启动数据库,使新加的参数生效,然后创建数据字典文件:

SQL> CONNECT SYS

SQL> EXECUTE dbms_logmnr_d.build(

dictionary_filename => ' v816dict.ora', 

dictionary_location => 'e:\oracle\logs'); 

2、创建要分析的日志文件列表

Oracle的重作日志分为两种,在线(online)和离线(offline)归档日志文件,下面就分别来讨论这两种不同日志文件的列表创建。

(1)分析在线重作日志文件

A. 创建列表

SQL> EXECUTE dbms_logmnr.add_logfile(

LogFileName=>' e:\Oracle\oradata\sxf\redo01.log',

Options=>dbms_logmnr.new); 

B. 添加其他日志文件到列表

SQL> EXECUTE dbms_logmnr.add_logfile(

LogFileName=>' e:\Oracle\oradata\sxf\redo02.log',

Options=>dbms_logmnr.addfile);(2)分析离线日志文件

A.创建列表

SQL> EXECUTE dbms_logmnr.add_logfile(

LogFileName=>' E:\Oracle\oradata\sxf\archive\ARCARC09108.001',

Options=>dbms_logmnr.new); 

B.添加另外的日志文件到列表

SQL> EXECUTE dbms_logmnr.add_logfile(

LogFileName=>' E:\Oracle\oradata\sxf\archive\ARCARC09109.001',

Options=>dbms_logmnr.addfile);关于这个日志文件列表中需要分析日志文件的个数完全由你自己决定,但这里建议最好是每次只添加一个需要分析的日志文件,在对该文件分析完毕后,再添加另外的文件。

和添加日志分析列表相对应,使用过程 'dbms_logmnr.removefile' 也可以从列表中移去一个日志文件。下面的例子移去上面添加的日志文件e:\Oracle\oradata\sxf\redo02.log。

SQL> EXECUTE dbms_logmnr.add_logfile(

LogFileName=>' e:\Oracle\oradata\sxf\redo02.log',

Options=>dbms_logmnr. REMOVEFILE); 

创建了要分析的日志文件列表,下面就可以对其进行分析了。

3、使用LogMiner进行日志分析

(1)无限制条件

SQL> EXECUTE dbms_logmnr.start_logmnr(

DictFileName=>' e:\oracle\logs\ v816dict.ora '); 

(2)有限制条件

通过对过程DBMS_ LOGMNR.START_LOGMNR中几个不同参数的设置(参数含义见表1),可以缩小要分析日志文件的范围。通过设置起始时间和终止时间参数我们可以限制只分析某一时间范围的日志。如下面的例子,我们仅仅分析2001年9月18日的日志,:

SQL> EXECUTE dbms_logmnr.start_logmnr(

DictFileName => ' e:\oracle\logs\ v816dict.ora ', 

StartTime => to_date('2001-9-18 00:00:00','YYYY-MM-DD HH24:MI:SS')

EndTime => to_date(''2001-9-18 23:59:59','YYYY-MM-DD HH24:MI:SS ')); 

也可以通过设置起始SCN和截至SCN来限制要分析日志的范围:

SQL> EXECUTE dbms_logmnr.start_logmnr(

DictFileName => ' e:\oracle\logs\ v816dict.ora ',

StartScn => 20,

EndScn => 50); 

表1 DBMS_LOGMNR.START__LOGMNR过程参数含义



4、观察分析结果(v$logmnr_contents)

到现在为止,我们已经分析得到了重作日志文件中的内容。动态性能视图v$logmnr_contents包含LogMiner分析得到的所有的信息。

SELECT sql_redo FROM v$logmnr_contents; 

如果我们仅仅想知道某个用户对于某张表的操作,可以通过下面的SQL查询得到,该查询可以得到用户DB_ZGXT对表SB_DJJL所作的一切工作。

SQL> SELECT sql_redo FROM v$logmnr_contents WHERE username='DB_ZGXT' AND tablename='SB_DJJL'; 

需要强调一点的是,视图v$logmnr_contents中的分析结果仅在我们运行过程'dbms_logmrn.start_logmnr'这个会话的生命期中存在。这是因为所有的LogMiner存储都在PGA内存中,所有其他的进程是看不到它的,同时随着进程的结束,分析结果也随之消失。

最后,使用过程DBMS_LOGMNR.END_LOGMNR终止日志分析事务,此时PGA内存区域被清除,分析结果也随之不再存在。

四、其他注意事项

我们可以利用LogMiner日志分析工具来分析其他数据库实例产生的重作日志文件,而不仅仅用来分析本身安装LogMiner的数据库实例的redo logs文件。使用LogMiner分析其他数据库实例时,有几点需要注意:

1. LogMiner必须使用被分析数据库实例产生的字典文件,而不是安装LogMiner的数据库产生的字典文件,另外必须保证安装LogMiner数据库的字符集和被分析数据库的字符集相同。

2. 被分析数据库平台必须和当前LogMiner所在数据库平台一样,也就是说如果我们要分析的文件是由运行在UNIX平台上的Oracle 8i产生的,那么也必须在一个运行在UNIX平台上的Oracle实例上运行LogMiner,而不能在其他如Microsoft NT上运行LogMiner。当然两者的硬件条件不一定要求完全一样。

3. LogMiner日志分析工具仅能够分析Oracle 8以后的产品,对于8以前的产品,该工具也无能为力。

五、结语

LogMiner对于数据库管理员(DBA)来讲是个功能非常强大的工具,也是在日常工作中经常要用到的一个工具,借助于该工具,可以得到大量的关于数据库活动的信息。其中一个最重要的用途就是不用全部恢复数据库就可以恢复数据库的某个变化。另外,该工具还可用来监视或者审计用户的活动,如你可以利用LogMiner工具察看谁曾经修改了那些数据以及这些数据在修改前的状态。我们也可以借助于该工具分析任何Oracle 8及其以后版本产生的重作日志文件。另外该工具还有一个非常重要的特点就是可以分析其他数据库的日志文件。总之,该工具对于数据库管理员来讲,是一个非常有效的工具,深刻理解及熟练掌握该工具,对于每一个数据库管理员的实际工作是非常有帮助的。


http://www.chinaunix.net/jh/19/210248.html

执行计划的使用(EXPLAIN)

对于 sql 执行的小量高低.我们可以通过执行计划的信息基本上可以进行分析查看该SQL语句执行的时间.连接顺序及浪费的数据库资源等信息,从而判断该SQL语句执行的效率如何,下面就简单的介绍一下执行计划的使用

2. Explain使用
Oracle RDBMS 执行每一条 SQL 语句,都必须经过 Oracle 优化器的评估。所以,了解优化器是如何选择(搜索)路径以及索引是如何被使用的,对优化 SQL 语句有很大的帮助。Explain 可以用来迅速方便地查出对于给定 SQL 语句中的查询数据是如何得到的即搜索路径(我们通常称为 Access Path)。从而使我们选择最优的查询方式达到最大的优化效果。
2.1. 安装
要使用执行计划首先需要执行相应的脚本。
使用 Explain 工具需要创建 Explain_plan 表,这必须先进入相关应用表、视图和索引的所有者的帐户内。Oracle 的介质中包含有执行此项工作的 SQL 源程序,例如:

ORA_RDBMS: XPLAINPL.SQL (VMS)
$ORACLE_HOME/rdbms/admin/utlxplan.sql (UNIX)

该脚本后会生成一个表这个程序会创建一个名为 plan_table 的表,表结构如下:
我们简单的介绍一下主要的字段含义:
字段名                       字段类型                    含义
STATEMENT_ID        VARCHAR2(30)        explain PLAN 语句中所指定的最优STATEMENT_ID 参数值, 如果在 EXPLAN PLAN 语句中没有使用SET STATEMENT_ID,那么此值会被设为 NULL。  
REMARKS                 VARCHAR2(80)        与被解释规划的各步骤相关联的注释最长可达80 字节
OPERATION              VARCHAR2(30)        各步骤所执行内部操作的名称在某条语句所产生的第一行中该列的可能取值如下 DELETE STATEMENT INSERT STATEMENT SELECT STATEMENT UPDATE STATEMENT
OPTIONS                   VARCHAR2(30)         对OPERATION 列中所描述操作的变种
OBJECT_NODE         VARCHAR2(128)       用于访问对象的数据库链接 database link 的名称对于使用并行执行的本地查询该列能够描述操作中输出的次序
OBJECT_OWNER      VARCHAR2(30)         对于包含有表或索引的架构 schema 给出其所有者的名称
OBJECT_NAME          VARCHAR2(30)        表或索引的名称
OBJECT_INSTANCE   INTEGER                  根据对象出现在原始 original 语句中的次序所给出的相应次序编号就原始的语句文本而论其处理顺序为自左至右自外向内景象扩张 view
OBJECT_TYPE          VARCHAR2(30)         用于提供对象描述性信息的修饰符例如索引的 NON-UNIQUE
OPTIMIZER                VARCHAR2(255)        当前优化程序的模式
ID                               INTEGER                    分配给执行规划各步骤的编号
PARENT_ID               INTEGER                    对 ID 步骤的输出进行操作的下一个执行步骤的ID
POSITION                  INTEGER                    对于具有相同 PARENT_ID 的步骤其相应的处理次序
COST                        INTEGER                    根据优化程序的基于开销的方法所估计出的操作开销值对于使用基于规则方法的语句该列为空该列值没有特定的测量单位它只是一个用于比较执行规划开销大小的权重值
CARDINALITY            INTEGER                    根据基于开销的方法对操作所访问行数的估计值
BYTES                       INTEGER                    根据基于开销的方法对操作所访问字节的估计

2.2. 使用
2.2.1. 常规使用

常规使用语法:
explain PLAN [ SET STATEMENT_ID [=] < string literal > ]
[ INTO < table_name > ]
FOR < sql_statement >
其中:
STATEMENT_ID 是一个唯一的字符串,把当前执行计划与存储在同一 PLAN 表中的其它执行计划区别开来。
TABLE_NAME 是 plan 表名,它结构如前所示,你可以任意设定这个名称。
SQL_STATEMENT 是真正的SQL语句。
如:
SQL> explain plan set statement_id='test1' for  
  2     SELECT a.soctermbegin,
  3            a.soctermend,
  4            a.dealserialno,
  5            a.levydataid,
  6            a.dealtotal,
  7            e.categoryitemcode,
  8            row_number() over(PARTITION BY a.levydataid ORDER BY 1) AS theRow
  9       FROM tb_soc_packdealdata   a,
10            tb_Lvy_TaxDataBillMap c,
11            Tb_lvy_BillData       d,
12            tb_soc_levydetaildata e
13      WHERE a.levydataid = c.datafrompointer(+)
14        AND c.billdataid = d.billdataid(+)
15        AND a.levydataid = e.levydataid
16        AND a.packdealstatuscode = '10'
17        AND (a.datastatus <> '9' OR a.datastatus is NULL)
18        AND (d.billstatus IS NULL OR
19            (d.billstatus <> '2' AND d.billstatus <> '8'))
20        AND a.Insurcode = '6010952'
21  ;
Explained

执行下面语句就可以查看该语句执行的执行计划:
SQL> SELECT A.OPERATION,OPTIONS,OBJECT_NAME,OBJECT_TYPE,ID,PARENT_ID
  2  FROM PLAN_TABLE  a
  3  WHERE STATEMENT_ID='test1'
  4  ORDER BY Id;
OPERATION        OPTIONS        OBJECT_NAME                    OBJECT_TYPEID  PARENT_ID
---------------- --------------------------------------------- ------------- ----------
SELECT STATEMENT                                                           0
WINDOW           SORT                                                      1          0
FILTER                                                                     2          1
NESTED LOOPS     OUTER                                                     3          2
NESTED LOOPS     OUTER                                                     4          3
NESTED LOOPS                                                               5          4
TABLE ACCESS     FULL           TB_SOC_PACKDEALDATA                        6          5
TABLE ACCESS     BY INDEX ROWID TB_SOC_LEVYDETAILDATA                      7          5
INDEX            RANGE SCAN     IND_DATAID_LEVSOC              NON-UNIQUE  8          7
TABLE ACCESS     BY INDEX ROWID TB_LVY_TAXDATABILLMAP                      9          4
INDEX            RANGE SCAN     TBLVYTAXDATABIL_DATAFROMPOINTE NON-UNIQUE 10          9
TABLE ACCESS     BY INDEX ROWID TB_LVY_BILLDATA                           11          3
INDEX            UNIQUE SCAN    TBLVYBILLDATA_BILLDATAID       UNIQUE  

2.2.2.自动显示使用
在SQLPLUS中自动跟踪显示执行计划及相关信息
SQL>set timing on  --显示执行时间
SQL>set autorace on --显示执行计划
SQL>set autorace on --显示执行计划
SQL>set autotrace traceonly --只显示执行计划即不显示查询出来的数据
设置完毕后执行SQL语句就会显示执行计划信息及相应的统计信息(需要设置显示该选项)
SQL> select nvl(sum(t.taxdue), 0)
  2             from tb_lvy_sbzs100 t, tb_lvy_declaredoc a, tb_lvy_declaredoc b
  3            where a.dossiercode = 'SB02041108'
  4              and a.pages = 123
  5              and a.remarkid = b.remarkid
  6              AND A.REMARKID IS NOT NULL
  7              and b.declaredocid = t.declaredocid;
NVL(SUM(T.TAXDUE),0)
--------------------
                   0
已用时间:  00: 00: 04.07
Execution Plan
----------------------------------------------------------
   0    SELECT STATEMENT Optimizer=CHOOSE (Cost=6 Card=1 Bytes=110)
   1    0   SORT (AGGREGATE)
   2    1   NESTED LOOPS (Cost=6 Card=1 Bytes=110)
   3    2   MERGE JOIN (CARTESIAN) (Cost=4 Card=1 Bytes=74)
   4    3   TABLE ACCESS (FULL) OF 'TB_LVY_SBZS100' (Cost=2 Card =1 Bytes=31)
   5    3    BUFFER (SORT) (Cost=2 Card=1 Bytes=43)
   6    5    TABLE ACCESS (FULL) OF 'TB_LVY_DECLAREDOC' (Cost=2 Card=1 Bytes=43)
   7    2    TABLE ACCESS (BY INDEX ROWID) OF 'TB_LVY_DECLAREDOC' (Cost=2 Card=1 Bytes=36)
   8    7     INDEX (UNIQUE SCAN) OF 'TBLVYDECLAREDOC_DECLAREDOCID' (UNIQUE)
Statistics
----------------------------------------------------------
          0  recursive calls --循环递归次数
          0  db block gets―请求的数据块在buffer能满足的个数
       6675  consistent gets --逻辑IO用于读表并计算行数, 数据请求总数在回滚段Buffer 中
         45  physical reads --从磁盘读到 Buffer Cache 数据块数量
          0  redo size --产生的 redo 日志大小
        217  bytes sent via SQL*Net to client
        276  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          1  sorts (memory)
          0  sorts (disk)
          1  rows processed
SQL>
如果6675  consistent gets --逻辑IO用于读表并计算行数, 数据请求总数在回滚段Buffer 中
45        physical reads --从磁盘读到 Buffer Cache 数据块数量
的数值比较小则该语句对对数据库的性能比较高。

2.2.3.PL/SQL和TOAD中使用
如果在PL/SQL中使用选择要查询语句显示执行计划,则只需要 SQL WINDOWS 窗口里面输入要查询的SQL语句,然后选择按键 F5 或者在菜单TOOLS-->Explain Plan 菜单按键就可以在执行计划窗口查看该语句的执行计划。
在 TOAD 语句中在执行当前的 SQL 窗口中选择下方的 Explain PlanTAB 页即可以查看要执行语句的执行计划信息。

2.3.限制
虽然任何 SQL 语句都可以用explain解释,但对于没有查询的INSERT,UPDATE,DELETE操作来说,这个工具并没有太大的用处。没有子查询的INSERT操作不会创建执行计划,但没有WHERE子句或子查询的 UPDATE 和 DELETE 操作会创建执行计划,因为这些操作必须先找出所要的记录。
另外,如果你在SQL语句中使用其它类型如 sequence 等,explain 也能揭示它的用法。
explain 真正的唯一的限制是用户不能去解释其它用户的表,视图,索引或其它类型,用户必须是所有被解释事物的所有者,如果不是所有者而只有 select 权限,explain 会返回一个错误。

关于 AUTOTRACE 的一些讨论分析

SQLPLUS的AutoTrace是分析SQL的执行计划,执行效率的一个非常简单方便的工具,在绝大多数情况下,也是非常有用的工具。


这里,我们试图归纳一些常见的问题,并进行一定的分析

1.如何设置和使用AUTOTRACE


SQL> connect / as sysdba
SQL> @?/rdbms/admin/utlxplan.sql


Table created.


SQL> create public synonym plan_table for plan_table;


Synonym created.


SQL> grant select,update,insert,delete on plan_table to public;


Grant succeeded.


SQL> @?/sqlplus/admin/plustrce.sql
SQL>grant plustrace to public.


2. 理解和使用AutoTrace

对于 SQL 调整,使用 Autotrace 是最简单的方法了,我们只需要做:
SQL>SET AUTOTRACE ON
我们就可以看到我们SQL的执行计划,执行成本(PHYSICAL READ/CONSISTENT READ...)
加上 SET Timing On 或者 Set Time On,我们可以得到很多我们需要的数据。


SQL> select nvl(title,' ') from punishinfo_cs where ci_id=45672 ;


NVL(TITLE,'')
--------------------------------------------------
阎王令


Elapsed: 00:00:00.00
SQL> set autotrace on
SQL> /


NVL(TITLE,'')
--------------------------------------------------
阎王令


Elapsed: 00:00:00.71


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=2 Card=1 Bytes=32)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'PUNISHINFO_CS' (Cost=2 Card=1 Bytes=32)


2 1 INDEX (UNIQUE SCAN) OF 'SYS_C001084' (UNIQUE) (Cost=1 Card=1)


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


3.关于使用 Autotrace 的一些常见疑问:

a.比如我上面的例子,我不用Autotrace,我的时间小于0.01S,但是用了Autotrace,我的执行时间变成了0.71S.
不注意的人往往会认为,或者没有测试不用Autotrace时候的情况,往往会忽视这个数字,认为时间就是0.71S.
实际上,这个0.7S,是花在Autotrace里面的时间。由于Autotrace需要记录你的SQL执行的成本,这个本身是往数据库里面读取和写入一定的数据的,需要一定的时间。当你的SQL执行时间足够短的时候,这个由于Autotrace带来的时间就变成非常可观的了。我们就需要通过不用Autotrace的时间,和使用Autotrace的执行成本来结合比较。


我们通过结合 Autotrace 和 Tkprof/SQLTRACE,很容易知道,Autotrace 究竟作了什么:

select nvl(title,' ')
from
punishinfo_cs where ci_id=45672

call        count cpu    elapsed disk      query  current rows
-------      ------   -------- ----------   ---------- ---------- ---------- ----------
Parse      1      0.00   0.01      0          0         0          0
Execute   1      0.00   0.00      0         0          0          0
Fetch       2      0.00   0.00      0         3          0          1
-------      ------   --------  ----------  ---------- ---------- ---------- ----------
total       4        0.00   0.01      0         3          0          1

DELETE FROM PLAN_TABLE
WHERE
STATEMENT_ID=:1

EXPLAIN PLAN SET STATEMENT_ID='PLUS185025' FOR select nvl(title,' ') from
punishinfo_cs where ci_id=45672

insert into plan_table (statement_id, timestamp, operation, options,
object_node, object_owner, object_name, object_instance, object_type,
search_columns, id, parent_id, position, other,optimizer, cost, cardinality,
bytes, other_tag, partition_start, partition_stop, partition_id,
distribution )
values
(:1,SYSDATE,:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18,:19,
:20,:21,:22)

SELECT ID ID_PLUS_EXP,PARENT_ID PARENT_ID_PLUS_EXP,LPAD(' ',2*(LEVEL-1))
||OPERATION||DECODE(OTHER_TAG,NULL,'','*')||DECODE(OPTIONS,NULL,'','
('||OPTIONS||')')||DECODE(OBJECT_NAME,NULL,'',' OF '''||OBJECT_NAME||'''')
||DECODE(OBJECT_TYPE,NULL,'',' ('||OBJECT_TYPE||')')||DECODE(ID,0,
DECODE(OPTIMIZER,NULL,'',' Optimizer='||OPTIMIZER))||DECODE(COST,NULL,'','
(Cost='||COST||DECODE(CARDINALITY,NULL,'',' Card='||CARDINALITY)
||DECODE(BYTES,NULL,'',' Bytes='||BYTES)||')') PLAN_PLUS_EXP,OBJECT_NODE
OBJECT_NODE_PLUS_EXP
FROM
PLAN_TABLE START WITH ID=0 AND STATEMENT_ID=:1 CONNECT BY PRIOR ID=PARENT_ID
AND STATEMENT_ID=:1 ORDER BY ID,POSITION

SELECT ID ID_PLUS_EXP,OTHER_TAG OTHER_TAG_PLUS_EXP,OTHER OTHER_PLUS_EXP
FROM
PLAN_TABLE WHERE STATEMENT_ID=:1 AND OTHER_TAG IS NOT NULL ORDER BY ID


我们看到,由于我们的 Autotrace,简简单单的一句话,实际上 oracle 做了那么多的事情。
一:How do i decide which query is better depending on the values of the each parameter in statistics?
1 Important parameters:
db blocks gets,consistent gets :logical reads or memory usage.
physical reads is disk I/O Depending on this we can estimate the memory usage.
2:secondly,recursive calls,redo size,sorts(memory),sorts(disk)
3:thirdly:bytes sent via SQL&Net from client ,bytes received via SQL&Net from client,SQL&Net roundtrips to/from client


二:What these parameters really mean?
Recursive calls – The number of recursive calls to the database. This type of call occurs for a few reasons – misses in the dictionary cache, dynamic storage extension, and when PL/SQL statements are executed. Generally, if the number of recursive calls is more than 4 per process, you should check the dictionary hit cache ratio. Recursive Calls These occur because of cache misses and dynamic storage extension. If the dictionary data is found in cache, a recursive call is not made and the data is read from cache directly. In general, if recursive calls are greater than four per process, the data dictionary cache should be optimized and segments should be rebuilt with storage clauses to have a few large extents. Segments include tables, indexes, and rollback segments.Recursive calls should be fewer than user calls (less than one-tenth). Where there is an imbalance, the aim should be to reduce parsing. High levels of recursive SQL may also be attributable to significant use of PL/SQL. For each SQL statement in a PL/SQL block, on each iteration, there are recursive calls to do the equivalent of bind and define.

DB Block gets – The number of blocks in the buffer cache that were accessed for INSERT, UPDATE, DELETE and SELECT for UPDATE statements.

Consistent gets – The number of blocks accessed in the buffer cache for queries without the SELECT FOR UPDATE clause. The value for this statistic plus the value of the “db block gets” statistic constitute what is referred to as a logical read.

Physical Reads – the number of data blocks that were read from disks to satisfy a SELECT, SELECT FOR UPDATE, INSERT, UPDATE or DELETE.
Data Cache Hit Ratio
Hit Ratio = (Logical Reads – Physical Reads) / Logical Reads

Redo Size – the size in bytes of the amount of redo information that was written to the redo logs. This information can be used to help size the redo logs and the LOG_SMALL_ENTRY_MAX_SIZE parameter in the init.ora.

Sorts(memory) – the number of sorts that were performed in memory

Sorts(disk) – the number of sorts that were unable to be performed in memory and therefore required the creation of a temp segment in the temporary tablespace. This statistic divided by the sorts(memory) should not be above the 5 percent. If it is, you should increase the SORT_AREA_SIZE parameter in the init.ora.


有时候我们会看到一些看上去很奇怪的问题,比如,有时候,我们的 Autotrace,会显示,Select 语句也会有 Redo 产生。
这里可能有两种情况:
1.Delayed Block Cleanout:
比如下面这个例子:


SQL>DELETE FROM T WHERE ROWNUM<100;
SQL>DELETE FROM T WHERE ROWNUM<100;
SQL>DELETE FROM T WHERE ROWNUM<100;
SQL>DELETE FROM T WHERE ROWNUM<100;
COMMIT;


SQL> select count(*) from t;


COUNT(*)
----------
25606


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (AGGREGATE)
2 1 TABLE ACCESS (FULL) OF 'T'


Statistics
----------------------------------------------------------
0 recursive calls
12 db block gets
326 consistent gets
0 physical reads
360 redo size
369 bytes sent via SQL*Net to client
426 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

第二种情况是:
用户用来排序的临时表空间不是真正的临时表空间:
例子:


SQL> L
1* ALTER USER TEST TEMPORARY TABLESPACE SYSTEM
SQL> /


User altered.


SQL> SELECT * FROM T ORDER BY 1,2,3,4,5,6;


25606 rows selected.


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (ORDER BY)
2 1 TABLE ACCESS (FULL) OF 'T'


Statistics
----------------------------------------------------------
1382 recursive calls
286 db block gets
740 consistent gets
809 physical reads
28264 redo size
1239304 bytes sent via SQL*Net to client
189903 bytes received via SQL*Net from client
1709 SQL*Net roundtrips to/from client
0 sorts (memory)
1 sorts (disk)
25606 rows processed

我们把用户的临时表空间重新改成 Locally MANAGED TEMPORARY TABLESPACE:


SQL> ALTER USER TEST TEMPORARY TABLESPACE TEMP;


User altered.


SQL> CONN TEST/TEST
Connected.
SQL> SET AUTOTRACE TRACEONLY;
SQL> SELECT * FROM T ORDER BY 1,2,3,4,5,6;


25606 rows selected.


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (ORDER BY)
2 1 TABLE ACCESS (FULL) OF 'T'


Statistics
----------------------------------------------------------
0 recursive calls
53 db block gets
320 consistent gets
808 physical reads
0 redo size
1239304 bytes sent via SQL*Net to client
189903 bytes received via SQL*Net from client
1709 SQL*Net roundtrips to/from client
0 sorts (memory)
1 sorts (disk)
25606 rows processed

还有一个挺难理解的现象:


SQL> conn internal
Connected.
SQL> set autotrace traceonly;
SQL> select * from test.t ORDER BY 1,2,3,4,5,6;


25606 rows selected.


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 SORT (ORDER BY)
2 1 TABLE ACCESS (FULL) OF 'T'


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


同样的语句,没有任何Trace的值。
这里,是因为我用 Internal 用户的连接,或者说,SYSDBA权限的连接。
用这个用户连接,没有Trace的结果的。


这一点,特别感谢 Oldwain 老哥,上面有:
DB Block gets – The number of blocks in the buffer cache that were accessed for INSERT, UPDATE, DELETE and SELECT for UPDATE statements.
为什么 普通的select 语句也有 db block gets??
如:
SQL> select empno,deptno from hashemp where deptno=10;


EMPNO DEPTNO
---------- ----------
7782 10
7839 10
7934 10


Elapsed: 00:00:02.36


Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (HASH) OF 'HASHEMP'


Statistics
----------------------------------------------------------
0 recursive calls
1 db block gets
2 consistent gets
0 physical reads
0 redo size
522 bytes sent via SQL*Net to client
503 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
3 rows processed
这个我就直接应用 Tom 的原话了:


recursive calls = basically sql performed on behalf of your sql. So, if we had
to PARSE the query for example, we might have had to run some other queries to
get data dictionary info. that would be recursive calls.


db block gets = blocks gotten in "current" mode. That is, blocks gotten as they
exist right now. You'll see these for full table scans (segment headers are
read in current mode) and modification statements (we modify the block as it
exists "right now")


consistent gets = blocks gotten in consistent read mode. This is the mode we
read blocks in with a select for example. Also, when you do a searched
UPDATE/DELETE, we read the blocks in consistent read mode and then get the block
in current mode to actually do the modification. A select for update will do
this as well.


physical reads = self explanatory, physical IO


redo size = self explanatory -- amount of redo generated


sorts (memory)/(disk) -- sorts done.

当时也是想了很久也没有想出来。

MTS 与 DEDICATE 介绍与比较

  一、简介

  MTS(Multi-Threaded Server)是ORACLE SERVER的一个可选的配置选择,是相对DEDICATE方式而言,它最大的优点是在以不用增加物理资源(内存)的前提下支持更多的并发的连接。换句话说,如果你只有2G的物理内存,而你又想支持2000个连接,在获取最好性能的前提下,你就应该选择MTS了。

  本文先说一说MTS的工作方式,然后与DEDICATE方式的做一下比较,接下来说一下MTS具体配置实现,最后说一些优化MTS配置选项的问题。

  二、MTS的工作方式

  1、Joseph C.Johnson以餐馆给出一个MTS的形象的比喻

  假设ORACLE是一家餐馆,当你走进一家餐馆时你感觉最舒服的服务方式就是有一个专门的waiter来为你服务,而不管餐馆中来了多少人,她只对你请求应答,这是DEDICTE的处理方式,也就是说每一个ORACLE客户端的连接都有一个专门的服务进程来为它服务。而大部的餐馆的服方式都不是一对一的,当你走进的时侯,你就被指定了一个waiter,她也可能为其它桌服着务,这对于餐馆来说是最有利的,因为他们可以服务更多的客人而不需要增加他们的员工。这样对你来说也可能是不错的,如果餐馆不是太忙,她服务的客人的请求都很简短且容易完成,你的感觉也好像自己拥有一个专门的waiter,waiter把你的ORDER转给厨师,然后把做好的菜拿给你,这就是MTS的处理方式,这些共享的waiters我们叫她们为Dispatchers,厨师我们则叫他们为Shared Server Processes。


  2、以简图说一下MTS的工作方式(SYBEX书中的一幅图)


  1)客户端向Dispatcher发一个服务请求

  2)Dispatch把这个请求放到SGA区的请求对队列中

  3)由一个或几个服务进程来处理这个请求

  4)服务进程把进行的结果放到Dispatch的SGA区的的响应队列中

  5)Dispatcher从响应队列拾起结果

  6)完成客户端的请求并把结果回送给客户端

  三、MTS与DEDICATE方式方面做一下比较,为方便比较绘制如下的简表































序号


比较项


MTS方式


DEDICATE方式


1


服务进程


多个连接共享一个服务进程


一个连接有一个专门的服务进程


2


每个客户端的连接使用的内存量


3-4M


150-200K


3


适合的应用环境


适合连接数很多且请求很短少的OLTP环境


如果Oracle服务器的资源够用,这种方式是优选


4


CPU负载


会造成一些CPU的负载,如果你的CPU有瓶颈,则不要用这种方式


 


 http://www.pconline.com.cn/pcedu/empolder/db/oracle/0403/324651.html

OLTP 与 OLAP 介绍和比较

联机分析处理 (OLAP) 的概念最早是由关系数据库之父E.F.Codd于1993年提出的,他同时提出了关于OLAP的12条准则。OLAP的提出引起了很大的反响,OLAP作为一类产品同联机事务处理 (OLTP) 明显区分开来。

    当今的数据处理大致可以分成两大类:联机事务处理OLTP(on-line transaction processing)、联机分析处理OLAP(On-Line Analytical Processing)。OLTP是传统的关系型数据库的主要应用,主要是基本的、日常的事务处理,例如银行交易。OLAP是数据仓库系统的主要应用,支持复杂的分析操作,侧重决策支持,并且提供直观易懂的查询结果。下表列出了OLTP与OLAP之间的比较。















































OLTP

OLAP

用户

操作人员,低层管理人员

决策人员,高级管理人员

功能

日常操作处理

分析决策

DB 设计

面向应用

面向主题

数据

当前的, 最新的细节的, 二维的分立的

历史的, 聚集的, 多维的集成的, 统一的

存取

读/写数十条记录

读上百万条记录

工作单位

简单的事务

复杂的查询

用户数

上千个

上百个

DB 大小

100MB-GB

100GB-TB




    
     OLAP是使分析人员、管理人员或执行人员能够从多角度对信息进行快速、一致、交互地存取,从而获得对数据的更深入了解的一类软件技术。OLAP的目标是满足决策支持或者满足在多维环境下特定的查询和报表需求,它的技术核心是"维"这个概念。

    “维”是人们观察客观世界的角度,是一种高层次的类型划分。“维”一般包含着层次关系,这种层次关系有时会相当复杂。通过把一个实体的多项重要的属性定义为多个维(dimension),使用户能对不同维上的数据进行比较。因此OLAP也可以说是多维数据分析工具的集合。

    OLAP的基本多维分析操作有钻取(roll up和drill down)、切片(slice)和切块(dice)、以及旋转(pivot)、drill across、drill through等。

·钻取是改变维的层次,变换分析的粒度。它包括向上钻取(roll up)和向下钻取(drill down)。roll up是在某一维上将低层次的细节数据概括到高层次的汇总数据,或者减少维数;而drill down则相反,它从汇总数据深入到细节数据进行观察或增加新维。
·切片和切块是在一部分维上选定值后,关心度量数据在剩余维上的分布。如果剩余的维只有两个,则是切片;如果有三个,则是切块。
·旋转是变换维的方向,即在表格中重新安排维的放置(例如行列互换)。

    OLAP有多种实现方法,根据存储数据的方式不同可以分为ROLAP、MOLAP、HOLAP。

    ROLAP表示基于关系数据库的OLAP实现(Relational OLAP)。以关系数据库为核心,以关系型结构进行多维数据的表示和存储。ROLAP将多维数据库的多维结构划分为两类表:一类是事实表,用来存储数据和维关键字;另一类是维表,即对每个维至少使用一个表来存放维的层次、成员类别等维的描述信息。维表和事实表通过主关键字和外关键字联系在一起,形成了"星型模式"。对于层次复杂的维,为避免冗余数据占用过大的存储空间,可以使用多个表来描述,这种星型模式的扩展称为"雪花模式"。

    MOLAP表示基于多维数据组织的OLAP实现(Multidimensional OLAP)。以多维数据组织方式为核心,也就是说,MOLAP使用多维数组存储数据。多维数据在存储中将形成"立方块(Cube)"的结构,在MOLAP中对"立方块"的"旋转"、"切块"、"切片"是产生多维数据报表的主要技术。

    HOLAP表示基于混合数据组织的OLAP实现(Hybrid OLAP)。如低层是关系型的,高层是多维矩阵型的。这种方式具有更好的灵活性。

还有其他的一些实现OLAP的方法,如提供一个专用的SQL Server,对某些存储模式(如星型、雪片型)提供对SQL查询的特殊支持。

    OLAP工具是针对特定问题的联机数据访问与分析。它通过多维的方式对数据进行分析、查询和报表。维是人们观察数据的特定角度。例如,一个企业在考虑产品的销售情况时,通常从时间、地区和产品的不同角度来深入观察产品的销售情况。这里的时间、地区和产品就是维。而这些维的不同组合和所考察的度量指标构成的多维数组则是OLAP分析的基础,可形式化表示为(维1,维2,……,维n,度量指标),如(地区、时间、产品、销售额)。多维分析是指对以多维形式组织起来的数据采取切片(Slice)、切块(Dice)、钻取(Drill-down和Roll-up)、旋转(Pivot)等各种分析动作,以求剖析数据,使用户能从多个角度、多侧面地观察数据库中的数据,从而深入理解包含在数据中的信息。

    根据综合性数据的组织方式的不同,目前常见的OLAP主要有基于多维数据库的MOLAP及基于关系数据库的ROLAP两种。MOLAP是以多维的方式组织和存储数据,ROLAP则利用现有的关系数据库技术来模拟多维数据。在数据仓库应用中,OLAP应用一般是数据仓库应用的前端工具,同时OLAP工具还可以同数据挖掘工具、统计分析工具配合使用,增强决策分析功能。


http://www.huihoo.com/database/dw2.html

如何在Linux上扩展SGA超过1.7G

今天一台Linux服务器扩展了一下内存,达到4G,开发的人自己修改了一下SGA结果数据库无法启动了.
启动不了时,出的错误是这个样子的:




            [oracle@neirong oracle]$ sqlplus "/ as sysdba"
SQL*Plus: Release 9.2.0.4.0 - Production on Fri Nov 25 15:43:26 2005
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
Connected to an idle instance.
SQL> startup
ORA-27123: unable to attach to shared memory segment
Linux Error: 22: Invalid argument
Additional information: 1
Additional information: 458753
SQL> exit
Disconnected

在32位平台上,缺省的SGA最大只能扩展到1.7G,如果需要支持更大的内存,就需要降低mapped_base,重新Link Oracle软件.
俺的平台为:




[oracle@neirong bdump]$ cat /etc/redhat-release
Red Hat Enterprise Linux AS release 3 (Taroon Update 2)

简单操作如下:
cd $ORACLE_HOME/rdbms/lib
cp ksms.s ksms.s.bak ( if u have a ksms.s file)
genksms -s 0x12000000 > ksms.s
make -f ins_rdbms.mk ksms.o
make -f ins_rdbms.mk ioracle

此处先备份ksms.s文件,如果编译过程中出现错误,保证操作可以被恢复:
恢复步骤大致如下:

cd $ORACLE_HOME/rdbms/lib
cp ksms.s.bak ksms.s (if u have backup ksms.s file)
genksms > ksms.s
make -f ins_rdbms.mk ksms.o
make -f ins_rdbms.mk ioracle
以下是操作日志:




[oracle@neirong dbs]$ cd $ORACLE_HOME/rdbms/lib
[oracle@neirong lib]$ genksms -s 0x12000000 > ksms.s
[oracle@neirong lib]$ make -f ins_rdbms.mk ksms.o
[oracle@neirong lib]$ make -f ins_rdbms.mk ioracle
- Linking Oracle
rm -f /opt/oracle/product/9.2.0/rdbms/lib/oracle
gcc -o /opt/oracle/product/9.2.0/rdbms/lib/oracle -L/opt/oracle/product/9.2.0/rdbms/lib/
-L/opt/oracle/product/9.2.0/lib/ -L/opt/oracle/product/9.2.0/lib/stubs/
-Wl,-E `test -f /opt/oracle/product/9.2.0/rdbms/lib/skgaioi.o && echo
/opt/oracle/product/9.2.0/rdbms/lib/skgaioi.o` /opt/oracle/product/9.2.0/rdbms/lib/opimai.o
/opt/oracle/product/9.2.0/rdbms/lib/ssoraed.o /opt/oracle/product/9.2.0/rdbms/lib/ttcsoi.o
/opt/oracle/product/9.2.0/lib/nautab.o /opt/oracle/product/9.2.0/lib/naeet.o
/opt/oracle/product/9.2.0/lib/naect.o /opt/oracle/product/9.2.0/lib/naedhs.o
/opt/oracle/product/9.2.0/rdbms/lib/config.o -lserver9 -lodm9 -lskgxp9 -lskgxn9 -lclient9
-lvsn9 -lwtcserver9 -lcommon9 -lgeneric9 /opt/oracle/product/9.2.0/rdbms/lib/defopt.o
-lknlopt `if /usr/bin/ar tv /opt/oracle/product/9.2.0/rdbms/lib/libknlopt.a | grep
xsyeolap.o > /dev/null 2>&1 ; then echo "-loraolap9" ; fi`
-lslax9 -lpls9 -lplp9 -lserver9 -lclient9 -lvsn9 -lwtcserver9 -lcommon9 -lgeneric9
-lknlopt -lslax9 -lpls9 -lplp9 -ljox9 -lserver9 -locijdbcst9 -lwwg9
`cat /opt/oracle/product/9.2.0/lib/ldflags` -lnsslb9 -lncrypt9 -lnsgr9 -lnzjs9
-ln9 -lnl9 -lnro9 `cat /opt/oracle/product/9.2.0/lib/ldflags` -lnsslb9 -lncrypt9
......
mv -f /opt/oracle/product/9.2.0/bin/oracle /opt/oracle/product/9.2.0/bin/oracleO
mv /opt/oracle/product/9.2.0/rdbms/lib/oracle /opt/oracle/product/9.2.0/bin/oracle
chmod 6751 /opt/oracle/product/9.2.0/bin/oracle



此后数据库可以以超过1.7G的SGA区设置启动:




            SQL> startup
ORACLE instance started.
Total System Global Area 2685476820 bytes
Fixed Size 454612 bytes
Variable Size 1073741824 bytes
Database Buffers 1610612736 bytes
Redo Buffers 667648 bytes
Database mounted.
Database opened.

http://www.eygle.com/archives/2005/11/oracle_howto_make_sga_17g.html

  数据库优化的讨论可以说是一个永恒的主题。资深的Oracle优化人员通常会要求提出性能问题的人对数据库做一个statspack,贴出数据库配置等等。还有的人认为要抓出执行最慢的语句来进行优化。但实际情况是,提出疑问的人很可能根本不懂执行计划,更不要说statspack了。而我认为,数据库优化,应该首先从大的方面考虑:网络、服务器硬件配置、操作系统配置、Oracle服务器配置、数据结构组织、然后才是具体的调整。实际上网络、硬件等往往无法决定更换,应用程序一般也无法修改,因此应该着重从数据库配置、数据结构上来下手,首先让数据库有一个良好的配置,然后再考虑具体优化某些过慢的语句。我在给我的用户系统进行优化的过程中,总结了一些基本的,简单易行的办法来优化数据库,算是我的三板斧,呵呵。不过请注意,这些不一定普遍使用,甚至有的会有副作用,但是对OLTP系统、基于成本的数据库往往行之有效,不妨试试。(注:附件是Burleson写的用来报告数据库性能等信息的脚本,本文用到)
  
  一.设置合适的SGA
  
  常常有人抱怨服务器硬件很好,但是Oracle就是很慢。很可能是内存分配不合理造成的。
  
  (1)假设内存有512M,这通常是小型应用。建议Oracle的SGA大约240M,其中:共享池(SHARED_POOL_SIZE)可以设置60M到80M,根据实际的用户数、查询等来定。数据块缓冲区可以大致分配120M-150M,8i下需要设置DB_BLOCK_BUFFERS,DB_BLOCK_BUFFER*DB_BLOCK_SIZE等于数据块缓冲区大小。9i 下的数据缓冲区可以用db_cache_size来直接分配。
  
  (2)假设内存有1G,Oracle 的SGA可以考虑分配500M:共享池分配100M到150M,数据缓冲区分配300M到400M。
  
  (3)内存2G,SGA可以考虑分配1.2G,共享池300M到500M,剩下的给数据块缓冲区。
  
  (4)内存2G以上:共享池300M到500M就足够啦,再多也没有太大帮助;(Biti_rainy有专述)数据缓冲区是尽可能的大,但是一定要注意两个问题:一是要给操作系统和其他应用留够内存,二是对于32位的操作系统,Oracle的SGA有1.75G的限制。有的32位操作系统上可以突破这个限制,方法还请看Biti的大作吧。
  
  二.分析表和索引,更改优化模式
  
  Oracle默认优化模式是CHOOSE,在这种情况下,如果表没有经过分析,经常导致查询使用全表扫描,而不使用索引。这通常导致磁盘I/O太多,而导致查询很慢。如果没有使用执行计划稳定性,则应该把表和索引都分析一下,这样可能直接会使查询速度大幅提升。分析表命令可以用ANALYZE TABLE 分析索引可以用ANALYZE INDEX命令。对于少于100万的表,可以考虑分析整个表,对于很大的表,可以按百分比来分析,但是百分比不能过低,否则生成的统计信息可能不准确。可以通过DBA_TABLES的LAST_ANALYZED列来查看表是否经过分析或分析时间,索引可以通过DBA_INDEXES的LAST_ANALYZED列。
  
  下面通过例子来说明分析前后的速度对比。(表CASE_GA_AJZLZ大约有35万数据,有主键)首先在SQLPLUS中打开自动查询执行计划功能。(第一次要执行\RDBMS\ADMIN\utlxplan.sql来创建PLAN_TABLE这个表)
  SQL> SET AUTOTRACE ON
  SQL>SET TIMING ON
  
  通过SET AUTOTRACE ON 来查看语句的执行计划,通过SET TIMING ON 来查看语句运行时间。
  SQL> select count(*) from CASE_GA_AJZLZ;
  COUNT(*)
  ----------
  346639
  已用时间: 00: 00: 21.38
  Execution Plan
  ----------------------------------------------------------
  0 SELECT STATEMENT Optimizer=CHOOSE
  1 0 SORT (AGGREGATE)
  2 1 TABLE ACCESS (FULL) OF 'CASE_GA_AJZLZ'
  ……………………
  请注意上面分析中的TABLE ACCESS(FULL),这说明该语句执行了全表扫描。而且查询使用了21.38秒。这时表还没有经过分析。下面我们来对该表进行分析:
  SQL> analyze table CASE_GA_AJZLZ compute statistics;
  
  表已分析。
  
  已用时间: 00: 05: 357.63
  
  然后再来查询:
  SQL> select count(*) from CASE_GA_AJZLZ;
  COUNT(*)
  ----------
  346639
  
  已用时间: 00: 00: 00.71
  Execution Plan
  ----------------------------------------------------------
  0 SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=351 Card=1)
  1 0 SORT (AGGREGATE)
  2 1 INDEX (FAST FULL SCAN) OF 'PK_AJZLZ' (UNIQUE) (Cost=351
  Card=346351)
  …………………………
  
  请注意,这次时间仅仅用了0.71秒!这要归功于INDEX(FAST FULL SCAN)。通过分析表,查询使用了PK_AJZLZ索引,磁盘I/O大幅减少,速度也大幅提升!下面的实用语句可以用来生成分析某个用户的所有表和索引,假设用户是GAXZUSR:
  SQL> set pagesize 0
  SQL> spool d:\analyze_tables.sql;
  SQL> select 'analyze table '||owner||'.'||table_name||' compute statistics;' from dba_tables where owner='GAXZUSR';
  SQL> spool off
  SQL> spool spool d:\analyze_indexes.sql;
  SQL> select 'analyze index '||owner||'.'||index_name||' compute statistics;' from dba_indexes where owner='GAXZUSR';
  SQL> spool off
  SQL> @d:\analyze_tables.sql
  SQL> @d:\analyze_indexes.sql
  
  解释:上面的语句生成了两个sql文件,分别分析全部的GAXZUSR的表和索引。如果需要按照百分比来分析表,可以修改一下脚本。通过上面的步骤,我们就完成了对表和索引的分析,可以测试一下速度的改进啦。建议定期运行上面的语句,尤其是数据经过大量更新。
  
  当然,也可以通过dbms_stats来分析表和索引,更方便一些。但是我仍然习惯上面的方法,因为成功与否会直接提示出来。
  
  另外,我们可以将优化模式进行修改。optimizer_mode值可以是RULE、CHOOSE、FIRST_ROWS和ALL_ROWS。对于OLTP系统,可以改成FIRST_ROWS,来要求查询尽快返回结果。这样即使不用分析,在一般情况下也可以提高查询性能。但是表和索引经过分析后有助于找到最合适的执行计划。
  
  三.设置cursor_sharing=FORCE 或SIMILAR
  
  这种方法是8i才开始有的,oracle805不支持。通过设置该参数,可以强制共享只有文字不同的语句解释计划。例如下面两条语句可以共享:
  
  SQL> SELECT * FROM MYTABLE WHERE NAME='tom'
  
  SQL> SELECT * FROM MYTABLE WHERE NAME='turner'
  
  这个方法可以大幅降低缓冲区利用率低的问题,避免语句重新解释。通过这个功能,可以很大程度上解决硬解析带来的性能下降的问题。个人感觉可根据系统的实际情况,决定是否将该参数改成FORCE。该参数默认是exact。不过一定要注意,修改之前,必须先给ORACLE打补丁,否则改之后oracle会占用100%的CPU,无法使用。对于ORACLE9i,可以设置成SIMILAR,这个设置综合了FORCE和EXACT的优点。不过请慎用这个功能,这个参数也可能带来很大的负面影响!
  
  四.将常用的小表、索引钉在数据缓存KEEP池中
  
  内存上数据读取速度远远比硬盘中读取要快,据称,内存中数据读的速度是硬盘的14000倍!如果资源比较丰富,把常用的小的、而且经常进行全表扫描的表给钉内存中,当然是在好不过了。可以简单的通过ALTER TABLE tablename CACHE来实现,在ORACLE8i之后可以使用ALTER TABLE table STORAGE(BUFFER_POOL KEEP)。一般来说,可以考虑把200数据块之内的表放在keep池中,当然要根据内存大小等因素来定。关于如何查出那些表或索引符合条件,可以使用本文提供的access.sql和access_report.sql。这两个脚本是著名的Oracle专家 Burleson写的,你也可以在读懂了情况下根据实际情况调整一下脚本。对于索引,可以通过ALTER INDEX indexname STORAGE(BUFFER_POOL KEEP)来钉在KEEP池中。
  
  将表定在KEEP池中需要做一些准备工作。对于ORACLE9i 需要设置DB_KEEP_CACHE_SIZE,对于8i,需要设置buffer_pool_keep。在8i中,还要修改db_block_lru_latches,该参数默认是1,无法使用buffer_pool_keep。该参数应该比2*3*CPU数量少,但是要大于1,才能设置DB_KEEP_CACHE_BUFFER。buffer_pool_keep从db_block_buffers中分配,因此也要小于db_block_buffers。设置好这些参数后,就可以把常用对象永久钉在内存里。
  
  五.设置optimizer_max_permutations
  
  对于多表连接查询,如果采用基于成本优化(CBO),ORACLE会计算出很多种运行方案,从中选择出最优方案。这个参数就是设置oracle究竟从多少种方案来选择最优。如果设置太大,那么计算最优方案过程也是时间比较长的。Oracle805和8i默认是80000,8建议改成2000。对于9i,已经默认是2000了。
  
  六.调整排序参数
  
  (1) SORT_AREA_SIZE:默认的用来排序的SORT_AREA_SIZE大小是32K,通常显得有点小,一般可以考虑设置成1M(1048576)。这个参数不能设置过大,因为每个连接都要分配同样的排序内存。
  
  (2) SORT_MULTIBLOCK_READ_COUNT:增大这个参数可以提高临时表空间排序性能,该参数默认是2,可以改成32来对比一下排序查询时间变化。注意,这个参数的最大值与平台有关系。
  
  七.调整其它几个关键的性能参数
  
  很多人认为使用oracle数据库,系统的默认参数就是最好的,其实不是这样,很多参数都需要调整,而且调整前后性能大不一样。
  
  (1) log_buffer
  
  日志缓冲区大小默认设置32k太小了,建议设置成512K或者1M。
  log_buffer=524288
  
  (2) optimizer_index_caching
  
  这个参数可以设置索引的缓冲度,范围是0到100,默认是0,可以考虑设置成90
  
  (3) optimizer_index_cost_adj
  
  这个参数是一个百分比,表明索引扫描与全表扫描的代价范围是1到1000。默认=100表名索引扫描与全表扫描代价一样。将这个参数设小表名索引代价要小于全表扫描,这样就使得使用CBO进行成本计算时更倾向于使用索引扫描。建议把这个参数设置成30到50。
  
  八.改变联机日志文件大小(一般用于oracle805)
  
  Oracle805的联机日志文件默认只有1M大小,这实在是太小了,通过查看数据库的日志,很可能发现“checkpoint not complete”之类的错误提示。这会导致系统稳定性,同样也降低了数据库性能。建议修改成10M。修改方法是删除一个组、添加一个组,直到3个组都换成新的大小。说明:这个操作需要实施人员具有较多的数据库知识,如果不太了解,最好不要试验。
  
  九.改变数据块大小(一般用于oracle805)
  
  Oracle805默认的块(DB_BLOCK_SIZE)大小是2K,太小了,因为块小,所以请求同样的数据量的时候,读的次数就要增多,导致性能低下。当然如果服务器性能比较好,还是升级Oracle更好,如果服务器配置比较差,建议改成8K。但是数据块不能直接修改,唯一的办法就是将数据导出,重新创建数据库,然后将数据导入。说明:这个操作需要实施人员具有较多的数据库知识,如果不太了解,最好不要试验。
  
  十.设置合适的表存储参数
  
  对于有很多并发写入用户的系统来说,如果系统没有经过调整,经常会有数据等待现象。这是因为9i之前的表设置的默认的自由队列freelists为1,这样就可能造成数据等待。通过查看v$waitstat,如果发现data block 或者free list类的count次数很大,则说明等待情况严重,需要增加freelists。这个参数在8i、9i中可以动态修改(需要打补丁,否则会有ORA-10620: Operation not allowed on this segment)在ORACLE805中,只能通过重新创建表来修改。
  SQL> select * from v$waitstat;
  CLASS COUNT TIME
  ------------------ ---------- ----------
  data block 11922013 342456
  sort block 0 0
  save undo block 0 0
  segment header 1 0
  free list 0 0
  
  如果测算经常有10个并发的写用户,可以把表的freelists改成10。例如下面的脚本可以把GAXZUSR用户的所有表重新设置FREELISTS的语句写在D:\FREELISTS.SQL里:
  SQL> SET PAGESIZE 0
  SQL> SPOOL D:\FREELISTS.SQL
  SQL> SELECT 'ALTER TABLE '||TABLE_NAME||' STORAGE(FREELISTS 10);' FROM DBA_TABLES WHERE OWNER=’GAXZUSR’;
  SQL>SPOOL OFF
  
  检查D:\FREELISTS.SQL,没有错误后运行修改FREELISTS:
  SQL>@D:\FREELISTS.SQL
  
  十一.重新组织表结构
  
  (1) 按照主键重新排序。
  
  数据库运行了一段时间后,可能会有很多数据,而这些数据又可能是经常按照某个字段来选取区段数据。如果我们能够把主键按照顺序重新来组织一下表,那么用主键进行的查询就会明显快很多,主要是因为经过排序后,相似的编号都放在同一个数据块里,ORACLE在进行主键范围查找的时候,就会大大减少物理块度读取数量。在对表和索引分析之后,可以通过DBA_INDEXES的CLUSTERING_FACTOR列来判断表是否需要重新排序。如果该字段的值与表的BLOCK数量差不多,则不需要重新排序,如果和表的行数差不多,则应该考虑重新组织一下了。下面的例子示意性说明怎样对表CASE_GA_AJZLZ按照主键PK_AJZLZ进行重新排序:
  
  <1> 将表CASE_GA_AJZLZ的索引、外间约束引用等找出来备用。
  SET PAGESIZE 0
  SET LINESIZE 300
  SPOOL DISABLE_CONSTRAINTS.SQL
  SELECT 'ALTER TABLE '||TABLE_NAME||' DISABLE CONSTRAINT '||CONSTRAINT_NAME||';' FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE='R' AND R_CONSTRAINT_NAME='PK_AJZLZ';
  SPOOL OFF
  SPOOL CREATE_CONSTRAINTS.SQL
  SELECT 'ALTER TABLE '||TABLE_NAME||' ADD CONSTRAINT '||CONSTRAINT_NAME||' FOREIGN KEY(CASEID) REFERENCES CASE_GA_AJZLZ(CASEID);' FROM USER_CONSTRAINTS WHERE CONSTRAINT_TYPE='R' AND R_CONSTRAINT_NAME='PK_AJZLZ';
  SPOOL OFF
  SPOOL CREATE_INDEX.SQL
  SELECT 'CREATE INDEX '||INDEX_NAME||' ON '||TABLE_NAME||'('||COLUMN_NAME||') TABLESPACE INDX ;' FROM USER_IND_COLUMNS WHERE TABLE_NAME='CASE_GA_AJZLZ' AND INDEX_NAME<>'PK_AJZLZ';
  
  <2> 创建新的表CASE_GA_AJZLZ_NEW:
  SQL> CREATE TABLE CASE_GA_AJZLZ_NEW AS SELECT
  /*+INDEX(CASE_GA_AJZLZ PK_AJZLZ) */ * FROM CASE_GA_AJZLZ ;
  
  注意,上面的注释(红颜色部分)表名按照PK_AJZLZ排序来重新组织表。
  
  <3>禁用CASE_GA_AJZLZ的外间约束,将表CASE_GA_AJZLZ TRUNCATE,然后删除之
  
  <4> 将表CASE_GA_AJZLZ_NEW更名为CASE_GA_AJZLZ
  
  SQL> ALTER TABLE CASE_GA_AJZLZ_NEW RENAME TO CASE_GA_AJZLZ;
  
  <5>创建CASE_GA_AJZLZ的所有索引、主键约束等。
  
  SQL> ALTER TABLE CASE_GA_AJZLZ ADD CONSTRAINT PK_AJZLZ PRIMARY KEY(CASEID);
  SQL> @CREATE_INDEX.SQL
  SQL> @CREATE_CONSTRAINTS.SQL
  
  (2) 将BLOB字段存储到单独的表空间中。
  
  基本上每个业务系统都有很多BLOB字段,而且很可能占据了整个数据库大小的大部分。默认情况下,BLOB字段会将4000个字节的指针与表的行存在一起,这直接会导致行迁移。而且BLOB字段会与表处于同一个表空间,这也对性能有不小的影响。从设计角度来说,BLOB字段都应该单独存储,遗憾的是我所遇到的很多系统都没有单独存储BLOB字段。如果BLOB字段占据了很大的存储,那么将BLOB字段单独存储后,带来的整体性能收益可能会非常的大。 另外BLOB字段存储子句中有一个DISABLE STORAGE IN ROW 属性,在将BLOB字段单独存放时,也应该实用该属性,这样可以有效避免行迁移。


http://publish.it168.com/2005/1118/20051118002701.shtml

Oracle9i New Features

  原文链接:
http://download-west.oracle.com/otndoc/oracle9i/901_doc/server.901/
a90117/whatsnew.htm
是编号为A90120-20文档的概括
前些天看到有人问9I的新功能,就随手翻译了一下有的地方不准确或者是错误的,大家多包涵不清楚的地方请参考文档,谢谢

Oracle9i Release 1 (9.0.1) New Features
Oracle9i brings a major new release of the Oracle database server. It includ
es features to make the database more available. More online operations reduce the need for offline maintenance. Management of the database requires less effort. Oracle9i can automatically create and manage the underlying operating system files required by the database. There is a theme of self management.
Oracle9i带来了一次Oracle数据库服务器的主要升级。它包括了可以使数据库更可靠,更多的在线操作替代了离线维护,管理数据库更有效的新特性。Oracle9i自动管理数据库需要的操作系统文件。这是自动管理的主题。

Performance is enhanced. The Database Resource Manager has new options that allow for more granular control of resources. The performance level required of a resource consumer group can be better sustained. Partitioning enhancements allow tables and indexes to be better partitioned for performance. Security enhancements are an important part of this release. Applications have available more and finer grained methods of implementing security and auditing.

性能得到增强。数据库资源管理器拥有新的选项,允许对资源进行更好的控制。一组资源消费所要求的性能水平可以得到持续满足。分区增强允许表和索引为性能更好的分区。安全增强是这次升级的重要部分。应用程序拥有更多更好的执行安全和审计的方法。

The following are summaries of the new features of Oracle9i that are discussed in this book.
下面是Oracle9i新特性的总结。

Online redefinition of tables
The new DBMS_REDEFINITION PL/SQL package provides a mechanism to redefine ta
bles online. When a table is redefined online, it is accessible to DML durin
g much of the redefinition process. This provides a significant increase in
availability compared to traditional methods of redefining tables that require tables to be taken offline.
1. 在线重定义表
新的PL/SQL包DBMS_REDEFINITION提供了在线重定义表的机制。当表被在线重定义的时候,在重定义进程中的大多数时刻对DML是可用的。与传统的要求表先离线再重新定义的方法相比,显著地提高了可用性。

ONLINE option for ANALYZE VALIDATE STRUCTURE statement
The ANALYZE statement can now perform validation while DML is ongoing within the object being analyzed.
2. ANALYZE VALIDATE STRUCTURE语句的ONLINE选项
ANALYZE语句现在可以在DML运行的时候提供确认,当目标正在分析的时候。

Controlling Archive Log
Oracle now provides a time-based means of switching the current online redo log group. In a primary/standby configuration, where all noncurrent logs of the primary site are archived and shipped to the standby database, this effectively limits the number of redo records, as measured in time, that will not be applied in the standby database.
3. 控制归档日志
Oracle现在提供一种基于时间的方法用来切换目前的在线redo log组。在primary/standby配置中,既所有主站点非当前日志都被归档并传到standby数据库中,它有效地限制了重做记录的数量,从时间上考虑,它不使用在standby database上。

Suspending a database
Oracle9i includes a database suspend/resume feature. The ALTER SYSTEM SUSPEND statement suspends a database by halting all input and output (I/O) to dat
afiles and control files. When the database is suspended all preexisting I/O
operations are allowed to complete and any new database accesses are placed in a queued state. The ALTER SYSTEM RESUME statement resumes normal databas
e operation.
4. 挂起数据库
Oracle包括数据库挂起/恢复特性。ALTER SYSTEM SUSPEND语句通过暂停所有对数据文件和控制文件的输入输出(I/O)挂起数据库。当数据库被挂起时,所有先前存在的I/9操作被允许执行完毕并且任何新的请求被放在一个状态队列中。ALTER SYSTEM RESUME语句恢复正常的数据库操作。

Quiescing a database
Oracle9i allows you to place the database into a quiesced state, where only DBA transactions, queries, or PL/SQL statements are allowed. This quiesced state allows you to perform administrative actions that cannot safely be done
otherwise. The ALTER SYSTEM QUIESCE RESTRICTED statement places a database into a quiesced state
5. 禁用数据库
Oracle9i允许拥护将数据库置于一个禁用状态,只有DBA事务、查询或者PL/SQL语句可以执行。这个状态允许用户进行在其他情况下不能保证安全的管理工作。ALTER SYSTEM QUIESCE RESTRICTED语句将数据库设置为禁用状态。

Resumable Space Allocation
Oracle provides a means for suspending, and later resuming, the execution of
large database operations in the event of space allocation failures. This enables you to take corrective action, instead of the Oracle database server returning an error to the user. After the error condition is corrected, the suspended operation automatically resumes.
6. 空间分配可恢复
当大型数据库操作在空间分配阶段失败时,Oracle提供了一种先挂起,一段时间后恢复执行的机制。它可以允许纠正操作,代替数据库返回用户一个错误。当错误状态被纠正时,挂起的操作自动恢复。

More archiving destinations
The maximum number of destinations to which you can archive the online redo
log, has been increased from 5 to 10.
7. 更多的归档目标文件
归档重做日志所用的目标文件的最大数量从5个增加到10个。

Automatic segment- space management Locally managed tablespaces allow extents to be managed automatically by Oracle. Oracle9i allows free and used space within segments stored in locally managed tablespaces to also be managed automatically. Using the SEGMENT SPACE
MANAGEMENT clause of CREATE TABLESPACE you specify AUTO or MANUAL to specify the type of segment space management Oracle will use.
8. 自动分段——空间管理
本地管理的表空间允许扩展段由Oracle自动管理。Oracle9i也允许本地表空间段中的free和used空间自动管理。使用CREATE TABLESPACE的SEGMENT SPACE MANAGEMENT子句,通过设置AUTO或MANUAL确定Oracle用来管理段空间所使用的方法。

Update of global indexes when partition maintenance is performed By default, many table maintenance operations on partitioned tables invalida
te (mark UNUSABLE) global indexes. You must then rebuild the entire global i
ndex or, if partitioned, all of its partitions. Oracle9i allows you to override this default behavior. When you specify the UPDATE GLOBAL INDEX clause in your ALTER TABLE statement for the maintenance operation, the global index is updated in conjunction with the base table operation.
9. 维护分区的时候更新全局索引
在缺省情况下,许多在分区表上进行的表维护操作使全局索引无效(标志为UNUSABLE)。用户必须重建全部的全局索引,或者在在分区的情况下,全部它的分区。Oracle9i允许用户使其无效。当用户在维护操作的ALTER TABLE语句中声明UPDATE GLOBAL INDEX子句时,全局索引和基表操作一起更新。

Multiple block sizes
Oracle now supports multiple block sizes. It has a standard block size, as s
et by the DB_BLOCK_SIZE initialization parameter, and additionally up to 4 n
onstandard block sizes. Nonstandard block sizes are specified when creating
tablespaces. The standard block size is used for the SYSTEM tablespace and most other tablespaces. Multiple block size support allows for the transporting of tablespaces with unlike block sizes between databases.
10. 块大小多样化
Oracle现在支持多种块的尺寸。数据块具有一个标准的大小,建立表空间时在DB_BLOCK_SIZE初始化参数中设置。标准块大小用于SYSTEM表空间和大多数其他表空间。多样化的块大小允许数据库间具有不同块大小的表空间传输。

Dynamic buffer cache
The size of the buffer cache subcomponent of the System Global Area is now dynamic. The DB_BLOCK_BUFFERS initialization parameter has been replaced by a new dynamic parameter, DB_CACHE_SIZE, where the user specifies the size of the buffer subcache for the standard database block size. The buffer cache now consists of subcaches when multiple block sizes are specified for the database. Up to four DB_nK_CACHE_SIZE initialization parameters allow you to specify the sizes of buffer subcaches for the additional block sizes.
11. 动态buffer cache
现在SGA区的buffer cache部分的大小是动态的。原来的初始化参数DB_BLOCK_BUFFERS被新的动态参数DB_CACHE_SIZE取代,用户可以为标准数据库块大小设置次级缓冲区。当数据库使用不同的块大小时,buffer cache由各个次级缓冲区组成。4个DB_nK_CACHE_SIZE初始化参数允许用户为其他的块尺寸设置次级缓冲。

Dynamic SGA
The initialization parameters affecting the size of SGA have been made dynamic. It is possible to alter the size of SGA dynamically through an ALTER SYSTEM SET statement.
12. 动态SGA
影响SGA大小的初始化参数被设置为动态。可以使用ALTER SYSTEM SET语句动态改变SGA的大小。

Automatic undo management
Historically, Oracle has used rollback segments to store undo. Undo is defined as information that can be used to roll back, or undo, changes to the database when necessary. Oracle now enables you to create an undo tablespace to store undo. Using an undo tablespace eliminates the complexities of managing rollback segment space, and enables you to exert control over how long undo is retained before being overwritten.
13. 自动UNDO管理
以前Oracle使用回滚段存储UNDO。UNDO定义为可以在需要的时候使用于回滚或者撤消数据库的改变的信息。Oracle现在允许用户建立一个undo表空间用来存储undo。使用undo表空间消除了管理回滚段空间的复杂性,并且允许用户精确地控制undo被重写前所保留的时间。

Oracle managed files
The Oracle managed files feature of Oracle9i eliminates the need for you to directly manage the files comprising an Oracle database. Through the DB_CREA
TE_FILE_DEST and DB_CREATE_ONLINE_LOG_DEST_n initialization parameters, you specify the file system directory to be used for a particular type of file c
omprising a tablespace, online redo log file, or control file. Oracle then e
nsures that a unique file, an Oracle-managed file, is created and deleted when no longer needed.
14. Oracle文件管理
Oracle9i的文件管理功能不再需要用户直接管理组成Oracle数据库的文件。通过DB_CREATE_FILE_DEST和DB_CREATE_ONLINE_LOG_DEST_n初始化参数,用户可以指定组成表空间,在线重做日志或控制文件所使用的文件所在的系统目录。Oracle确保自己管理的文件可以建立,并在不需要时删除。

Automatic deletion of datafiles Oracle9i provides an option to automatically remove a tablespaces's operating system files (datafiles) when the tablespace is dropped using the DROP TABLESPACE statement. A similar option for the ALTER DATABASE TEMPFILE statement, causes deletion the operating system files associated with a temporary file.
15. 文件自动删除
Oracle9i提供了在执行DROP TABLESPACE语句删除表空间时,自动删除操作系统数据文件的选项。与之类似的ALTER DATABASE TEMPFILE语句,可以删除相关的临时文件。


Metadata API
A new PL/SQL package, DBMS_METADATA.GET_DDL, allows you to obtain metadata (
in the form of DDL used to create the object) about a schema object
16. Metadata API
一个新的PL/SQL包,DBMS_METADATA.GET_DDL,允许用户获得一个概要对象的元数据(以
建立这个对象的DDL形式)。

External tables
Oracle9i allows you read-only access to data in external tables. External tables are defined as tables that do not reside in the database, and can be in any format for which an access driver is provided. The CREATE TABLE ... ORG
ANIZATION EXTERNAL statement specifies metadata describing the external table. Oracle currently provides the ORACLE_LOADER access driver which provides data mapping capabilities that are a subset of the SQL*Loader control file syntax.
17. 外部表
Oracle9i允许用户只读访问外部表中的数据。外部表定义为不在数据库中的表,以任何可以使用的驱动所能提供的形式。CREATE TABLE ... ORGANIZATION EXTERNAL语句定义描述外部表的元数据。Oracle现在提供ORACLE_LOADER访问驱动,以提供数据映射能力,作为SQL*Loader控制文件语法的子集。

Constraint enhancements
Enhancements to the USING INDEX clause of CREATE TABLE or ALTER TABLE allow
you to specify the creation or use of a specific index when a unique or primary key constraint is created or enabled. Additionally, you can prevent the dropping of the index enforcing a unique or primary key constraint when the constraint is dropped or disabled.
18. 约束增强
对CREATE TABLE和ALTER TABLE的USING INDEX子句增强允许用户在唯一或主键约束建立或改变时建立或使用一个指定的索引。另外,用户可以防止当删除或禁止一个索引时强制删除唯一或主键约束。

Server parameter file
Oracle has traditionally stored initialization parameters in a text initiali
zation parameter file, often on a client machine. Starting with Oracle9i, you can elect to maintain initialization parameters in a server parameter file, which is a binary parameter file stored on the database server. Initialization parameters stored in a server parameter file are persistent, in that any changes made to the parameters while an instance is running persist across
instance shutdown and startup.
19. 服务器参数文件
以前Oracle将初始化参数存储在客户机上的一个文本文件中。从Oracle9i开始,用户可以选择在服务器参数文件中维护初始化参数,它是一个存储在数据库服务器中的二进制参数文件。存储在服务器参数文件中的初始化参数是不变的,??????

Default temporary tablespace
The new DEFAULT TEMPORARY TABLESPACE clause of the CREATE DATABASE statement
allows you to create a default temporary tablespace at database creation time. This tablespace is used as the default temporary tablespace for users who are not otherwise assigned a temporary tablespace.
20. 默认临时表空间
CREATE DATABSE语句的新子句DEFAULT TEMPORARY TABLESPACE允许用户在建立数据库时建立默认临时表空间。作为没有指定临时表空间用户的缺省临时表空间。

Setting the database time zone
The CREATE DATABASE statement now has a SET TIME_ZONE clause that allows you to set the time zone of the database as a displacement from UTC (Coordinated Universal Time--formerly Greenwich Mean Time). Oracle normalizes all TIMES TAMP WITH LOCAL TIME ZONE data to the time zone of the database when the data is stored on disk. Additionally, a new session parameter TIME_ZONE has bee
n added to the SET clause of ALTER SESSION.
21. 设置数据库时区
现在使用CREATE DATABASE的SET TIME_ZONE子句允许用户设置数据库时区为UTC的偏移。当数据存储到磁盘上时,Oracle用本地数据库时区的数据格式化所有时间戳。另外,新的会话参数TIME_ZONE加入ALTER SESSION的SET子句中。

Transaction Naming
Oracle now allows you to assign a name to a transaction. The transaction name is helpful in resolving in-doubt distributed transactions, and replaces a
COMMIT COMMENT.
22. 事务命名
现在Oracle允许用户为事务指定一个名字。事务名称有助于解决分布事务的不确定性,并取代COMMIT的注释。

Oracle Database Configuration Assistant changes
The Oracle Database Configuration Assistant has been redesigned. It now prov
ides templates, which are saved definitions of databases, from which you can
generate your database. Oracle provides templates, or you can create your own templates by modifying existing ones, defining new ones, or by capturing the definition of an existing database.When creating a database with the Database Configuration Assistant, you can either initially include, or later add as an option, Oracle's new Sample Schemas. These schemas are the basis for many of the examples used in Oracle documentation.
23. Oracle Database Configuration Assistant 变化
Oracle Database Configuration Assistant经过了重新设计。它提供了存储数据库精确定义的模板,通过模板用户可以生成自己的数据库。Oracle提供了模板,用户也可以通过改变现有的,定义新的,或者获得现有数据库的精确定义来建立自己的模板。当使用数据库配置向导建立数据库时,用户可以在开始或之后加入一个选项——Oracle的新方案实例。这些方案是Oracle文档中很多例子的基础。

Monitoring index usage
A MONITORING USAGE clause has been added for the ALTER INDEX statement. It allows you to monitor an index to determine if it is actively being used.
24. 监视索引使用
在ALTER INDEX语句中加入了MONITORING USAGE子句。它允许用户监视索引是否被有效地使用。

List partitioning Oracle introduces list partitioning, which enables you to specify a list of discrete values for the partitioning column in the description for each part
ition. The list partitioning method is specifically designed for modeling data distributions that follow discrete values. This cannot be easily done by range or hash partitioning.
25.列表分区(List partitioning)
Oracle引入列表分区,使得用户能够为各个分区指定一组离散的值。列表分区方法是专门为离散数据模型设计的,原来使用范围和哈希分区很难做到。

Hash partitioning of index-organized tables In this release, support has been added for partitioning index-organized tables by the hash method. Previously, they could be partitioned, but only by the range method.
26. 索引组织表的哈希分区
在这个版本中,增加了使用哈希方法分区的索引组织表。在这之前只能使用排列方法分区。

Dynamic job queue processes
The job queue process creation has been made dynamic so that only the required number of processes are created to execute the jobs that are ready for execution. A job queue coordinator background process (CJQ) dynamically spawns Jnnn processes to execute jobs.
27. 动态任务序列进程
动态的建立任务序列进程,这样只有需要的进程数量被在任务准备执行时建立。一个任务序列后台调度进程产生Jnnn进程用来执行任务

New in the Database Resource Manager for Oracle9i
The following new functionality has been added to the Database Resource Mana
ger:Ability to create an active session pool. This pool consists of a specified
maximum number of user sessions allowed to be concurrently active within a g
roup of users. Additional sessions beyond the maximum are queued for execution, but you can specify a timeout period, after which queued jobs will abort.Automatic switching of users from one group to another group based on administrator defined criteria. If a member of a particular group of users creates a session that executes for longer than a specified amount of time, that session can be automatically switched to another group of users with different resource requirements. Ability to prevent the execution of operations that are estimated to run for a longer time than a predefined limit Ability to create an undo pool. This pool consists of the amount of undo space that can be consumed in by a group of users.
28. Oracle9i数据库资源管理器新特性下列新功能被加入到数据库资源管理器中:
1) 建立动态进程池功能。由指定的最大数量的一组活动用户进程组成。其他超过这个最大值的进程将加入等待执行的队列,但是用户可以指定一个过期时间,超过后队列中的任务将被取消。
2) 基于管理员定义的标准自动将用户从一个组切换到另一个组。如果一个组中的某个用户建立的进程超过了指定的时间,这个进程可以被自动切换到另一个拥有不同资源的组中。
3) 能够防止操作运行时间过长,超过一个预定的限制。
4) 能够建立undo池。由一组用户使用的undo空间组成。

Proxy authentication and authorization
Oracle9i enables you to authorize a middle-tier server to act on behalf of a
client. The GRANT CONNECT THROUGH clause of the ALTER USER statement specifies this functionality. You can also specify roles that the middle tier is permitted to activate when connecting as the client.
29. 代理认证和授权
Oracle9i允许用户为客户端授权使用一个中间层服务器。ALTER USER语句的GRANT CONNECT THROUGH子句实现这个功能。用户也可以指定中间层作为客户端连接时允许使用的规则。

Application roles Oracle provides a mechanism by which roles granted to application users are enabled using a designated PL/SQL package. This feature introduces the IDENTIFIED USING package clause for the CREATE ROLE statement.
30. 应用程序角色Oracle提供一种机制,使得被授予应用程序角色的用户可以是使用一个指定的PL/SQL包。这个特性在CREATE ROLE语句的IDENTIFIED USING packet子句中引入。

Fine-grained auditing
In Oracle's traditional auditing methods, a fixed set of facts is recorded in the audit trail. Audit options can only be set to monitor access of objects or privileges. A new PL/SQL package, DBMS_FGA, allows applications to implement fine-grained auditing of data access based on content.
31. 细致审计
在Oracle以前的审计方法中,一套固定的因素记录在审计记录中。审计选项只能被设置为监视对象和权限的访问情况。一个新的PL/SQL包,DBMS_FGA,允许应用程序执行基于内容数据访问的细致审计。

New in LogMiner for Release 9.0.1 LogMiner release 9.0.1 has added support for many new features. Some of the new features work with any redo log files from an Oracle 8.0 or later database. Other features only work with redo log files produced on Oracle9i or later.
32. LogMiner9.0.1版新特性
LogMiner9.0.1版增加了对很多新特性的支持。其中一部分可以应用于Oracle8及以后版本数据库的重做日志文件。其他的只能用于Oracle9i和后来版本。

New Features for Redo Log Files Generated by Oracle9i or Later
1) Oracle9i及后续版本重做日志文件的新特性
For any redo log files generated by Oracle9i or later, LogMiner now provides
support for the following:
对于任何Oracle9i和后来版本生成的重做日志文件,LogMiner现在提供下列支持:
Index clusters
索引簇
Chained and migrated rows
链接的和可移动的行
Direct path inserts (with ARCHIVELOG mode enabled)
直接路径插入(在ARCHIVELOG模式有效时)
Extracting the data dictionary into the redo log files.
将数据字典摘取到重做日志文件中。
Using the online catalog as the data dictionary.
使用在线目录作为数据字典。
Tracking of all data definition language (DDL) operations, which enables you
to monitor schema evolution.
跟踪所有数据定义语言(DDL),使用户可以监视schema的变化。
Viewing user-executed DDL in the SQL_REDO column. Information regarding the
original database user is also returned.
在SQL_REDO栏中看到用户执行的DDL。关于原来数据库用户的信息也被改变。
Generating SQL_REDO and SQL_UNDO with primary key information for updates. T
hat is, updated rows are identified by primary keys and ROWIDs (provided sup
plemental logging is enabled), thereby making it easier to apply the stateme
nts to a different database.
为更新而产生SQL_REDO和SQL_UNDO关于主键的信息。这样更新行是通过主键和ROWID,因此使在另一个数据库上应用这些语句变得更容易。

New Features for Redo Log Files Generated by Oracle Release 8.0 or Later
2) Oracle8.0及后续版本重做日志文件的新特性
For any redo log files generated by Oracle release 8.0 or later, LogMiner now provides support for the following:
对于任何Oracle8.0和后来版本生成的重做日志文件,LogMiner现在提供下列支持:
Limiting V$LOGMNR_CONTENTS data to rows belonging to committed transactions
only. This option enables you to filter out rolled back transactions and transactions that are in progress.
将V$LOGMNR_CONTENTS中数据限制在属于已提交的事务行上。这个选项允许用户过滤回滚事务和正在进行的事务。
Performing queries based on actual data values in the redo log files.
在重做日志文件中执行基于确定值的查询。


http://www.chinaitlab.com/www/news/article_show.asp?id=1127

Problem:


I'm getting errors when I compile this procedure.

create or replace procedure send_message
(v_message in varchar2)
is s integer;
begin
dbms_pipe.pack_message(v_message);
s:=dbms_pipe.send_message('DEMO_PIPE');
if s<>0
then raise_application_error(-20200,'ERROR'||to_char(s)||'sending on pipe');
end if;
end send_message;
 
 The errors are ..
   PLS-00201: identifier 'SYS.DBMS_PIPE' must be declared
   PL/SQL: Statement ignored
   PL/SQL: Statement ignored
   PLS-00201: identifier 'SYS.DBMS_PIPE' must be declared
So whats wrong? Thanks

 

Resolvent:


sql>connect sys as sysdba
sql>password: change_on_install
sql> grant execute on dbms_pipe to public;
sql>create public synonym dbms_pipe for dbms_pipe;(if the synonym doesn't exist)
sql>conn scott/tiger
sql>execute the package

 

ps:the all package execute privilege is included in role EXECUTE_CATALOG_ROLE

 


一、简介

在过去,如果用户误删/更新了数据后,作为用户并没有什么直接的方法来进行恢复,他们必须求助DBA来对数据库进行恢复,到了Oracle9i,这一个难堪局面有所改善。Oracle 9i中提供了一项新的技术手段--闪回查询,用户使用闪回查询可以及时取得误操作前的数据,并可以针对错误进行相应的恢复措施,而这一切都无需DBA干预。

下面我们通过一个例子来具体说明闪回查询的用法。

二、示例

1、使用闪回查询前必须确定下面两个参数:

UNDO_MANAGEMENT = AUTO

undo_retention = 1200; #这个时间可以随便设,他表示在系统中保留提交了的UNDO信息的时间,1200就是保留20分钟。

2、使用闪回查询

SQL> conn sys/sys as sysdba

Connected.

SQL> create user flash identified by flash;

User created.

SQL> grant connect, resource to flash;

Grant succeeded.

SQL> grant execute on dbms_flashback to flash;

Grant succeeded.

SQL> conn flash/flash

Connected.

SQL> set echo on

SQL> create table t (a varchar2(10));

Table created.

SQL> insert into t values('gototop');

1 row created.

SQL> insert into t values('www.ncn.cn');

1 row created.

SQL> /

SQL> select * from t;

A

----------

gototop

www.ncn.cn

www.ncn.cn

SQL> set time on

15:00:22 SQL>

15:00:22 SQL>

15:00:23 SQL> delete t where a='gototop';

1 row deleted.

15:00:35 SQL> commit;

Commit complete.

15:00:38 SQL> select * from t;

A

----------

www.ncn.cn

www.ncn.cn

15:08:22 SQL> execute DBMS_FLASHBACK.ENABLE_AT_TIME(to_date('2003-05-16 15:00:00'));

PL/SQL procedure successfully completed.

15:09:02 SQL> select * from t;

A

----------

gototop

www.ncn.cn

www.ncn.cn

15:16:43 SQL> execute DBMS_FLASHBACK.DISABLE;

PL/SQL procedure successfully completed.

15:17:05 SQL> select * from t;

A

----------

www.ncn.cn

www.ncn.cn

3、使用闪回查询恢复数据:

15:36:55 SQL> select * from t;

no rows selected

15:36:57 SQL> insert into t values('www.ncn.cn');

1 row created.

15:37:15 SQL> /

1 row created.

15:37:16 SQL> /

1 row created.

15:37:17 SQL> /

1 row created.

15:37:18 SQL> /

1 row created.

15:37:19 SQL> commit;

Commit complete.

15:37:21 SQL> /

Commit complete.

15:37:22 SQL> /

Commit complete.

15:37:23 SQL> select * from t;

A

----------

www.ncn.cn

www.ncn.cn

www.ncn.cn

www.ncn.cn

www.ncn.cn

www.ncn.cn

6 rows selected.

15:37:28 SQL>

15:38:44 SQL> delete t;

6 rows deleted.

15:38:50 SQL> commit;

Commit complete.

15:38:53 SQL> commit;

Commit complete.

15:38:54 SQL> /

Commit complete.

15:38:57 SQL> declare

15:39:28 2 cursor flash_recover is

15:39:28 3 select * from t;

15:39:28 4 t_recode t%rowtype;

15:39:28 5 begin

15:39:28 6 DBMS_FLASHBACK.ENABLE_AT_TIME(to_date('2003-05-16 15:37:23'));

15:39:28 7 open FLASH_RECOVER;

15:39:28 8 DBMS_FLASHBACK.DISABLE;

15:39:28 9 loop

15:39:28 10 FETCH FLASH_RECOVER INTO t_recode;

15:39:28 11 EXIT WHEN FLASH_RECOVER%NOTFOUND;

15:39:28 12 insert into t values (t_recode.a);

15:39:28 13 end loop;

15:39:28 14 CLOSE FLASH_RECOVER;

15:39:28 15 commit;

15:39:28 16 end;

15:39:28 17 /

PL/SQL procedure successfully completed.

15:39:28 SQL> 15:39:28 SQL>

15:39:31 SQL> select * from t;

A

----------

www.ncn.cn

www.ncn.cn

www.ncn.cn

www.ncn.cn

www.ncn.cn

15:39:35 SQL>

我们可以已经恢复了5条纪录,但我们要恢复的6条纪录,为什么会少一条呢?原因就在下面。

三、局限性

1、闪回查询是基于SCN的,虽然我执行的是:

DBMS_FLASHBACK.ENABLE_AT_TIME(to_date('2003-05-16 15:37:23'));

但Oracle并不会精确的这个时间点,而是ROUND DOWN到最近的一次SCN,然后从这个SCN开始进行恢复。而Oracle 9i是每五分钟记录一次SCN的,并将SCN和对应时间的映射做个纪录。时间和 SCN 的对应关系记录在 sys.smon_scn_time 中,估计是 smon 每五分钟更新一次该表,且该表总记录保持为 1440 条,也就是说该表保持 5 天的记录,所以有后面 5 天的限制,如果要用精确恢复,还是用基于 SCN 的恢复比较好。

这正是上面我们进行恢复时少了一条的原因。因此如果使用DBMS_FLASHBACK.ENABLE_AT_TIME来进行恢复,为了避免恢复失败,我可以先等5分钟,然后再进行恢复。

使用DBMS_FLASHBACK.ENABLE_AT_TIME进行恢复还有一个缺点,那就是在Oracle 9i中SCN和对应时间的映射信息只会保留5天,因此我们无法通过DBMS_FLASHBACK.ENABLE_AT_TIME来恢复5天前的数据。如果你想使用闪回查询来恢复5天前的数据,你必须自己来确定需要恢复的SCN,然后使用

DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(SCN_NUMBER); 来定位你的恢复时间点,下面是使用方法:

15:58:58 SQL> VARIABLE SCN_SAVE NUMBER;

16:13:43 SQL> EXECUTE :SCN_SAVE := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER;

PL/SQL procedure successfully completed.

16:13:50 SQL> print SCN_SAVE;

SCN_SAVE

----------

2.1202E+11

16:28:34 SQL> execute DBMS_FLASHBACK.ENABLE_AT_SYSTEM_CHANGE_NUMBER(:SCN_SAVE);

PL/SQL procedure successfully completed.

另外,在使用DBMS_FLASHBACK.ENABLE_AT_TIME前,你必须设定你的NLS_DATE_FORMAT的精确程度,Oracle默认的是精确到天,如果你不设定,像上面的例子你不会得到预期结果。

2、如果你使用sysdate和DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER来获取时间点或者SCN值,你必须注意它们取得都是当前的时间点和SCN值。

3、你只能在事务开始时进入闪回查询模式,如果之前有DML操作,则必须COMMIT。

4、闪回查询无法恢复到表结构改变之前,因为闪回查询使用的当前的数据字典。


补充:
    DBMS_FLASHBACK 包将整个 SESSION 恢复到相应的时间点,恢复过去之后不能做任何操作,如果要获得恢复的数据,只能用前面的游标实现,或者可以用简单的 AS OF 的方法:
    Create table flashback as
      select * from t1 as of scn/timestamp XXXX


http://www.chinaitlab.com/www/news/article_show.asp?id=12393
http://www.chinaunix.net/jh/19/286443.html

  索引可以加快查询的速度,但索引会占用许多存储空间,在插入和删除行的时候,索引还会引入额外的开销,因此确保索引得到有效利用是我们很关注的一个问题。在Oracle9i之前,要知道一个索引是否被使用是困难的,而Oracle 9i中提供了一个有效的监控方法:ALTER INDEX MONITORING USAGE。下面我讲详细说明如何使用该方法来鉴别未使用的索引。

一、我们先通过一个例子具体说明“ALTER INDEX MONITORING USAGE”的使用方法:

1、建测试表

create table test(id number(3),name varchar2(10));

insert into test values(1,'aaaaaaaa');

insert into test values(2,'www.ncn.cn');

insert into test values(3,'aadfaaaa');

insert into test values(4,'gototop');

insert into test values(5,'shenzhen');

insert into test values(6,'china');

commit;

alter table test add (constraint test_pk primary key (id));

2、查询v$object_usage(因为没有监视,所以还看不到内容)

column index_name format a12

column monitoring format a10

column used format a4

column start_monitoring format a19

column end_monitoring format a19

select index_name,monitoring,used,start_monitoring,end_monitoring from v$object_usage;

SQL> l

1* select index_name,monitoring,used,start_monitoring,end_monitoring from v$object_usage

SQL> /

no rows selected

Elapsed: 00:00:00.00

3、开始监控索引的使用情况

SQL> alter index test_pk monitoring usage;

Index altered.

Elapsed: 00:00:00.05

4、查询v$object_usage(可以看到正监视中)

SQL> select index_name,monitoring,used,start_monitoring,end_monitoring from v$object_usage;

INDEX_NAME MONITORING USED START_MONITORING END_MONITORING

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

TEST_PK YES NO 05/15/2003 13:28:22

Elapsed: 00:00:00.00

5、使用索引进行查询

SQL> set autotrace on explain

SQL> select * from test where id = 2;

ID NAME

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

2 www.ncn.cn

Elapsed: 00:00:00.00

Execution Plan

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

0 SELECT STATEMENT Optimizer=CHOOSE

1 0 TABLE ACCESS (BY INDEX ROWID) OF 'TEST'

2 1 INDEX (UNIQUE SCAN) OF 'TEST_PK' (UNIQUE)

SQL> set autotrace off

SQL> /

ID NAME

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

2 www.ncn.cn

Elapsed: 00:00:00.00

SQL>

从上我们可以看到确实使用了索引。

6、查询v$object_usage(可以看到索引被使用过,但目前还处于被监视过程中)

SQL> select index_name,monitoring,used,start_monitoring,end_monitoring from v$object_usage;

INDEX_NAME MONITORING USED START_MONITORING END_MONITORING

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

TEST_PK YES YES 05/15/2003 13:28:22

Elapsed: 00:00:00.00

7、停止监视,并查询v$object_usage

SQL> alter index test_pk nomonitoring usage;

Index altered.

Elapsed: 00:00:05.03

SQL> select index_name,monitoring,used,start_monitoring,end_monitoring from v$object_usage;

INDEX_NAME MONITORING USED START_MONITORING END_MONITORING

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

TEST_PK NO YES 05/15/2003 13:28:22 05/15/2003 13:40:00

Elapsed: 00:00:00.64

到此为止,监视结束,MONITORING为NO,END_MONITORING给出了时间戳。

二、v$object_usage视图解释

从上面的例子中我们可以看出,索引的监视信息都是存在在v$objec_usage视图中,该视图的定义如下:

CREATE OR REPLACE VIEW SYS.V$OBJECT_USAGE

(

INDEX_NAME,

TABLE_NAME,

MONITORING,

USED,

START_MONITORING,

END_MONITORING

)

AS

select io.name, t.name,

decode(bitand(i.flags, 65536), 0, 'NO', 'YES'),

decode(bitand(ou.flags, 1), 0, 'NO', 'YES'),

ou.start_monitoring,

ou.end_monitoring

from sys.obj$ io, sys.obj$ t, sys.ind$ i, sys.object_usage ou

where io.owner# = userenv('SCHEMAID')

and i.obj# = ou.obj#

and io.obj# = ou.obj#

and t.obj# = i.bo#

/

COMMENT ON TABLE SYS.V$OBJECT_USAGE IS

'Record of index usage'

/

GRANT SELECT ON SYS.V$OBJECT_USAGE TO "PUBLIC"

/

下面是该视图列的描述:

INDEX_NAME: sys.obj$.name 中的索引名字

TABLE_NAME: sys.obj$obj$name 中的表名

MONITORING: YES (索引正在被监控), NO (索引没有被监控)

USED: YES (索引已经被使用过), NO (索引没有被使用过)

START_MONITORING: 开始监控的时间

END_MONITORING: 结束监控的时间

所有被使用过至少一次的索引都可以被监控并显示到这个视图中。

三、监视数据库中所有索引的使用情况

1、生成开始/结束监视索引的SQL脚本:

set heading off

set echo off

set feedback off

set pages 10000

spool start_index_monitor.sql

select 'alter index '||owner||'.'||index_name||' monitoring usage;'

from dba_indexes

where owner in ('YOUR','PROD_DB','OWNER','LIST');

spool off

set heading on

set echo on

set feedback on

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

set heading off

set echo off

set feedback off

set pages 10000

spool stop_index_monitor.sql

select 'alter index '||owner||'.'||index_name||' nomonitoring usage;'

from dba_indexes

where owner in ('YOUR','PROD_DB','OWNER','LIST');

spool off

set heading on

set echo on

set feedback on

2、进行监视并查询结果:

 

在业务量比较多的一天上班时运行start_index_monitor.sql,下班前运行stop_index_monitor.sql,之后就可以在各用户自己的v$object_usage视图中看到该SCHEMA下的索引使用情况了:

SQL> conn t/t

Connected.

SQL> select index_name,table_name,used

2 from v$object_usage

3 where used='NO';

INDEX_NAME TABLE_NAME USED

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

TEST_PK TEST NO

1 row selected.

SQL>

3、改进结果查寻方法

你也许已经注意到,上面查询结果是需要我们单独查询各SCHEMA中的v$object_usage,其实我们可以通过给v$object_usage视图添加一个owner列来创建一个可以存储所有SHCEMA的v$object_usage视图,不妨叫做v$all_object_usage,定义如下:

CREATE OR REPLACE VIEW SYS.V$ALL_OBJECT_USAGE

(

OWNER,

INDEX_NAME,

TABLE_NAME,

MONITORING,

USED,

START_MONITORING,

END_MONITORING

)

AS

select u.name, io.name, t.name,

decode(bitand(i.flags, 65536), 0, 'NO', 'YES'),

decode(bitand(ou.flags, 1), 0, 'NO', 'YES'),

ou.start_monitoring,

ou.end_monitoring

from sys.obj$ io, sys.obj$ t, sys.ind$ i, sys.object_usage ou, sys.user$ u

where i.obj# = ou.obj#

and io.obj# = ou.obj#

and t.obj# = i.bo#

and io.owner# = u.user#

/

COMMENT ON TABLE SYS.V$ALL_OBJECT_USAGE IS

'Record of all index usage'

/

GRANT SELECT ON SYS.V$ALL_OBJECT_USAGE TO "PUBLIC"

/

CREATE PUBLIC SYNONYM V$ALL_OBJECT_USAGE

FOR SYS.V$ALL_OBJECT_USAGE

/

之后就可以从这个视图中查询相关信息了,下面是示例过程:

----------www.ncn.cn---------示例过程--开始--------------------

SQL> conn sys/sys as sysdba

Connected.

SQL> desc v$all_object_useage

ERROR:

ORA-04043: object v$all_object_useage does not exist

SQL> @/oracle/oracle9/cyx/all_object_usage.sql

SQL> CREATE OR REPLACE VIEW SYS.V$ALL_OBJECT_USAGE

2 (

3 OWNER,

4 INDEX_NAME,

5 TABLE_NAME,

6 MONITORING,

7 USED,

8 START_MONITORING,

9 END_MONITORING

10 )

11 AS

12 select u.name, io.name, t.name,

13 decode(bitand(i.flags, 65536), 0, 'NO', 'YES'),

14 decode(bitand(ou.flags, 1), 0, 'NO', 'YES'),

15 ou.start_monitoring,

16 ou.end_monitoring

17 from sys.obj$ io, sys.obj$ t, sys.ind$ i, sys.object_usage ou, sys.user$ u

18 where i.obj# = ou.obj#

19 and io.obj# = ou.obj#

20 and t.obj# = i.bo#

21 and io.owner# = u.user#

22 /

View created.

SQL> COMMENT ON TABLE SYS.V$ALL_OBJECT_USAGE IS

2 'Record of all index usage'

3 /

Comment created.

SQL> GRANT SELECT ON SYS.V$ALL_OBJECT_USAGE TO "PUBLIC"

2 /

Grant succeeded.

SQL> CREATE PUBLIC SYNONYM V$ALL_OBJECT_USAGE

2 FOR SYS.V$ALL_OBJECT_USAGE

3 /

Synonym created.

SQL> @start_index_monitor.sql

SQL> alter index T.INDEX_CFS monitoring usage;

Index altered.

SQL> alter index T.TEST_PK monitoring usage;

Index altered.

SQL> conn t/t

Connected.

SQL> select * from test where id <5;

ID NAME

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

1 aaaaaaaa

2 www.ncn.cn

3 aadfaaaa

4 gototop

4 rows selected.

SQL> conn sys/sys as sysdba

Connected.

SQL> @stop_index_monitor.sql

SQL> alter index T.INDEX_CFS nomonitoring usage;

Index altered.

SQL> alter index T.TEST_PK nomonitoring usage;

Index altered.

SQL> @report_index_usage.sql

SQL> set pages 10000

SQL> set pagesize 200

SQL> set linesize 100

SQL> spool report_index_usage.txt

SQL> ttitle center "--Report of Unused Indexes--"

SQL> select owner,table_name,index_name,used

2 from v$all_object_usage

3 where used='NO';

--Report of Unused Indexes--

OWNER TABLE_NAME INDEX_NAME USED

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

T CFS INDEX_CFS NO

1 row selected.

SQL> spool off


http://www.chinaitlab.com/www/news/article_show.asp?id=12392

  Oracle9i引入了具有延续性的初始化参数文件SPFILE(Server Parameter FILE),所谓延续性是指对初始化参数的在线修改可以直接作用到参数文件中,这样所有被修改的参数将永久生效。

SPFILE有以下几个显著优点:

1、“ALTER SYSTEM”所设定的参数可以直接保存在SPFILE中,不像以前那样需要手工更改参数文件才可以使改动永久生效;

2、RMAN支持对SPFILE的备份,在这之前是无法做到使用RMAN来备份初始化参数文件的;

3、可以实现在本地没有远程数据库的INIT.ORA拷贝的时候,远程启动数据库;

4、在RAC的多个实例之间可以共享一个SPFILE

下面我们将详细讨论这几个新特性。

1、SPFILE概述

SPFILE是一个很小的二进制文件,有ORACLE服务器自动维护,位于ORACLE服务器端($ORACLE_HOME/dbs/spfile.ora),因为ORACLE默认就是此SPFILE,所以我们可以通过SQL*PLUS或OEM无需指定初始化参数在客户端远程启动数据库。(8i可以吗?)

2、SPFILE的创建、导出与更新

SYSDBA/SYSOPER(我不知道别人是不是使用SYSOPER,反正我是从来不用这个^_^)可以在数据库处于任何状态下(IDLE/NOMOUNT/MOUNT/OPEN),通过下面的语句来创建一个SPFILE:

CREATE SPFILE[='SPFILE_NAME'] FROM PFILE[='PFILE_NAME'];

而将这个语句反过来就可以通过SPFILE来建立PFILE,ORACLE称之为SPFILE的导出。

CREATE PFILE[='PFILE_NAME'] FROM SPFILE[='SPFILE_NAME'];

导出的文件格式如下:

......

*.background_dump_dest='/oracle/app/oracle/admin/ora9/bdump'

*.compatible='9.2.0.0.0'

*.control_files='/dev/rcon1','/dev/rcon2','/dev/rcon3'

*.core_dump_dest='/oracle/app/oracle/admin/ora9/cdump'

*.db_block_size=8192

*.db_cache_size=3072000000#changed at 20030425

*.db_domain=''

*.db_file_multiblock_read_count=16

*.db_name='ora9'

......

导出SPFILE由两个主要的用途:批量修改参数、作为SPFILE的一种备份方式(如果数据库采用RMAN备份方式,我们可以直接用RMAN来备份SPFILE)。

当批量修改(编辑PFILE)完成后,我们可以通过重新创建SPFILE来实现对SPFILE的更新。

3、参数的修改

对于单个参数的修改,我们可以通过下面的语句来完成:

ALTER SYSTEM SET PARAMETER=value [COMMENT='COMMENT TEXT'][SCOPE=MEMORY|SPFILE|BOTH]

通过SCOPE选项实现了对初始化参数更改的永久性。

对于动态参数,可以加上DEFERRED关键字来标明更改仅对以后的SESSIONS起作用。

SQL> alter system set sort_area_size=104800

2 comment='temporary seting' scope=spfile;

System altered.

4、启动时参数文件的读取顺序

数据库启动时STARTUP默认使用初始化参数文件的顺序是:

[指定的PFILE -->] SPFILE --> $ORACLE_HOME/dbs/PFILE

当然在PFILE中也可以指向SPFILE。

5、读取SPFILE参数设置

我们可以从v$spparameter, v$parameter, v$parameter2中获得相关参数的信息,也依旧可以使用SHOW SGA。

SQL> select name,value,update_comment from v$spparameter

2 where name='sort_area_size';

NAME VALUE UPDATE_COMMENT

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

sort_area_size 104800 temporary seting

6、共享初始化参数文件

在9i RAC中,多个实例可以共享同一个初始化参数文件,而各实例所特有的参数值可以通过在参数前加上实例名称来标示:

hawk19:sort_area_size=104800

hawk29:sort_area_size=102400

关于SPFILE差不多就这些内容了,请继续关注gototop为了你带来的其他Oracle 9i的文章,也欢迎各位网友来信与我讨论和Oracle相关的一些问题。


http://www.chinaitlab.com/www/news/article_show.asp?id=12391

  在Oracle 9i里,一个很显著的新特性就是引入了自动的回滚段管理,当使用了AUM (Automatic Undo Management)时,为了区别,名称也由原来的ROLLBACK SEGMENT(回滚段)变成UNDO SEGMENT(撤销段),相对应的是UNDO TABLESPACE。当然我们也可以继续使用传统的MANUAL方式来管理撤销段。

一、初始化参数

使用下面的参数来设置有ORACLE自动管理撤销段:

UNDO_MANAGEMENT = AUTO

ORACLE会自动完成撤销段的创建、删除以及ONLINE/OFFLINE,而DBA将无法干预所有以上操作。

如果想自己来管理回滚段可以将UNDO_MANAGEMENT设成MANUAL(DEFAULT就是MANUAL的)。虽然我们可以在UNDO表空间上创建回滚段,但ORACLE并不建议这样做。

当使用了AUM,我们唯一需要做的就是至少创建一个UNDO表空间,我们可以创建多个UNDO表空间,然后使用下面的参数来指定具体使用哪个。

UNDO_TABLESPACE =UNDORBS1

SQL> l

1* select name ,value from v$parameter where name like 'undo%'

SQL> /

 

undo_management MANUAL

undo_tablespace UNDOTBS1

undo_suppress_errors FALSE

undo_retention 10800

创建多个UNDO表空间的好处是,我们可以根据不同的应用在不同大小的UNDO表空间之间进行切换。

二、UNDO表空间的创建

1、在建数据库是创建UNDO表空间,具体方法参见本人写的Oracle 9i安装、建库与升级。文章在www.ncn.cn上有下载。

2、我们也可以通过下面的语句来创建:

Create undo tablespace undotbs2 datafile ‘/dev/rundotbs2_1.dbf’ size 100m;

三、UNDO表空间特性

1、UNDO表空间默认就是LOCAL管理方式:

SQL> l

1 select TABLESPACE_NAME, CONTENTS,EXTENT_MANAGEMENT, ALLOCATION_TYPE,

2 SEGMENT_SPACE_MANAGEMENT

3* from dba_tablespaces where contents='UNDO'

SQL> /

 

TABLESPACE_NAME CONTENTS EXTENT_MANAGEMENT ALLOCATION_TYPE SEGMENT_SPAC

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

UNDOTBS1 UNDO LOCAL SYSTEM MANUAL

UNDOTBS2 UNDO LOCAL SYSTEM MANUAL

2、除撤销段外,我们不能在UNDO表空间上作其他操作:

SQL> create table gototop_t1(c1 number) tablespace undotbs1;

create table gototop_t1(c1 number) tablespace undotbs1

*

ERROR 位于第 1 行:

ORA-30022: Cannot create segments in undo tablespace

SQL> l

1* create rollback segment ncn_rb1 tablespace undotbs1

SQL> /

create rollback segment ncn_rb1 tablespace undotbs1

*

ERROR 位于第 1 行:

ORA-30019: Illegal rollback Segment operation in Automatic Undo mode

3、一个实例职能使用一个UNDO表空间:

除了在INIT.ORA中指定UNDO表空间外,我们还可以使用下面的语句来在线更改实例所用的UNDO表空间:

SQL> alter system set undo_tablespace=undotbs2;

系统已更改。

四、撤销段的特性

1、撤销段自动创建:

Ø n个撤销段(n基于SESSIONS参数,后面会详细讲)

Ø 名字为_SYSSMUn$

Ø OWNER为PUBLIC(在RAC配置中有用)

Ø 选择AUM后,无法手动管理

SQL> l

1 select owner,segment_name,tablespace_name,status

2* from dba_rollback_segs order by 4

SQL> /

 

OWNER SEGMENT_NAME TABLESPACE_NAME STATUS

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

PUBLIC _SYSSMU1$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU2$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU3$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU5$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU7$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU9$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU10$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU8$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU6$ UNDOTBS1 OFFLINE

PUBLIC RB1_CYX1 UNDOTBS1 OFFLINE

PUBLIC RB1_CYX UNDOTBS1 OFFLINE

SYS RB1_08 UNDOTBS1 OFFLINE

SYS RB1_07 UNDOTBS1 OFFLINE

SYS RB1_05 UNDOTBS1 OFFLINE

SYS RB1_04 UNDOTBS1 OFFLINE

SYS RB1_03 UNDOTBS1 OFFLINE

SYS RB1_02 UNDOTBS1 OFFLINE

SYS RB1_01 UNDOTBS1 OFFLINE

SYS RB3_06 UNDOTBS3 OFFLINE

SYS RB3_05 UNDOTBS3 OFFLINE

SYS RB3_04 UNDOTBS3 OFFLINE

SYS RB3_03 UNDOTBS3 OFFLINE

SYS RB3_02 UNDOTBS3 OFFLINE

SYS RB3_01 UNDOTBS3 OFFLINE

SYS RB2 INDX OFFLINE

PUBLIC _SYSSMU4$ UNDOTBS1 OFFLINE

SYS SYSTEM SYSTEM ONLINE

PUBLIC _SYSSMU11$ UNDOTBS2 ONLINE

PUBLIC _SYSSMU12$ UNDOTBS2 ONLINE

PUBLIC _SYSSMU13$ UNDOTBS2 ONLINE

PUBLIC _SYSSMU14$ UNDOTBS2 ONLINE

PUBLIC _SYSSMU15$ UNDOTBS2 ONLINE

PUBLIC _SYSSMU16$ UNDOTBS2 ONLINE

PUBLIC _SYSSMU17$ UNDOTBS2 ONLINE

PUBLIC _SYSSMU18$ UNDOTBS2 ONLINE

PUBLIC _SYSSMU19$ UNDOTBS2 ONLINE

PUBLIC _SYSSMU20$ UNDOTBS2 ONLINE

 

已选择37行。

 

SQL>

因为我在系统上作测试,之前手动建过回滚段,所以上面返回结果显一般多。

2、只有活动的UNDO表空间上的撤销段和系统回滚段是ONLINE的,其他的撤销段都是OFFLINE的。

这一点从上面的输出中可以清楚地看到。

不过,也不一定一开始所有的撤销段都会ONLINE的,这要依赖于初始化参数SESSIONS的值,默认SESSIONS = 1.1 * PROCESSES + 5,他决定了系统的并发用户数。下面的实验可以让你对这一情况有个明确的认识。

我们将SESSIONS调小后重起数据库,可以看到活动的UNDO表空间UNDOTBS1上共10个撤销段,但只ONLINE了5个。

SQL> show parameter sessions

 

NAME TYPE VALUE

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

java_max_sessionspace_size integer 0

java_soft_sessionspace_limit integer 0

license_max_sessions integer 0

license_sessions_warning integer 0

logmnr_max_persistent_sessions integer 1

mts_sessions integer 0

sessions integer 27

shared_server_sessions integer 0

SQL> select owner,segment_name,tablespace_name,status

2 from dba_rollback_segs;

 

OWNER SEGMENT_NAME TABLESPACE_NAM STATUS

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

SYS SYSTEM SYSTEM ONLINE

PUBLIC _SYSSMU1$ UNDOTBS1 ONLINE

PUBLIC _SYSSMU2$ UNDOTBS1 ONLINE

PUBLIC _SYSSMU3$ UNDOTBS1 ONLINE

PUBLIC _SYSSMU4$ UNDOTBS1 ONLINE

PUBLIC _SYSSMU5$ UNDOTBS1 ONLINE

PUBLIC _SYSSMU6$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU7$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU8$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU9$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU10$ UNDOTBS1 OFFLINE

PUBLIC _SYSSMU11$ UNDOTBS2 OFFLINE

PUBLIC _SYSSMU12$ UNDOTBS2 OFFLINE

PUBLIC _SYSSMU13$ UNDOTBS2 OFFLINE

PUBLIC _SYSSMU14$ UNDOTBS2 OFFLINE

PUBLIC _SYSSMU15$ UNDOTBS2 OFFLINE

PUBLIC _SYSSMU16$ UNDOTBS2 OFFLINE

PUBLIC _SYSSMU17$ UNDOTBS2 OFFLINE

PUBLIC _SYSSMU18$ UNDOTBS2 OFFLINE

PUBLIC _SYSSMU19$ UNDOTBS2 OFFLINE

PUBLIC _SYSSMU20$ UNDOTBS2 OFFLINE

SYS RB1_01 UNDOTBS1 OFFLINE

SYS RB1_02 UNDOTBS1 OFFLINE

SYS RB1_03 UNDOTBS1 OFFLINE

SYS RB1_04 UNDOTBS1 OFFLINE

SYS RB1_05 UNDOTBS1 OFFLINE

SYS RB1_07 UNDOTBS1 OFFLINE

SYS RB1_08 UNDOTBS1 OFFLINE

PUBLIC RB1_CYX UNDOTBS1 OFFLINE

PUBLIC RB1_CYX1 UNDOTBS1 OFFLINE

SYS RB2 INDX OFFLINE

SYS RB3_01 UNDOTBS3 OFFLINE

SYS RB3_02 UNDOTBS3 OFFLINE

SYS RB3_03 UNDOTBS3 OFFLINE

SYS RB3_04 UNDOTBS3 OFFLINE

SYS RB3_05 UNDOTBS3 OFFLINE

SYS RB3_06 UNDOTBS3 OFFLINE

 

已选择37行。

 

SQL>

 

五、AUM和RAC

UNDO空间管理方式在RAC中会有一些特殊的要求。

1、RAC所有实例应使用相同UNDO管理模式。

2、不同的实例应使用不同的UNDO表空间,如果没有明确设置不同的UNDO_TABLESPACE参数,每个实例会自动使用第一个可用的UNDO表空间。

 

六、其它说明

1、当在AUTO模式下进行MANUAL操作时,我们可以设置初始化参数UNDO_SUPPRESS_ERRORS = TRUE来禁止所有报错信息,慎用!

SQL> l

1* alter rollback segment "_SYSSMU6$" online

SQL> /

alter rollback segment "_SYSSMU6$" online

*

ERROR 位于第 1 行:

ORA-30019: Illegal rollback Segment operation in Automatic Undo mode

SQL> alter system set UNDO_SUPPRESS_ERRORS = TRUE;

系统已更改。

SQL> alter rollback segment "_SYSSMU6$" online;

回退段已变更。

SQL>

这条语句看起来是操作成功了,但实际上什么事也没有干!

SQL> select owner,segment_name,tablespace_name,status

2 from dba_rollback_segs where status ='ONLINE';

OWNER SEGMENT_NAME TABLESPACE_NAM STATUS

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

SYS SYSTEM SYSTEM ONLINE

PUBLIC _SYSSMU1$ UNDOTBS1 ONLINE

PUBLIC _SYSSMU2$ UNDOTBS1 ONLINE

PUBLIC _SYSSMU3$ UNDOTBS1 ONLINE

PUBLIC _SYSSMU4$ UNDOTBS1 ONLINE

PUBLIC _SYSSMU5$ UNDOTBS1 ONLINE

已选择6行。

SQL>

 

2、和手动删除了回滚段一样,查询事务信息如果位于已删除的UNDO表空间时,而快照又比UNDO表空间的DROP-SCN旧,同样会报ORA-01555 "snapshot too old (rollback segment too small)"错。

 

七、个人看法

无论是叫做ROLLBACK SEGMENT(回滚段)也好,还是叫做UNDO SEGMENT(撤销段)也好,作为用户,我们最关心的是给我们到底带来什么好处。正如Oracle所宣传的那样,自动管理确实给用户减轻了不少管理工作,但是作为企业级应用,我们不仅要考虑管理的复杂性,更要考虑它的性能问题,而在我们所进行的项目测试过程中,发现自动管理并不理想。

也就是说,自动管理是以性能为代价来减少管理的复杂性,这无疑会给用户以鸡肋的感觉。到目前为止我还没有发现一个合理解释,不知道在下一个版本中会不会在性能上有个很大的提高。

在这种情况下,是否采用自动管理?如何选择完全看你自己了。


http://www.chinaitlab.com/www/news/article_show.asp?id=12390

  我们都知道在9i之前,要想获得建表和索引的语句是一件很麻烦的事。我们可以通过export with rows=no来得到,但它的输出因为格式的问题并不能直接拿来用。而另一种方法就是写复杂的脚本来查询数据字典,但这对于一稍微复杂的对象,如IOT和嵌套表等,还是无法查到。

从数据字典中获得DDL语句是经常要用的,特别是在系统升级/重建的时候。在Oracle 9i中,我们可以直接通过执行dbms_metadata从数据字典中查处DDL语句。使用这个功能强大的工具,我们可以获得单个对象或整个SCHEMA的DDL语句。最好不过的是因为它使用起来很简单。

1、获得单个表和索引DDL语句的方法:

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

set heading off;

set echo off;

Set pages 999;

set long 90000;

 

spool get_single.sql

select dbms_metadata.get_ddl('TABLE','SZT_PQSO2','SHQSYS') from dual;

select dbms_metadata.get_ddl('INDEX','INDXX_PQZJYW','SHQSYS') from dual;

spool off;

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

下面是输出。我们只要把建表/索引语句取出来在后面加个分号就可以直接运行了。

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

SQL> select dbms_metadata.get_ddl('TABLE','SZT_PQSO2','SHQSYS') from dual;

 

CREATE TABLE "SHQSYS"."SZT_PQSO2"

( "PQBH" VARCHAR2(32) NOT NULL ENABLE,

"ZJYW" NUMBER(10,0),

"CGSO" NUMBER(10,0) NOT NULL ENABLE,

"SOLS" VARCHAR2(17),

"SORQ" VARCHAR2(8),

"SOWR" VARCHAR2(8),

"SOCL" VARCHAR2(6),

"YWHM" VARCHAR2(10),

"YWLX" VARCHAR2(6)

) PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING

STORAGE(INITIAL 1048576 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)

TABLESPACE "DATA1"

 

 

SQL> select dbms_metadata.get_ddl('INDEX','INDXX_PQZJYW','SHQSYS') from dual;

 

CREATE INDEX "SHQSYS"."INDXX_PQZJYW" ON "SHQSYS"."SZT_PQSO2" ("ZJYW")

PCTFREE 10 INITRANS 2 MAXTRANS 255

STORAGE(INITIAL 1048576 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645

PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT)

TABLESPACE "DATA1"

 

 

SQL>

SQL> spool off;

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

2、获得整个SCHEMA DDL语句的方法:

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

set pagesize 0

set long 90000

set feedback off

set echo off

spool get_schema.sql

connect shqsys/shqsys@hawk1;

SELECT DBMS_METADATA.GET_DDL('TABLE',u.table_name)

FROM USER_TABLES u;

SELECT DBMS_METADATA.GET_DDL('INDEX',u.index_name)

FROM USER_INDEXES u;

spool off;

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

需要注意的是,当我们的表中有外健(参照约束)时,我们需要判别参照表之间的顺序,确保重建时按照合理的顺序进行。你可以通过查询dba_constraints and dba_cons_columns来确定各表之间的顺序,不再详述。


http://www.chinaitlab.com/www/news/article_show.asp?id=12389

关于排序、sort_area_size、临时表空间

简单陈述一下:

针对每个session,排序首先会使用sort_area_size ,如果不足则会使用临时表空间。但这里面又到底是怎么一个过程呢?下面阐述一下,也许对大家有用处(如果有什么不清楚或者不恰当的地方欢迎大家探讨)

假设sort_area_size = 100k,正好能盛下100条记录进行排序

当排序记录小于等于100条,ok,所有排序在内存中进行,很快
但若超过100条,则会使用临时表空间(利用磁盘进行)
我们选取一个临界值来说明,假设需要排序的记录有10010条

这个时候我们进行的排序会分为101组进行
每读100条进行一次小组排序,然后写入磁盘,第101组只有10条,排序后也写入磁盘

这是进行第二次排序,这次排序将在前100小组里面各抽取一条进行排序。《按照我个人的猜测,应该是排好后每写入一条入磁盘则将该记录所在小组重新抽取一条出来进行排序(这时是有序记录组里面所以很快)》。当这个过程完成后,这时所需要的磁盘空间大约为 实际记录存储空间的2倍(这也是多数书上提到的排序空间大约是记录空间的2倍的原因)

由于还剩下10条记录,于是这10条记录需要跟前面排序的10000条记录进行排序合并,这个代价也是相当大的!

所以,我们通常推荐,假如你需要排序的记录最大为100万条,则sort_area_size最小要能装下1000条,否则如上面的例子,那多余的10条,仅仅10条将会带来巨大的代价!

如果,设置的极度不合理的情况下,排序记录达到了 sort_area_size所能容纳的三次方以上,比如上面例子中排序需要100万记录
那么同样的,重复这个过程,当每一万条记录如上排序后,再如上从这100小组(每组10000条记录)各抽一条进行排序……

在这个过程中,磁盘的消耗和时间的代价大家都应该有个感性认识了
所以,我们建议: sprt_area_size 所能容纳记录数至少大于排序记录数的 平方根

oracle文档
http://download-west.oracle.com/docs/cd/A87861_01/NT817EE/index.htm

http://www.chinaitlab.com/www/news/article_show.asp?id=5978

在9i之前,如果一个数据库用户没有被指定默认临时表空间,那么oracle就会使用system表空间作为该用户的临时表空间,这是很危险的。在9i里面,database可以被指定一个默认临时表空间。这样如果数据库用户没有被明确指定临时表空间,oracle 9i就会自动指定database的默认临时表空间作为该用户的临时表空间。
  
   我们可以通过下面的语句来查询数据库的默认临时表空间:
  
  SQL> select * from database_properties where property_name = 'DEFAULT_TEMP_TABLESPACE';
   
       

   默认临时表空间的限制:
  
  1. 默认临时表空间必须是TEMPORARY的:
  
    SQL> alter database default temporary tablespace tools;
  
    alter database default temporary tablespace tools
  
    *
  
    ERROR at line 1:
  
    ORA-12902: default temporary tablespace must be SYSTEM or of TEMPORARY type
  
   2. 默认临时表空间一旦被指定,将无法在改成PERMANET:
  
    SQL> alter tablespace temp2 permanent;
  
    alter tablespace temp2 permanent
  
    *
  
    ERROR at line 1:
  
    ORA-12904: default temporary tablespace cannot be altered to PERMANENT type
  
  3. 在删除默认临时表空间必须先重新指定默认临时表空间:
  
    SQL> drop tablespace temp including contents and datafiles;
  
    drop tablespace temp including contents and datafiles
  
    *
  
    ERROR at line 1:
  
    ORA-12906: cannot drop default temporary tablespace
  
    SQL> create tablespace TEMP2
  
     2 datafile '/data1/ora9data/temp2_01.dbf' 
  
     3 size 100k TEMPORARY;
  
    Tablespace created.
  
    SQL> alter database default temporary tablespace TEMP2;
  
    Database altered.
  
    SQL> drop tablespace temp including contents and datafiles;
  
    Tablespace dropped.
  
   4. 默认临时表空间无法OFFLINE:
  
    SQL> alter tablespace temp offline;
  
    alter tablespace temp offline
  
    *
  
    ERROR at line 1:
  
    ORA-12905: default temporary tablespace cannot be brought OFFLINE
  
   5. 用户的临时表空间必须是TEMPORARY的(在9i之前没有这个限制,可以是PERMANENT): 
  
    SQL> alter user scott temporary tablespace TOOLS;
  
    alter user scott temporary tablespace TOOLS
  
    *
  
    ERROR at line 1:
  
    ORA-12911: permanent tablespace cannot be temporary tablespace
  
    SQL> create tablespace temp2 
  
     2 datafile '/data1/ora9data/temp2_01.dbf' 
  
     3 size 100k temporary;
  
    Tablespace created.
  
    SQL> alter user scott temporary tablespace temp2;
  
    User altered.
  
   6. 如果删除了用户的临时表空间,而这个临时表空间又不是数据库的默认临时表空间(如果是数据库的默认临时表空间是删不掉的),用户的临时表空间不会自动转换到数据库的默认临时表空间上:
  
    SQL> select tablespace_name, contents from dba_tablespaces where tablespace_name like 'TEMP%';
   
             
  
    SQL> drop tablespace TEMP2 including contents and datafiles;
  
    Tablespace dropped.
  
    SQL> select TEMPORARY_TABLESPACE from dba_users where username='SCOTT';
  
    TEMPORARY_TABLESPACE
  
    ------------------------------
  
    TEMP2

Create Table 建表时,Storage 含义


  • 系统环境:
      1、操作系统:Windows 2000
      2、数据库: Oracle 8i R2 (8.1.6) for NT 企业版
      3、安装路径:C:\ORACLE


  • 解释:

可用于:表空间、回滚段、表、索引、分区、快照、快照日志
































































参数名称 缺省值 最小值 最大值 说明
INITIAL 5(数据块) 2(数据块) 操作系统限定 分配给Segment的第一个Extent的大小,以字节为单位,这个参数不能在alter语句中改变,如果指定的值小于最小值,则按最小值创建。
NEXT 5(数据块) 1(数据块) 操作系统限定 第二个Extent的大小等于NEXT的初值,以后的NEXT值=前一NEXT大小乘以(1+PCTINCREASE/100),如果指定的值小于最小值,则按最小值创建。
如果在alter语句中改变NEXT的值,则下一个分配的Extent将具有指定的大小,而不管上一次分配的Extent大小和PCTINCREASE参数值。
MINEXTENTS 1(Extent)
回滚段为2个Extent
1(Extent)
回滚段为2个Extent
操作系统限定 Segment第一次创建时分配的Extent数量
MAXEXTENTS 根据数据块大小而定 1(Extent)
回滚段为2个Extent
无限制 随着Segment中数据量的增长,最多可分配的Extent数量
PCTINCREASE 50%


(Oracle816中为0%)
0% 操作系统限定 指定第三个及其后的Extent相对于上一个Extent所增加的百分比,
如果PCTINCREASE为0,则Segment中所有新增加的Extent的大小都相同,等于NEXT的值,
如果PCTINCREASE大于0,则每次计算NEXT的值(用上面的公式),
PCTINCREASE不能为负数。
创建回滚段时,不可指定此参数,回滚段中此参数固定为0。
OPTIMAL ---- 不能小于回滚段初始分配空间 操作系统限定 仅与回滚段有关,当回滚段因为增长、扩展而超过此参数的设定范围时,Oracle系统会根据情况动态地重新分配Extents,试图收回多分配的Extent。
FREELISTS 1 1 数据块大小限制 只能在CREATE TABLE、CLUSTER、INDEX中指定FREELISTS和FREELIST GROUPS参数。
模式对象中每一个自由列表组中自由列表的数量
FREELIST GROUPS 1 1 取决于Oracle并行实例的数量 用户创建的数据库对象的自由列表组的数量,只有用OPS并行服务器选项时才使用这一参数,一个实例对应一个组。
BUFFER_POOL ---- ---- ---- 给模式对象定义缺省缓冲池(高速缓存),该对象的所有块都存储在指定的高速缓存中,对于表空间或回滚段无效。


    建议PCTINCREASE参数设置为0,可使碎片最小化,使每一个Extent都相同(等于NEXT值)

    一旦建立了某个对象,它的INITIAL和MINEXTENTS参数不能修改(Oracle 816中可修改MINEXTENTS参数)

    对于NEXT和PCTINCREASE的任何修改都只影响后来分配的那些Extent

    在分配一个新Extent时,系统直接按NEXT的值分配一个Extent,
    然后用公式:前一NEXT值*(1+PCTINCREASE/100) 计算出下一个应该分配的Extent的大小,
    并把计算结果保存到相关数据字典的NEXT_EXTENT列上,做为下一个应该分配的Extent的大小。

    CREATE TABLE test(a number)
    STORAGE(
    INITIAL 100K
    NEXT 100K
    MINEXTENTS 2
    MAXEXTENTS 100
    PCTINCREASE 100);

    解释:
    初始给test表分配两个Extent,
    第一个Extent是100K,因INITIAL=100K
    第二个Extent是100K,因NEXT=100K
    如果因表内数据增长,需要分配第三个Extent,因PCTINCREASE是100,则
    第三个Extent是200K=100K+100K
    第四个Extent是400K=200K+200K


    可通过数据字典表DBA_TABLES、ALL_TABLES、USER_TABLES查看参数设置情况,如:
    select table_name,initial_extent,next_extent,min_extents,max_extents,pct_increase from user_tables;

    TABLE_NAME INITIAL_EXTENT NEXT_EXTENT MIN_EXTENTS MAX_EXTENTS PCT_INCREASE
    ---------- -------------- ----------- ----------- ----------- ------------
    TEST 106496 212992 2 100 100


http://www.chinaitpower.com/A200507/2005-07-27/177759.html


http://www.chinaitlab.com/www/news/article_show.asp?id=37456

整理的 OCI 文档,抛砖引玉

| 1 Comment

网上很少有OCI的中文文档,一般英文文档大家可能看了也不太顺,我整理了一份,写了一些常用的OCI函数,供大家参考。
因为无法加附件,只好把内容贴上来了
一.        Oracle oci工具包安装:
$ORACLE_HOME\BIN:执行文件和help文件
$ORACLE_HOME\OCI\INCLUDE:头文件
$ORACLE_HOME\OCI\LIB\BC:  for Borlanf C++的OCI库
$ORACLE_HOME\OCI\LIB\MSVC:  for MS Visual C++的OCI库

如果是unix下,对于ORACLE8i,则OCI库在$ORACLE_HOME/lib下,如果是9i,则在$ORACLE_HOME/lib32下,库文件名一般为libclntsh.so
1.        创建OCI环境即创建和初始化OCI工作环境,其他的OCI函数需要OCI环境才能执行。
2.        需要申请的句柄类型:
OCI环境句柄: OCI_HTYPE_ENV—它定义所有OCI函数的环境调用环境,是其他句柄的父句柄。(由OCIEnvInit或OCIEnvCreate生成)
错误句柄:OCI_HTYPE_ERROR—作为一些OCI函数的参数,用来记录这些OCI函数操作过程中所产生的错误,当有错误发生时,可用COIErrorGet()来读取错误句柄 中记录的错误信息。
服务器环境句柄:OCI_HTYPE_SVCCTX—定义OCI调用的服务器操作环境,它包含服务器、用户会话和事务三种句柄。
服务器句柄:OCI_HTYPE_SERVER—标识数据源,它转换为与服务器的物理连接。
用户会话句柄:OCI_HTYPE_SESSION—定义用户角色和权限及OCI调用的执行环境。
事务句柄:OCI_HTYPE_TRANS—定义执行SQL操作的事务环境,事务环境中包含用户的会话状态信息。
语句句柄:OCI_HTYPE_STMT—是一个标识SQL语句或PL/SQL块,以及其相关属性的环境。
Bind/Define句柄:属于语句句柄的子句柄,由OCI库隐式自动生成。用户不需要自己再申请,OCI输入变量存储在bind 句柄中,输出变量存储在定义句柄中

 3.        句柄属性包括:
服务器环境句柄属性:(OCI_HTYPE_SVCCTX)
OCI_ATTR_SERVER—设置/读取服务环境的服务器环境属性
         OCI_ATTR_SESSION—设置/读取服务环境的会话认证环境属性
               OCI_ATTR_TRANS—设置/读取服务环境的事务环境属性
用户会话句柄属性:(OCI_HTYPE_SESSION)
OCI_ATTR_USERNAME—设置会话认证所使用的用户名
          OCI_ATTR_PASSWORD—设置会话认证所使用的用户口令
服务器句柄:(OCI_HTYPE_SEVER)
OCI_ATTR_NOBLOCKING_MODE—设置/读取服务器连接:=TRUE时服务器连接设置为非阻塞方式
语句句柄:(OCI_HTYPE_STMT)
OCI_ATTR_ROW_COUNT—只读,为当前已处理的行数,其default=1
OCI_ATTR_STMT_TYPE—读取当前SQL语句的类型:
Eg : OCI_STMT_BEGIN
       OCI_STMT_SELECT   OCI_STMT_INSERT   
OCI_STMT_UPDATE  OCI_STMT_DELETE
                          OCI_ATTR_PARAM_COUNT—返回语句选择列表中的列数
4.        关于输出变量定义:如果在语句执行前就知道select语句的选择列表结构,则定义输出操作可在调用 OCISTMTExecute前进行,如果查询语句的参数为用户动态输入的,则必须在执行后定义。
5.        OCI函数返回值:
OCI_SUCCESS –函数执行成功 (=0)
OCI_SUCCESS_WITH_INFO –执行成功,但有诊断消息返回,可能是警告信息
OCI_NO_DATA—函数执行完成,但没有其他数据
OCI_ERROR—函数执行错误
OCI_INVALID_HANDLE—传递给函数的参数为无效句柄,或传回的句柄无效
OCI_NEED_DATA—需要应用程序提供运行时刻的数据
OCI_CONTINUE—回调函数返回代码,说明回调函数需要OCI库恢复其正常的处理操作
OCI_STILL_EXECUTING—服务环境建立在非阻塞模式,OCI函数调用正在执行中。
6.        OCI连接有二种方式:Blocking(阻塞方式)和non_Blocking(非阻塞方式),阻塞方式就是当调用 OCI操作时,必须等到此OCI操作完成后服务器才返回客户端相应的信息,不管是成功还是失败。非阻塞方式是当客户端提交OCI操作给服务器后,服务器立即返回OCI_STILL_EXECUTING信息,而并不等待服务端的操作完成。
   
   
  对于non-blocking方式,应用程序若收到一个OCI函数的返回值为 OCI_STILL_EXECUTING时必须再次对每一个OCI函数的返回值进行判断,判断其成功与否。
  可通过设置服务器属性为OCI_ATTR_NONBLOCKING_MODE来实现。系统默认方式为阻塞模式.
7.        OCI函数设置的模式有:
  OCI_DEFUALT:使用OCI默认的环境
  OCI_THREADED:线程环境下使用OCI
  OCI_OBJECT:对象模式
  OCI_SHARED:共享模式
  OCI_EVENTS
  OCI_NO_UCB
  OCI_ENV_NO_MUTEX:非互斥访问模式
  其中模式可以用逻辑运算符进行迭加,将函数设置成多多种模式:如mode=OCI_SHREADED| OCI_OBJECT

8.        当应用进程与服务器断开连接时,程序没有使用OCITransCommit()进行事务的提交,则所有活动的事务会自动回滚。
9.        OCI重定义数据类型
             typedef unsigned char  ub1;   
typedef   signed char  sb1;
                typedef unsigned short    ub2;  
typedef   signed short    sb2;
                typedef unsigned int  ub4;   
typedef   signed int  sb4;  
typedef         ub4      duword;   
typedef         sb4      dsword;   
typedef         dsword   dword;

10.        在SQL语句准备后,可以用OCIAttrSet(0设置该语句的类型属性OCI_ATTR_STMT_TYPE,以后可读取语句属性,根据属性分别进行处理。
11.        批量绑定输入和定义输出参数:将数据存入一个静态数据组中。一次执行可以提交或读取多行记录值。
12.        结合占位符和指示器变量:
占位符:在程序中,一些SQL语句需要在程序运行时才能确定它的语句数据,在设计时可用一个占位符来代替,当程序运行时,在它准备好语句后,必须为每个占位符指定一个变量,即将占位符与程序变量地址结合,执行时,Oracle就从这些变量中读取数据,并将它们与SQL语句一起传递给Oracle服务器执行。OCI结合占位符时,它将占位符与程序变量关联起来,并同时要指出程序变量的数据类型和数据长度。
如:select * from test where name=:p1 and age>;:p2
:p1和:p2为占位符

指示器变量:由于在Oracle中,列值可以为NULL,但在C语言中没有NULL值,为了能使OCI程序表达NULL列值,OCI函数允许程序为所执行语句中的结合变量同时关联一个指示符变量或指示符变量数组,以说明所结合的占位符是否为NULL或所读取的列值是否为NULL,以及所读取的列值是否被截取。
除SQLT_NTY(SQL Named DataType)外,指示符变量或指示符变量数组的数据类型为sb2,其值说明:
作为输入变量时:(如insert ,update语句中)
 =-1:OCI程序将NULL赋给Oracle表的列,忽略占位符结合的程序变量值
>;=0:应用程序将程序变量值赋给指定列
                作为输出变量时:(如select语句中)
                 =-2:所读取的列数据长度大于程序变量的长度,则被截取。
                 =-1:所读取的值为NULL,输出变量的值不会被改变。
                =0:数据被完整读入到指定的程序变量中
                >0:所读取的列数据长度大于程序变量的长度,则被截取,指示符变量值为所读取数据被截取前的实际长度
三.        OCI函数说明
注:红色为输入参数   蓝色为输出参数  ,否则为输入/出参数

示例以下面结构作为说明
   sword     swResult;
        OCIBind*  hBind;
  OCIDefine*  hDefine;
OCIStmt      *stmtp
OCIError     *errhp;
OCIStmt       *stmtp
OCISvcCtx  * svchp
OCIEnv * envhpp;
OCISession * usrhp;
sb2                sb2aInd[30]; //指示器变量,用于取可能存在空值的字段
Typedef strcut
{
char tname[40];
int age;
} t_std;
typedef struct
{
        sb2     sb2_tname[100];
        sb2     sb2_age[100];
} stdInd_T;  //指示器数组
typedef struct
{
        ub2     ub2_tname[100];
       ub2     ub2_age[100];
} stdLen_T; //字段长度

t_std tstd[100];  //数组变量,用于批量操作
stdInd_T tstdInd;
stdLen_T tstdLen;
stdLen_T tstdRet;

t_std std;

各函数数明
1.创建OCI环境
sword OCIEnvCreate(  
OCIEnv **envhpp,  //OCI环境句柄指针
                ub4 mode, //初始化模式:OCI_DEFAULT/OCI_THREADED 等
                CONST dvoid *ctxp,
                CONST dvoid *(*malicfp)(dvoid *ctxp,size_t size),
                        CONST dvoid *(ralocfp)(dvoid *ctxp,dvoid *memptr,size_t newsize),
                CONST void *(*mfreefp)(dvoid *ctxp,dvoid *memptr),
                Size_t xstramemsz,
                Dvoid **usrmempp
        )
eg :
  swResult = OCIEnvCreate(&envhpp, OCI_DEFAULT, NULL, NULL, NULL, NULL, 0, NULL);
       
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
                return FALSE;

sword OCIInitialize (
                ub4           mode,
                              CONST dvoid   *ctxp,
                              CONST dvoid   *(*malocfp)   (/* dvoid *ctxp,  size_t size _*/),
                             CONST dvoid   *(*ralocfp) (/*_ dvoid *ctxp, dvoid *memptr, size_t newsize _*/),
                              CONST void    (*mfreefp) (/*_ dvoid *ctxp, dvoid *memptr _*/)
        );

sword OCIEnvInit (
                OCIEnv    **envhpp,
                           ub4       mode,
                                   size_t    xtramemsz,
                           dvoid     **usrmempp
         );
注:
在8i以后,可用OCIEnvCreate一个函数就可以初始化环境了,相当于OCIInitialize+ OCIEnvInit
       
2.申请/释放句柄
   sword OCIHandleAlloc(
                        CONST dvoid *parenth,  //新申请句柄的父句柄,一般为OCI环境句柄
                        Dvoid **hndlpp,   //申请的新句柄
                        Ub4 type, type,  //句柄类型
                        Size_t xtramem_sz,   //申请的内存数
                        Dvoid **usrmempp  //申请到的内存块指针
                )
注:
  一般需要申请的句柄有:
               服务器句柄OCIServer, 句柄类型OCI_HTYPE_SERVER
错误句柄OCIError,用于捕获OCI错误信息, 句柄类型OCI_HTYPE_ERROR       
事务句柄OCISession, 句柄类型OCI_HTYPE_SESSION
上下文句柄OCISvcCtx, 句柄类型OCI_HTYPE_SVCCTX
SQL语句句柄OCIStmt, 句柄类型OCI_HTYPE_STMT
eg: 申请一个错误句柄OCIError
swResult = OCIHandleAlloc(envhpp, (dvoid *)& errhp, OCI_HTYPE_ERROR, 0, NULL);
        if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
        {
               
                return FALSE;
        }
  
释放句柄
  sword OCIHandleFree(
                        dvoid *hndlp,  //要释放的句柄
                        ub4 type   //句柄类型
                )

eg:
OCIHandleFree(stmtp, OCI_HTYPE_STMT)
3.读取/设置句柄属性
  sword OCIAttrSet(
                dvoid *trgthndlp,  //需设置的句柄名
                ub4  trghndltyp,        //句柄类型
                dvoid *attributep, //设置的属性名
                ub4 size,        //属性值长度
                ub4 attrtype,     //属性类型
                OCIError *errhp   //错误句柄
        )
注:一般要设置的属性有:
  服务器实例:
句柄类型OCI_HTYPE_SVCCTX,属性类型OCI_ATTR_SERVER
        连接数据的用户名:
   句柄类型OCI_HTYPE_SESSION,属性类型OCI_ATTR_USERNAME
用户密码
     句柄类型OCI_HTYPE_SESSION,属性类型OCI_ATTR_PASSWORD
事务:  
   句柄类型OCI_HTYPE_SVCCTX,属性类型OCI_ATTR_SESSION

eg:设置用户名和密码
char username[20],passwd[20];
  strcpy(username,”tiger”)
strcpy(passwd,”cotton”)
swResult = OCIAttrSet(usrhp, OCI_HTYPE_SESSION,  (text*) username, strlen(username),
OCI_ATTR_USERNAME, errhp);
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
                return FALSE;
       
swResult = OCIAttrSet(usrhp, OCI_HTYPE_SESSION,    (text*) passwd, strlen(passwd),
        OCI_ATTR_PASSWORD, errhp);
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
                return FALSE;

  
sword OCIAttrGet(
                dvoid *trgthndlp,  //需读取的句柄名
                ub4  trghndltyp,        //句柄类型
                dvoid *attributep, //读取的属性名
                ub4 *sizep,        //属性值长度
                ub4 attrtype,     //属性类型
                OCIError *errhp   //错误句柄
        )

4.连接/断开服务器
   多用户方式连接:
        sword  OCIServerAttach(
                        OCIServer     *srvhp,//未初始化的服务器句柄
                                     OCIError      *errhp,
                                                CONST text    *dblink,//服务器SID
                                        sb4           dblink_len,
                        ub4           mode //=OCI_DEFAULT,系统环境将设为阻塞方式
);

          sword OCIServerDetach (
                        OCIServer   *srvhp,
                                 OCIError    *errhp,
                                        ub4         mode //OCI_DEFAULT
                );
        单用户方式连接:
          sword OCILogon (
                        OCIEnv          *envhp,
                                   OCIError        *errhp,
                                         OCISvcCtx       **svchp,
                                         CONST text      *username,
                                         ub4             uname_len,
                                         CONST text      *password,
                                         ub4             passwd_len,
                                         CONST text      *dbname,
                                         ub4             dbname_len
                );
       
        sword OCILogoff (
                        OCISvcCtx      *svchp
                                         OCIError       *errhp
                );

5.开始/结束一个会话
先认证用户再建立一个会话连接
          sword OCISessionBegin (
                        OCISvcCtx     *svchp,  //服务环境句柄
                                     OCIError      *errhp,
                                         OCISession    *usrhp,   //用户会话句柄
                                        ub4           credt,    //认证类型
                                        ub4           mode   //操作模式
                );

          *认证类型:
                OCI_CRED_RDBMS:用数据库用户名和密码进行认证,则先要设置OCI_ATTR_USERNAME和OCI_ATTR_PASSWORD属性
                OCI_CRED_EXT:外部认证,不需要设置用户和密码
                OCI_DEFAULT:用户会话环境只能被指定的服务器环境句柄所设置
                OCI_SYSDBA:用户要具有sysdba权限
                OCI_SYSOPER:用户要具有sysoper权限


Eg:
swResult = OCISessionBegin(svchp, errh,usrhp, OCI_CRED_RDBMS, OCI_DEFAULT);
if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
                return FALSE;


        sword OCISessionEnd (
                        OCISvcCtx       *svchp,
                                      OCIError        *errhp,
                                      OCISession      *usrhp,
                                     ub4             mode );
6.读取错误信息
           sword OCIErrorGet (
                        dvoid      *hndlp, //错误句柄
                            ub4        recordno,//从那里读取错误记录,从1开始
                            text       *sqlstate,//已取消,=NULL
                            sb4        *errcodep, //错误号
                            text       *bufp,  //错误内容
                            ub4        bufsiz,  //bufp长度
                            ub4        type //传递的错误句柄类型
                                        =OCI_HTYPE_ERROR:错误句柄
                                        =OCI_HTYPE_ENV:环境句柄
                );
eg:
ub4    ub4RecordNo = 1;
OCIError* hError
sb4    sb4ErrorCode;
char   sErrorMsg[1024];

if (OCIErrorGet(hError, ub4RecordNo++, NULL, &sb4ErrorCode, (OraText*) sErrorMsg, sizeof(sErrorMsg), OCI_HTYPE_ERROR) == OCI_SUCCESS)
       printf(“error msg:%s\n”, sErrorMsg);


7.准备SQL语句
sword OCIStmtPrepare (
                OCIStmt       *stmtp,//语句句柄  
                         OCIError      *errhp,
                               CONST text    *stmt,  //SQL语句
                               ub4           stmt_len,   //语句长度
                               ub4           language,  //语句的语法格式=OCI_NTV_SYNTAX
        ub4           mode //=OCI_DEFAULT
);

eg:
char sSQL[1024];

sprintf(sSQL, “select table_name from user_tables”);

        swResult = OCIStmtPrepare(stmtp errhp,  (CONST OraText*)sSQL, strlen(sSQL), OCI_NTV_SYNTAX, OCI_DEFAULT);
        if(swResult != OCI_SUCCESS && swResult != OCI_SUCCESS_WITH_INFO)
                        return FALSE;




8. 绑定输入参数
       
OCIBindArrayOfStruct()         Set skip parameters for static array bind ,数组绑定,一般用于批量操作
OCIBindByName()        Bind by name  按名绑定
OCIBindByPos()        Bind by position  按位置绑定,建议一般按此方式绑定
OCIBindDynamic()        Sets additional attributes after bind with OCI_DATA_AT_EXEC mode  
OCIBindObject()        Set additional attributes for bind of named data type

注:
OCIBindArrayOfStruct必须先用OCIBindByPos初始化,然后在OCIBindArrayOfStruct中定义每个参数所跳过的字节数。
如:

存储方式:



第一条记录第二条记录                                                        N


  SkipPara(实际就是结构体长度,即本次所有列的长度和)



sword OCIBindByName (
                OCIStmt       *stmtp, //语句句柄
                 OCIBind       **bindpp,//结合句柄,=NULL
                 OCIError      *errhp,
                 CONST text    *placeholder,//占位符名称
                 sb4           placeh_len, //占位符长度
                 dvoid         *valuep, //绑定的变量名
                 sb4           value_sz, //绑定的变量名长度
                 ub2           dty,  //绑定的类型
                 dvoid         *indp, //指示符变量指针(sb2类型),单条绑定时为NULL,
                 ub2           *alenp, //说明执行前后被结合的数组变量中各元素数据实际的长度,单条绑定时为NULL
                 ub2           *rcodep,//列级返回码数据指针,单条绑定时为NULL
                 ub4           maxarr_len, //最多的记录数,如果是单条绑定,则为0
                 ub4           *curelep, //实际的记录数,单条绑定则为NULL
                 ub4           mode //=OCI_DEFAULT
        );

sword OCIBindByPos ( OCIStmt      *stmtp,
                     OCIBind      **bindpp,
                     OCIError     *errhp,
                     ub4          position,// 绑定的位置
                     dvoid        *valuep,
                     sb4          value_sz,
                     ub2          dty,
                     dvoid        *indp,
                     ub2          *alenp,
                     ub2          *rcodep,
                     ub4          maxarr_len,
                     ub4          *curelep,
                     ub4          mode );

sword OCIBindArrayOfStruct (
                OCIBind     *bindp,//绑定的结构句柄,由OCIBindByPos定义
                 OCIError    *errhp,
                 ub4         pvskip, //下一列跳过的字节数**
                 ub4         indskip,//下一个指示器或数组跳过的字节数
                 ub4         alskip, //下一个实际值跳过的字节数
                 ub4         rcskip //下一个列级返回值跳过的字节数
                );

例:
sword     swResult;
OCIBind*  hBind;
Ub4 rec_num;
Sql:  insert into student values (:p1,:p2)

单条绑定:
hBind = NULL;
        swResult = OCIBindByPos(stmtp &hBind, errhp,1,ststd.tname,
        sizeof(ststd.tname),        SQLT_CHR, NULL,
        NULL,NULL,0, NULL, OCI_DEFAULT);


批量取数据,一次取100条
Sql:  select username,age from student where username=:p1 and age=:p2

hBind = NULL;
swResult = OCIBindByPos(stmtp &hBind, errhp,1,tstd[0].tname,
        sizeof(tstd[0].tname),        SQLT_CHR, &tstdInd.sb2_usernmae[0],
        &tstdLen.ub2_username[0],&tstdRet.ub2_username[0],100, &rec_num, OCI_DEFAULT);
swResult = OCIBindArrayOfStruct(hBind, errhp,sizeof(tstd [0]), sizeof(sb2), sizeof(ub2), sizeof(ub2));

9.执行SQL语句
        sword OCIStmtExecute (
                OCISvcCtx           *svchp,  //服务环境句柄
                               OCIStmt             *stmtp,  //语句句柄
                               OCIError            *errhp,
                               ub4                 iters, // **
                               ub4                 rowoff, //**
                               CONST OCISnapshot   *snap_in,
                               OCISnapshot         *snap_out,
                               ub4                 mode //**
        );
**注:
1.        iters:对于select语句,它说明一次执行读取到buffer中的记录行数,如果不能确定select语句所返回的行数,可将iters设置为0,而对于其他的语句,iters表示这些语句的执行次数,此时iters不能为0。
2.        rowoff:在多行执行时,该参数表示从所结合的数据变量中的第几条记录开始执行(即记录偏移量)。
3.        mode:=OCI_DEFAULT:default模式
=OCI_DESCRIBE_ONLY:描述模式,只返回选择列表的描述信息,而不执行语句
=OCI_COMMIT_ON_SUCCESS:自动提交模式,当执行成功后,自动提交。
=OCI_EXACT_FETCH:精确提取模式。
=OCI_BATCH_ERRORS:批错误执行模式:用于执行数组方式的操作,在此模式下,批量insert ,update,delete时,执行过程中任何一条记录错误不会导致整个insert ,update,delete失败,系统自动会收集错误信息,而在非批错误方式下,其中的任何一条记录错误,将会导致整个操作失败。
Eg:
执行一次
swResult = OCIStmtExecute(svchp, stmtp,  errhp;,
                                      1, 0, NULL, NULL, OCI_DEFAULT);
批量执行100次:
swResult = OCIStmtExecute(svchp, stmtp,  errhp;,
                                      100, 0, NULL, NULL, OCI_DEFAULT);

10.定义输出变量
  
OCIDefineArrayOfStruct()          Set additional attributes for static array define  
OCIDefineByPos()          Define an output variable association  
OCIDefineDynamic()          Sets additional attributes for define in OCI_DYNAMIC_FETCH mode  
OCIDefineObject()          Set additional attributes for define of named data type  

sword OCIDefineByPos (
                OCIStmt     *stmtp, //语句句柄
                       OCIDefine   **defnpp,//定义句柄—用于数组变量
                       OCIError    *errhp,
                       ub4         position,//位置序号(从1 开始)
                       dvoid       *valuep, //输出的变量名
                       sb4         value_sz, //变量长度
                       ub2         dty,  //数据类型
                       dvoid       *indp, //指示器变量/指示器变量数组,如果此字段可能存在空值,则要指示器变量,否则单条处理时为NULL
                       ub2         *rlenp, //提取的数据长度
                       ub2         *rcodep, //列级返回码数组指针
ub4         mode //OCI_DEFAULT
        );




sword OCIDefineArrayOfStruct (
                OCIDefine   *defnp,//由OCIDefineByPos定义的句柄
                 OCIError    *errhp,
                ub4         pvskip, //下一列跳过的字节数,一般就是结构的大小
                 ub4         indskip,//下一个指示器或结构跳过的字节数,=0
                 ub4         rlskip, //下一个实际值跳过的字节数,=0
                 ub4         rcskip //下一个列列级返回值跳过的字节数,=0
                );

sword OCIDefineDynamic (
                        OCIDefine   *defnp,
                         OCIError    *errhp,
                         dvoid       *octxp,
                         OCICallbackDefine       (ocbfp)(/*_
                                  dvoid          *octxp,
                                  OCIDefine      *defnp,
                                  ub4            iter,
                                  dvoid          **bufpp,
                                  ub4            **alenpp,
                                  ub1            *piecep,
                                  dvoid          **indpp,
                                  ub2            **rcodep _*/)  );

sword OCIDefineObject ( OCIDefine       *defnp,
                        OCIError        *errhp,
                        CONST OCIType   *type,
                        dvoid           **pgvpp,
                        ub4             *pvszsp,
                        dvoid           **indpp,
                        ub4             *indszp );

eg:
单条查询
sql: select username,age from student  where username=:p1;
如果此字段有可能有空值,则
hDefine = NULL;
swResult = OCIDefineByPos(stmtp &hDefine, errhp, 1, tstd.username, sizeof(tstd.username), SQLT_CHR, & sb2aInd[0], NULL, NULL, OCI_DEFAULT);
如果此字段没有空值,则
hDefine = NULL;
swResult = OCIDefineByPos(stmtp &hDefine, errhp, 1, tstd.username, sizeof(tstd.username), SQLT_CHR, NULL, NULL, NULL, OCI_DEFAULT);

  批量查询
select username,age from student  where age>;30;
hDefine = NULL;
swResult = OCIDefineByPos(stmtp, &hDefine, errhp, 1, &tstd[0].username,
sizeof(tstd[0].usenmae), SQLT_CHR, NULL, NULL, NULL, OCI_DEFAULT);

swResult = OCIDefineArrayOfStruct(hDefine, errhp, sizeof(tstd[0]), 0, 0, 0);
11.提取结果
        sword OCIStmtFetch (
                OCIStmt     *stmtp,//语句句柄
                     OCIError    *errhp,
                     ub4         nrows, //从当前位置处开始一次提取的记录数,对于数据变量,可以>;1,否则不能>;1
                     ub2         orientation,//提取的方向:OCI_FETCH_NEXT
ub4         mode //OCI_DEFAULT
          )

eg
   while ((swResult=OCIStmtFetch stmtp errhp,1,OCI_FETCH_NEXT,OCI_DEFAULT)) != OCI_NO_DATA)
        {
                ……
        }

12.事务操作
开始一个事务
sword OCITransStart (
                OCISvcCtx    *svchp,
                      OCIError     *errhp,
                      uword        timeout, //**
                      ub4          flags );
**注:
1.        Timeout:
                当flag=OCI_TRANS_RESUME:它表示还有多少秒事务将被激活
                        =OCI_TRANS_NEW: 事务响应的超时时间(秒)
2.        Flags:指定一个新的事务还是已有事务
        =OCI_TRANS_NEW:定义一个新的事务
        =OCI_TRANS_RESUME
       
准备一个事务:
sword OCITransPrepare (
         OCISvcCtx    *svchp,
                        OCIError     *errhp,
                        ub4          flags );//OCI_DEFAULT

sword OCITransForget (
        OCISvcCtx     *svchp,
                       OCIError      *errhp,
                       ub4           flags );//OCI_DEFAULT

断开一个事务:
sword OCITransDetach (
        OCISvcCtx    *svchp,
                       OCIError     *errhp,
ub4          flags );//OCI_DEFAULT

          提交一个事务:
sword OCITransCommit (
                OCISvcCtx    *svchp,  //服务环境句柄
                              OCIError     *errhp,
                              ub4          flags ); //OCI_DEFAULT
        回滚一个事务
sword OCITransRollback (
                dvoid        *svchp,
                              OCIError     *errhp,
                              ub4          flags ); //OCI_DEFAULT


四.        OCI数据类型与C语言数据类型对照表
表字段类型             OCI类型        C类型        备注
Number(N)        SQLT_UIN         int        无符号整型
Number(N)        SQLT_INT         int        有符号整型
Number(n,m)        SQLT_FLT         float        符点数
Varchar2(N)        Sqlt_chr  Char        字符串
Raw(N)          Sqlt_BIN        具体看不同的定义        二进制类型,多用于一个结构字段
DATE        SQLT_DAT        无        最好转换成字符串或数字


 


http://bbs.chinaunix.net/viewthread.php?tid=530742&extra=page%3D1

Oracle高级复制的创建配置步骤

本例涉及两个站点.
主体定义站点:AVATAR.COOLYOUNG.COM.CN
主体站点:AUTHAA.COOLYOUNG.COM.CN
注:主体定义站点指配置复制工作的站点

本例涉及的用户.
复制管理员:repadmin
应用用户:hawa
本例复制的对象:hw_test 数据表
1.在主体定义站点复制用户下创建复制对象




SQL> select * from global_name;

GLOBAL_NAME
-----------------------------------------------------------
AVATAR.COOLYOUNG.COM.CN

SQL> connect hawa/password
Connected.
SQL> create table hw_test as select * from hw_online;

Table created.

SQL> select count(*) from hw_test;

COUNT(*)
----------
464

SQL> alter table hw_test add (constraint pk_userid primary key (numuserid));

Table altered.


2.在主体站点同样创建复制对象




SQL> select * from global_name;

GLOBAL_NAME
------------------------------------------------------------------------
AUTHAA.COOLYOUNG.COM.CN

SQL> connect hawa/password
Connected.
SQL> create table hw_test as select * from hw_online;

Table created.

SQL> select count(*) from hw_test;

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


3.在主体站点手工同步数据




SQL> connect repadmin/password

Connected.
SQL> insert into hawa.hw_test select * from hawa.hw_test@avatar;

464 rows created.

SQL> commit;

Commit complete.


4.在主体定义站点开始操作
登陆主体定义站点




$ sqlplus repadmin/password

SQL*Plus: Release 9.2.0.4.0 - Production on Mon Jun 27 09:32:36 2005

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.4.0 - Production

SQL> select * from global_name;

GLOBAL_NAME
----------------------------------------------------------------------------
AVATAR.COOLYOUNG.COM.CN


创建复制组:




SQL> execute dbms_repcat.create_master_repgroup('rep_hh');

PL/SQL procedure successfully completed.

SQL> select gname,master,status from dba_repgroup where gname='REP_HH';

GNAME M STATUS
------------------------------ - ---------
REP_HH Y QUIESCED




在复制组里加入复制对象




SQL> execute dbms_repcat.create_master_repobject
(sname=>'hawa',oname=>'hw_test',
type=>'table',use_existing_object=>true,gname=>'rep_hh',copy_rows=>false);

PL/SQL procedure successfully completed.

SQL> select sname,oname,status,gname from dba_repobject where gname='REP_HH';

SNAME ONAME STATUS GNAME
------------------------------ ------------------------------ ---------- ------------------------------
HAWA HW_TEST VALID REP_HH


对复制对象产生复制支持




SQL> execute dbms_repcat.generate_replication_support('hawa','hw_test','table');

PL/SQL procedure successfully completed.

SQL> select gname, master, status from dba_repgroup where gname='REP_HH';

GNAME M STATUS
------------------------------ - ---------
REP_HH Y QUIESCED

SQL> select sname,oname,status,gname from dba_repobject where gname='REP_HH';

SNAME ONAME STATUS GNAME
------------------------------ ------------------------------ ---------- ------------------------------
HAWA HW_TEST VALID REP_HH
HAWA HW_TEST$RP VALID REP_HH
HAWA HW_TEST$RP VALID REP_HH

SQL>


添加主体复制节点




SQL> execute dbms_repcat.add_master_database
(gname=>'rep_hh',master=>'AUTHAA.COOLYOUNG.COM.CN',use_existing_objects=>true,
copy_rows=>false, propagation_mode => 'synchronous');

PL/SQL procedure successfully completed.

SQL> column masterdef format a10
SQL> column master format a10
SQL> column dblink format a25
SQL> column gname format a12

SQL> select gname, dblink, masterdef MASTERDEF, master MASTER from sys.dba_repsites where gname='REP_HH';

GNAME DBLINK MASTERDEF MASTER
------------ ------------------------- ---------- ----------
REP_HH AVATAR.COOLYOUNG.COM.CN Y Y
REP_HH AUTHAA.COOLYOUNG.COM.CN N Y


登陆主体站点,检查复制对象情况:




[oracle@www167 oracle]$ sqlplus repadmin/password

SQL*Plus: Release 9.2.0.4.0 - Production on Mon Jun 27 09:34:49 2005

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


Connected to:
Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
With the Partitioning option
JServer Release 9.2.0.4.0 - Production

SQL> select * from global_name;

GLOBAL_NAME
--------------------------------------------------------------------------------
AUTHAA.COOLYOUNG.COM.CN


SQL> set linesize 120
SQL> select sname,oname,status,gname from dba_repobject where gname='REP_HH';

SNAME ONAME STATUS GNAME
------------------------------ ------------------------------ ---------- ------------------------------
HAWA HW_TEST VALID REP_HH
HAWA HW_TEST$RP VALID REP_HH
HAWA HW_TEST$RP VALID REP_HH


在主体定义站点启动复制:




SQL> select * from global_name;

GLOBAL_NAME
-----------------------------------------------------------------------------
AVATAR.COOLYOUNG.COM.CN

SQL> execute dbms_repcat.resume_master_activity('rep_hh',true);

PL/SQL procedure successfully completed.


在主体定义站点删除数据测试:




SQL> connect hawa/password
Connected.
SQL> select count(*) from hw_test;

COUNT(*)
----------
464

SQL> delete from hw_test where rownum <20;

19 rows deleted.

SQL> commit;

Commit complete.

SQL> select count(*) from hw_test;

COUNT(*)
----------
445


在主体站点观察变化:




SQL> select * from global_name;

GLOBAL_NAME
--------------------------------------------------------------------------------
AUTHAA.COOLYOUNG.COM.CN

SQL> select count(*) from hw_test;

COUNT(*)
----------
445

SQL>


至此,同步复制配置完毕。

关于Advanced Replication 的初步研究
Oracle 高级复制冲突解决机制
Oracle 高级复制冲突解决机制的研究


如何搭建 Oracle 8 高级复制环境

一、主要配置参数说明示例

    Oracle 高级复制,也称为对称复制。和 Oracle 的其他功能不同,Oracle 的高级复制不是即插即用的,用户必须深刻理解它们是如何工作的以及各种复制方案的优缺点。深刻理解复制的基本概念可以帮助你设计一个可靠的复制环境。
    接下来主要介绍搭建 Oracle 高级复制环境时需要设置的一些系统参数。需要提醒注意的是,这里所给出的这些系统参数的具体配置数值只能保证可以成功的搭建出一个相对较好的高级复制环境,但并未对这些参数的优化配置进行进一步的深入探讨。

现在我们正式开始。假设有两个节点,节点名分别为 RLDBA 和 XJTU。
数据库名 Rldba Xjtu
数据库域名 Hr_group World
数据库SID Rep.world Xjtu.world
Listener端口号 1521 1521
服务器IP地址 192.168.110.221 192.168.110.130

1. 实现数据库复制的前提条件
a 数据库支持高级复制功能:您可以用 system 身份登录数据库,查看 v$option 视图,如果其中 Advanced replication 为 TRUE,则支持高级复制功能;否则不支持。
b 数据库初始化参数要求:
(1) db_domain = test.com.cn:指明数据库的域名(默认的是WORLD),这里可以用您公司的域名。
(2) global_names = true:它要求数据库链接(database link)和被连接的数据库名称一致。 现在全局数据库名:db_name+"."+db_domain
c 数据库连接通畅:
运行 $tnsping hr_svr 与 $tnsping xjtu,出现以下提示符:
Attempting to contact
(ADDRESS=(PROTOCOL=TCP)(HOST=10.1.1.200)(PORT=1521)) OK(n毫秒)则表示数据库连接通畅,可以准备复制。


2. 系统环境参数(init.ora文件)设置(对于非缺省值)
如果要搭建Oracle高级复制环境,必须在初始化文件中设置下列参数,见表1所示。



























































































表1:Oracle8高级复制环境初始化参数设置

参数名称


推荐值


备注


processes


100

 进程数,default=59如果进程数大于59数据库将可能发生死锁

shared_pool_size


30000000


至少30M,如果有很多的复制对象的话,则需要更多的空间


large_pool_size


500K


 


db_block_buffers


550


 


compatible


8.0.5.0


 该版本以上


db_file_multiblock_read_count


16


 


dml_locks


100


 


sequence_cache_entries


30


 


sequence_cache_hash_buckets


23


 


global_names


TRUE


 


distributed_lock_timeout


300


 


distributed_transactions


10


 


Open_links


6


复制节点多的话,需要增加


Sort_area_size


1000000


 


db_name


ORA_BJ


或者ORA_NB


job_queue_processes


6


 定义SNP进程的启动个数为n。系统缺省值为0,正常定义范围为0~36,根据任务的多少,可以配置不同的数值。


job_queue_interval


60


 定义系统每隔N秒唤醒该进程一次。系统缺省值为60秒,正常范围为1~3600秒。事实上,该进程执行完当前任务后,就进入睡眠状态,睡眠一段时间后,由系统的总控负责将其唤醒。


parallel_max_servers


10


只适用于并行传播


parallel_min_servers


2


只适用于并行传播


PEPLICATION_DEPENDENCY_TRACKING


true


如果采用并行传播,必须设置为TRUE


表1中各个参数的推荐值认为目前的复制环境只有两个节点,一个简单的高级复制环境,如果节点较多,且复制关系复杂,需要复制的表也很多,则需要相应增大一些参数的值,这可以通过修改不同的参数试验获得。如果修改了以上这几个参数,需要重新启动数据库以使参数生效。

将所有的 SNAPSHOT_ 或者是 JOB_QUEUE_KEEP_CONNECTIONS 参数都删除,因为 Oracle 以后已经不支持这些参数。

3.Net8参数文件




(1)sqlnet.ora文件设置





# SQLNET.ORA Network Configuration File: D:\Oracle\Ora81\network\admin\sqlnet.ora
# Generated by Oracle configuration tools
SQLNET.AUTHENTICATION_SERVICES= (NTS)
NAMES.DIRECTORY_PATH= (TNSNAMES, ONAMES, HOSTNAME)
automatic_ipc=off
names.default_domain = world
name.default_zone = world
sqlnet.expire_time = 0
DISABLE_OOB = ON






(2)tnsnames.ora文件设置






RLDBA =
    (DESCRIPTION =
         (ADDRESS_LIST =
            (ADDRESS = (PROTOCOL = TCP)(HOST = hr_svr)(PORT = 1521))
         ) 
         (CONNECT_DATA = (SERVICE_NAME = rep.world) )
    )

XJTU = 
    (DESCRIPTION = 
         (ADDRESS_LIST = 
            (ADDRESS = (PROTOCOL = TCP)(HOST = xjtu)(PORT = 1521))
         )
         (CONNECT_DATA = (SERVICE_NAME = xjtu.world) )
    )


上面Host为各个复制节点的IP地址,如果复制节点很多,则全部加入到tnsnames.ora文件中,本文作为用例中有两个节点。


4.表空间
如果搭建 Oracle 8 高级的高级复制环境,额外需要加大一些表空间,表2是建议的初始表空间。


























表2:Oracle系统表空间大小设置

表空间


建议初始值


建议


SYSTEM


至少20M


 


ROLLBACK SEGMENTS


至少20M


建议回滚段的下一个区大小设置至少为100K


TEMPORARY


至少10M


 


TOOLS


至少20M


 


上面这些建议的设置是一种较小复制环境下的空间设置。如果要复制的表很多,每天的变化量很大,复制节点复杂,则需要相应增大表空间的大小,具体数据依据具体情况而定。


二、复制应用实例

    上面我们对复制基本概念及复制参数的作了说明,接下来主要介绍一个Oracle快照复制的实际例子及其技术实现细节。

(1) 业务需求描述
在一个实际的数据库应用中,如电信、人力资源管理等应用中通常都采用这样一种解决方案,在一个行政区域内,如一个省或者一个市,在不同的地理位置架设数台数据库服务器,这些不同地理位置的服务器具有同样的后台数据库。为了维护数据库系统的一致性,对于整个行政区域应用的基本数据表应该保持一致,如果不考虑数据复制,想维护同样的不冲突的代码表是很困难的。下面我们不考虑实际的业务应用,只从数据库复制角度来说明Oracle快照复制的应用。
为了维护整个系统基本数据表的一致性,比如有这样的业务需求,对RLDBA上的一些表采用统一维护,即在一台服务器上维护。而在其他位置(如数据库 XJTU,用户SNAP)可以直接使用这些表,也就是说在位置1具有对代码表插入、删除和更新的能力,而在其他地方具有同步查询应用的能力。

(2) 应用设计
针对上述的需求,现在提出了这样一种解决方案,也就是采用Oracle的快照复制。具体业务实现方案设计如下:
在位置1的数据库RLDBA维护所有的表,在其余数据库建立相对于位置1的所有表的快照。为了维护快照的方便,在位置2创建一个单独的快照表空间和一个模式(schema),也可以称为用户(USER),系统中的其他用户通过一个私有同义词来存取这些快照。这里私有同义词相对公共同义词要好,这是因为在位置1存在一个同样的系统,它的表是通过公共同义词来存取的。对于快照的刷新,采用Oracle系统包DBMS_REFRESH进行,并将该刷新过程的运行定时在每天早上2:00,这样可以减少网络流量。对于快照的刷新形式,由于对于表的维护不是很多而且表的数据量相对较少,所以在此选择了完全刷新,这样就避免了管理快照日志的麻烦。下面以一个节点2(XJTU)为例来说明具体的技术实现细节。

(3) 技术实现细节
除非特别说明,下面的SQL命令都是在数据库XJTU的SYSETM用户下运行的。

1. 在数据库2(XJTU)上增加数据库1(RLDBA)的services name,可以直接在tnsnames.ora文件中增加数据库1的services name,包括IP地址,SID以及端口号等。services name 命名为rep.world。

2. 创建一个用于连接数据库1(RLDBA)的数据库连接(dblink)
DROP PUBLIC DATABASE LINK rep.hr_group@rldba; //删除Database link
CREATE PUBLIC DATABASE LINK rep.hr_group@rldba CONNECT TO rldba IDENTIFIED BY admin USING 'rldba'; //Create Database link
select * from cat@rep.hr_group@rldba; //Test the Database link
注:出于安全考虑,可以采用一个私有数据连接。

3. 创建一个名为snapshot_rldba的表空间来存放RLDBA快照,并创建一个和该表空间有关的名为Snap的用户。
CREATE TABLESPACE "snapshot_rldba" LOGGING DATAFILE 'D:\ORACLE\ORADATA\ORA8I\SNAPSHOT_RLDBA.ora'SIZE 30M
DEFAULT STORAGE (
INITIAL 30K
NEXT 15K
MINEXTENTS 100
MAXEXTENTS UNLIMITED
PCTINCREASE 0 ); //Create Table space

CREATE USER snap IDENTIFIED BY snap DEFAULT TABLESPACE "snapshot_rldba";
//Create User in the table space
GRANT CONNECT, RESOURCE TO snap; //grant role to the user

4. 运行下面的脚本文件snapsql.sql来生成创建rldba数据库上rldba用户表的快照脚本:
注意如果所需生成快照的表中含有类型为long的列,"select *"在这里就不会起作用,上面的这个SQL脚本就不能自动建立生成所需快照的脚本,必须通过在select列表中显式地添加long型列名来创建表的快照。下面是一个例子,假如我们要创建快照依赖的表T_YGJBXX中有一个列ZP类型为long,就需要单独写出如下的创建快照的脚本:
CREATE SNAPSHOT T_YGJBXX PCTFREE 10 PCTUSED 40
TABLESPACE "snapcost_rldba "
STORAGE (
INITIAL 40960
NEXT 57344
PCTINCREASE 0 )
USING INDEX REFRESH WITH PRIMERY KEY
FOR UPDATEAS select YGID, GZBH, FZJRLB, ZP, SXZY, XCSZY from T_YGJBXX@rep.hr_group@rldba; //Create snapshot

EXECUTE DBMS_SNAPSHOT.REFRESH ('snap.T_YGJBXX ')
运行脚本文件create_snapshot.sql后,就在模式snap中创建了所需要的快照。下一步就是考虑该如何刷新快照。对于快照的刷新,可以通过一些桌面DBA工具来刷新快照也可以通过系统包dbms_snapshot.refresh来刷新一个快照:
创建或选择实现数据库复制的用户和对象,给用户赋权,数据库对象必须有主关键字,如果数据库对象没有主关键字,可以运行以下SQL命令添加:
alter table dept add (constraint dept_deptno_pk primary key (deptno));

5. 创建一个定时刷新过程来定时刷新快照:
--sp_snapshot_refresh.sql
CREATE OR REPLACE PROCEDURE sp_snapshot_refresh
IS
BEGIN
DBMS_REFRESH.MAKE ( NAME=>' T_YGJBXX ', LIST=>'snap. T_YGJBXX', NEXT_DATE=>TRUNC (SYSDATE+1)+2/24, INTERVAL=>'(SYSDATE+1)', IMPLICIT_DESTROY=>FALSE, LAX=>TRUE);
END
sp_snapshot_refresh; --创建了一个定时任务来每天早晨2:00定时刷新快照
EXECUTE sp_snapshot_refresh; //Execute the procedure
SELECT JOB, WHAT FROM DBA_JOBS; //查询刚刚加入的这个任务
CREATE SYNONYM system.T_YGJBXX FOR snap.T_YGJBXX;//在用户system下创建快照的私有同义词
GRANT SELECT ON dm_gy_rydm TO system;//以snap用户向system用户授与快照可以select的权限。

6. 同样的步骤在其它位置建立位置1(rldba)的表快照和定时刷新任务。这样就可实现在位置1统一维护代码表,在位置2和其它位置使用该表的目的。如下面的SQL语句,在位置2(xjtu)用户snap浏览在位置1(rldba)中的代码表。
SELECT * FROM T_YGJBXX;

(4) 日常维护及注意事项
无论任何时候只要出现网络连接问题,刷新就会失败。这些错误信息可以在alert.log文件中找到。下面简单介绍一下对这种问题的处理办法:
1.首先在任务队列中找到刷新快照的任务编号
SELECT JOB, what FROM DBA_JOBS;
2.删除该任务
EXECUTE DBMS_JOB.REMOVE (JOBNO);
3.删除快照组
EXECUTE DBMS_REFRESH.DESTROY ('tax_dmb_grp');
4.重新创建快照组并且重新定时任务来定时刷新快照
EXECUTE sp_snapshot_refresh('snap.T_YGJBXX')
5.快照监视
SELECT NAME, TO_CHAR(last_refresh,'DD-MON-YY HH:MM:SS') FROM DBA_SNAPSHOTS;


http://www0.ccidnet.com/tech/guide/2001/09/03/58_3174.html
http://www.linuxmine.com/3422.html

Oracle 8 高级数据复制技术

Oracle 8高级数据复制技术(上)
(作者:石骁騑 2001年03月28日 13:45)

  本文首先简单介绍和数据库复制有关的基本概念,然后探讨Oracle8数据复制技术中的几个重要模型,最后介绍Oracle8的数据复制管理器以及如何利用它来配置和维护复制环境。

  在文章的开头,我想首先简单谈一下复制的基本概念,也就是什么是复制?复制简单地说就是在由两个或者多个数据库系统构成的一个分布式数据库环境中拷贝数据的过程。Oracle高级复制,也称为对称复制,第一次是在Oracle 7.1.6版本中出现的,在这之前的Oracle版本中,Oracle数据复制方法仅有只读快照形式的基本复制一种方法。随着Oracle版本的每一次升级,数据复制的功能、管理以及速度等方面都得到了很大的改进和完善。目前,由于对分布式数据环境需求的不断增长,越来越多的应用提出了数据复制的需求。

一、基本概念
  1.分布式数据库技术

  分布式数据库技术是目前我们经常提及的分布式计算的一个重要组成部分,该技术允许数据在多个服务器端共享。采用分布式数据库技术,一个本地服务器可以存取不同物理地点的远程服务器上的数据;也可以使所有的服务器均可以持有数据的拷贝/复制,这样分布式系统中的所有服务器均可进行本地存取。

  设计一个分布式计算解决方案首先需要考虑的问题就是应用的完整性、复杂性、性能和可用性以及响应时间等,同时还需要考虑的是对于不同的应用需求是采用实时存取远程数据还是采用延迟存取远程数据。这对于数据复制来讲就是采取实时更新复制方案还是延迟数据复制方案。

  2.同步和异步的概念

  同步分发数据库技术是一种实时远程存取和实时更新数据的技术。这种技术可以保证应用的完整性降低了应用的复杂性,但是如果系统存在网络存取速度很慢这样的问题,相应响应时间就会很慢。

  异步分发数据库技术是一种延迟远程存取和延迟传播对数据更新的技术。这种技术具有很高的可用性和很短的响应时间。相比同步分发数据库技术就显得复杂一些,为了确保应用的完整性需要仔细考虑和设计。

  对于实际的商业问题,必须权衡这两种技术的利弊最终选择最佳的解决方案,有些问题选用同步技术比较适合,也有一些问题采用异步技术是比较好的解决方案,还有一些问题必须综合这两种技术。

  3.复制的概念

  复制,顾名思义就是将数据库中的数据拷贝到不同物理地点的数据库中以支持分布式应用,它是整个分布式计算解决方案的一个重要组成部分。上面介绍了同步和异步的概念,这里针对复制也存在同步复制和异步复制的问题。

  同步复制,复制数据在任何时间在任何复制节点均保持一致。如果复制环境中的任何一个节点的复制数据发生了更新操作,这种变化会立刻反映到其他所有的复制节点。这种技术适用于那些对于实时性要求较高的商业应用中。

  异步复制,所有复制节点的数据在一定时间内是不同步的。如果复制环境中的其中的一个节点的复制数据发生了更新操作,这种改变将在不同的事务中被传播和应用到其他所有复制节点。这些不同的事务间可以间隔几秒,几分种,几小时,也可以是几天之后。复制节点之间的数据临时是不同步的,但传播最终将保证所有复制节点间的数据一致。

  4.更新冲突

  在异步复制环境中,对于所有应用最关键的就是要确保数据的一致性。我们来看下面这种情况会有什么后果发生呢?在同一时间对同一个表的同一行数据的同一列在两个不同的地点作更新。这种情况就会发生称之为更新冲突的错误。为保证数据的一致性,更新冲突必须被检测到并且处理以确保在不同地点的数据元素保持同样的值。更新冲突可以通过限制"所有权" 到单一节点或者将更新某个特定数据元素的权利限制到某一具体节点的方法来避免。

二、Oracle 8数据复制应用模型(usage models)
  为确保实际应用数据的一致性,必须在异步复制应用模型中考虑冲突避免或者冲突检测和消除的方法。例如,对于一个实际商业应用,首先必须在逻辑上了解该商业应用采取的冲突避免方法和在某个节点有那些数据以及这些数据中那些是可更新的,而那些又是不可更新的。在下面的这一部分中,我们首先将详细讨论两种常用的冲突避免方法:主站点所有权模型和动态所有权模型。然后,讨论共享所有权模型以及这种模型引起的冲突检测和处理问题,最后,讨论针对Fail-over的复制配置,这种复制方案同时考虑了冲突避免和冲突检测与消除两种情况。

  1.主站点所有权

  主站点所有权,异步复制数据被一个单一节点"所有",这些要复制的数据仅能被该节点更新,其他节点向拥有该数据的主节点订阅(subscribe)数据,这意味着他们在本地系统上只能够存取这些复制数据的只读拷贝。下面是一些这样的例子。

  (1)决策支持系统(DSS)的联机事务处理数据的卸载。来自一个或者多个OLTP系统的数据可以被卸载到一个独立的局部DSS中,用于只读分析。

  (2)中央信息的分发。产品信息,如价格列表等在总部节点上维护,然后将这些信息复制到远程销售办事处的只读产品目录系统中。

  (3)远程信息的集中。许多远程节点上的产品目录数据复制到总部节点,这里总部节点只需要有数据只读的权限。

  一个主节点拥有一个表的完全所有权,而其他节点只能订阅这个表的只读拷贝。也可以是多个主节点拥有同一个表的截然不同子集或者划分,而另一些节点则订阅这些子集或者划分的只读拷贝。如,一个分布的产品目录系统可以让不同的销售办事处拥有一个表的属于自己的一个"水平"部分,如在客户(CUSTOMERS)表, 订单(ORDERS)表和目录(ITEMS)这些表中含有每个销售办事处为之服务的客户和产品信息。中心总部节点可以通过订阅每个办事处拥有的数据来保持一个完整的所有产品和客户信息的只读拷贝。

  2.动态所有权

  动态所有权,异步更新将复制数据从一个节点移到另一个节点,而在该过程中,必须保证在同一时刻只有一个特定的节点可以对数据进行更新。一个典型实际应用就是"海关订单处理系统",订单处理的典型步骤是,报关→同意→装运→开单→收单→入帐等。应用模型可以执行其中的任何步骤,但必须保证各个不同模块的同一个数据应该在一个综合数据库中。在该系统中,当且仅当订单的状态表明前一个步骤已经完成时,下一个应用模块才可以执行更新订单数据的操作。例如,"装运"应用模块仅能在"报关"并且得到"同意"后才能被执行。

  通过使用动态所有权复制模型,可以将一个系统分布在多个节点和数据库上,也就是说应用模型可以建立在不同的系统上。我们还是来看上面的例子,"报关"和"批准"这两部分可以运行在一个系统上,"装运"在另一个系统上,"开单"和"收单"等又可在一个系统上。在这个分布式系统中,数据可以被复制到不同的节点上,这些节点对复制的数据只要具有只读的权限即可。如,利用复制,"报关"节点可以监视已经报关的订单处理过程。

  前面讨论的主节点所有权和动态所有权复制模型具有一个共同的特征:在任何一个给定的时间点,只允许一个节点有更新数据的权利,而其余节点对于复制的数据拷贝仅有只读权限。然而,还存在这样的情况,允许多个节点可以更新同一个数据,在极端情况下可以是在同一时刻,这就是所说的共享所有权。

  3.共享所有权

  共享所有权使用异步复制,这对于主节点和动态所有权模型来讲存在一些限制。在共享所有权情况下,整个系统可以存在暂时的不一致,同时必须使用冲突检测和消除。共享所有权模型相对于前面两种模型具有一些新的特点。

  例如,对于前面我们讨论的那个采用具有水平划分主节点复制方案来的分布式"订单处理系统"的例子。采用共享所有权模型,每个销售办事处都有库表中不同的水平划分,该库表含有每一个办事处为之服务的一些订单信息和与消费者有关的顾客信息。每一个销售办事处只输入与自己有关的顾客订单情况,而不管其余顾客信息。

  然而,在实际商业应用中,这个模型不是最佳的选择。例如,这种情况,一个零售集团在一个大城市中可以有好几个商场。顾客可能经常去离他们住的最近的那个商场,但是偶尔也可能到其他商场去购物。这时,如果多家商场执行更新同一个顾客和其订单数据的信息,更新冲突就会发生。所以在这种情况下必须要采用冲突检测和消除方案。

  Oracle8高级复制支持同时既考虑冲突避免又考虑冲突检测和消除的复制模型。Oracle8高级复制之所以又称为对称复制,其原因之一就是支持对称复制模型,也就是可以在任何地方更新,即所有的复制节点都可以进行更新处理。为了避免冲突,一种方法就是将应用设计为将更新限制在一些特定的节点。对于共享所有权,Oracle 8提供了自动冲突检测和消除方案。

  4.备用数据库(Fail-Over )

  异步复制通过将一个主系统数据复制到另一系统,可以起到对主系统的崩溃提供保护的作用,这也就是所说的fail-over系统,如果主系统出现问题,业务依旧可以通过复制数据库进行。

  Oracle 8高级复制支持这种fail-over配置。同时,Oracle也针对fail-over提供了另外两个可选的解决方案:Oracle并行服务器和备用数据库配置。用户可以根据吞吐量、可用性、事务损失的可能性和其他一些如数据一致性、方法的局限性等参考指标来权衡选择合适的fail-over方案。


Oracle 8高级数据复制技术(下)
(作者:石骁騑 2001年03月28日 13:45)

三、Oracle 高级复制配置
  Oracle 8高级复制即可支持基于整个表的复制也可支持基于部分表的复制两种复制方案。这两种复制方案主要是通过Oracle的两种复制机制来完成的,即多主复制和可更新快照复制,同时还可以将这两种复制机制结合起来以满足不断变化的业务需求。

  1.多主复制

  多主复制方案支持全表在各个主节点间的对称复制,允许所有主节点对主表都有更新操作的权利。任何一个主节点上的复制表的更新都会被传播并被直接应用到其他所有主表。一个主节点出现问题,不会对其他主节点之间变化的传播造成影响。

  多主复制采用一种称为"延迟远程过程调用(deferred remote procedure calls RPCs)"的机制作为主要的传播和应用变化的机制。各节点之间变化的传播,既可以以基于事件的方式立即传播,也可以在某个特定的时间点,如在网络空闲时(如晚上)传播。在传播变化时,如果其中的一个远端系统没有准备好,传播变化的延迟远程过程调用(RPCs)就会保存在其本地队列中,等到系统准备好以后再执行。

  2.可更新快照

  Oracle 将最早Oracle 7上的只读快照机制扩展为一种允许快照可更新的对称复制机制。快照更新的传播方式和如何应用到快照主节点采用了和多主复制一样的延迟远程过程调用机制。

  对于快照的定义,既可以是包含一个主表的完全拷贝,也可以是为满足基于值的选择标准的主表中行的子集。快照在主节点的刷新是按照一定的时间间隔或用户单独请求进行的。最后一次刷新后主表的任何变化也同样被传播并应用到快照。多个快照的刷新是在一个一致的事务中完成的,这就确保了数据和引用的完整性。

  3.混合配置

  可以将多主复制和可更新快照复制结合在一起,构成一种新的混合配置,这种配置可以完成对全表或者子表的复制。例如下面这种应用就是一个典型的混合配置方案,一个系统具有两个位于不同地理区域的中心节点,这两个不同的地理区域下面还有一些分支机构,两个中心节点可以彼此看做是自己的备份节点。采用多主复制方法在两个中心站点之间复制数据,同时采用只读或者可更新快照复制方法在每个区域范围中的主节点之间复制全表或者子表。这种配置的一个显著好处就是当其中的一个中心节点发生问题时,这些快照的主节点可以被重新定义到另一个运行良好的中心节点,从而提高了系统的可靠性。

  4.其他复制机制

  Oracle除了前面讨论的三种复制机制以外,还提供了另外两种复制机制:过程级复制和同步复制。

  (1)过程级复制

  这种复制方案主要应用在存在大量数据更新以及采取批处理方式操作数据时需要复制数据的情况。例如,下面这个应用,一个以年为单位管理客户订单的公司,对于老的订单数据不再需要在线保存,而需要卸载到某存储介质中。这时,如果在多个节点间复制每一独立的行级变化效率将是非常低的。对于这种情况,可以直接在每个复制节点执行一个过程来直接进行这种更新操作。Oralce8高级复制提供的分布式模式管理功能(将在下面详细讨论)可以非常方便地在多个节点上设置和维护过程级复制的远程过程。

  (2)同步复制

  一个采用同步复制方案的表发生变化时,Oracle会确保这种变化能够成功地作用在本地表和其他节点的复制表,如果失败则整个事务会被成功回滚。同步复制在网络的稳定性比较高的情况下是可行的,可以保证复制节点之间的复制数据一直保持同步。

四、Oracle 8管理工具
  很显然,有效的管理工具对于成功的分布式应用是非常关键的,如果没有能力去操作它,再专业的复制功能也不能发挥很好的作用。Oracle 8高级复制提供了几个功能强大的管理工具,诸如复制目录,分布式模式管理以及其他的一些Oracle 复制管理工具。

  1.复制目录

  复制目录是一个包含定义复制环境原数据的一个单一综合库。复制目录本身也被复制到多个节点以确保高可用性和授权用户可以简单地实现本地存取管理。

  复制目录定义了被复制的数据库对象,复制的节点以及用于复制的机制。数据库对象有需要复制的库表和其他一些相关的对象,如索引,视图,过程,触发器和同义词等等。这些原数据是开放的,用户可以通过标准SQL语句进行检索和查询。

  2.分布式模式管理

  Oracle 8高级复制的分布式模式管理功能允许在一个控制点就可进行复制环境的定义和改变。对复制环境的任何改变,都将自动复制并且应用这些数据定义语言(DDL)命令到其他复制环境节点,同时也利用数据库触发器和复制相关过程自动生成复制所需要的一些支持对象。

  分布式模式管理在一个被称为主定义节点的地方进行控制。它自动将DDL推向其他所有主节点并且也允许快照节点"拉"回并且执行这些DDL命令。由于主定义节点使用并且维护着整个复制目录,该复制目录本身也被复制到其他节点,所以该主定义节点一旦出现问题,就必须用其他节点来代替。分布式模式管理可以通过一个图形用户界面管理工具(GUI)来配置。

  3.Oracle复制管理器

  Oracle复制管理器是Oracle提供的一个图形界面的复制管理工具,通过该工具可以配置,定时和通过一个节点来管理整个的复制环境。该管理工具可以单独运行也可以在Oracle企业管理器中通过一个applet来激活。

  采用Oracle复制管理器,用于复制的对象组可以通过一些鼠标操作非常简单地定义。复制组可以包含表和其他相关的对象,如触发器,存储过程,索引,视图,同义词以及序列等。Oracle除了可以复制每个复制组的全部拷贝以外,还可以选择复制数据的子集。复制组的配置可以在任何时候修改,这种变化将自动应用到其他所有的复制节点。

  一旦定义了对象组,可以通过Oracle复制管理器,简单进行拖拉操作,就可自动部署复制组到一个新的节点。这些快照节点既可以是只读的也可以是可更新的。复制节点配置完成以后,用户可以配置定时以使复制环境中的变化传播到其他节点,当然也可以选择采用同步复制。

  4.选择冲突解决方案

  如果选择采用一种可以在任何地方更新的复制方案,Oracle复制管理器提供了几个内建的冲突解决方案,诸如"最近时间戳"和"站点优先"等来解决潜在的冲突。对于不同的表可以选择不同的方法,甚至可以对一个表中的不同列选择不同的冲突消除方案。用户对于一些特殊的商业需求也可以创建自己的冲突解决方案。

  5.实时管理

  通过Oracle的复制管理器,复制环境中任何地方发生的错误均可以非常快速和简单地分离出来并且改正。通过一个单一的节点,用户就可以看到每个节点的延迟事务队列,也可以重新定时或者强制立即执行事务。另外,用户也可以利用Oracle企业管理器的事件管理功能来对复制环境进行监视,该事件管理器提供了对多个站点间的复制状态的主动监视功能,另外还提供了可以定义自动改正的选项等。

结论
  和Oracle的其他功能不同,Oracle的高级复制不是即插即用的,用户必须深刻理解它们是如何工作的以及各种复制方案的优缺点。深刻理解复制的基本概念可以帮助你设计一个可靠的复制环境。


http://www0.ccidnet.com/tech/guide/2001/03/28/58_1900.html
http://www0.ccidnet.com/tech/guide/2001/03/28/58_1901.html

一、 Oracle Data Guard


  Oracle9i推出了一种功能强大,更能有效地实施灾难恢复的解决方案 Oracle Data Guard


  Oracle Data Guard 采用主数据库正常运行,一或多个备用数据库进行备份的方式保护数据库,备用数据库的备份、管理和监视工作都是自动完成的,当主数据库宕机发生时,至少有一个备用数据库马上投入使用,使应用程序的运行不会间断,避免了系统的瘫痪。


(一)、Data Guard的功能简介


1.数据库的切换


  允许DBA将主数据库切换到备用数据库,此备用数据库变为主数据库,响应用户的请求,而原主数据库变为备用数据库。Data Guard的这种特性保证了数据不会丢失,避免数据库恢复期间无法处理用户的请求。


2.通过分布式组态,增强数据库的可用性


  Oracle Data Guard是由主数据库和一到多个备用数据库构成,这些在Data Guard的环境中称为站点,通常各个站点以松散的方式分布在各地,以网络连接,所以,即使遇到地震、火灾、洪水等自然灾害,数据库的数据也会得到很好地保护。Data Guard的结构由下图所示:



3.同步主站点与备用站点的数据


  在Data Guard环境中,将一个站点设置为主站点,用来响应用户的请求,事务对数据库所做的修改,以归档日志的形式由日志传输服务自动从主站点传送到各个备用站点,以实现备用站点与主站点的同步。


4.防止数据库的物理损坏


  由于主站点的物理损坏不可能通过归档日志文件传输到备用站点,所以降低了由物理损坏带给数据库的风险。


(二)、数据库的切换


  将主数据库切换到备用数据库,此备用数据库变为主数据库,而原主数据库变为备用数据库。数据库的切换可以从主数据库角色切换到备用数据库角色,也可从备用数据库角色切换到主数据库角色。


1.主数据库的工作模式:


Guaranteed protection:

规定在修改主数据库时,至少有一个备用数据库有效。假如主备之间的连接中断,通过中断主实例来禁止数据的分歧,保证无数据丢失。这种模式对数据库性能的影响最大。

Instant protection :

规定在修改主数据库时,至少有一个备用数据库有效。与 Guaranteed protection 模式不同的是当主备之间的连接中断,允许数据分歧,并当恢复连接后,解决数据分歧的现象。无数据丢失,对主数据库的性能有较小的影响。

Rapid protection :

指出主数据库的修改在备用数据库上有效。有数据丢失,最小化对数据库性能的影响。

Delayed protection :


指出主数据库的修改最终在备用数据库上有效。 Rapid protection 和 Delayed protection 模式即使在网络连接有效时,也允许主数据库与所有的备用数据库有数据分歧,数据的丢失量等同于主数据库联机重做日志的未归档数。最小化对数据库性能的影响。


四种模式的区别详见下表:



































































主数据库


保护模式


保护策略


网络连接


主数据库


操作状态


Switchover


Failover


Guaranteed


保护


连接


无数据分歧


无数据丢失


无数据丢失


未连接


关闭实例


不可能


无数据丢失


Instant


未保护


连接


无数据分歧


无数据丢失


无数据丢失


未连接


Delayed


保护模式


不可能


数据丢失


Rapid


未保护


连接


存在数据分歧


无数据丢失


数据丢失


未连接


Delayed


保护模式


不可能


数据丢失


Delayed


未保护


连接


存在数据分歧


无数据丢失


数据丢失


未连接


存在数据分歧


不可能


数据丢失


2.备用数据库的工作模式:


Managed recovery mode :

最大化保护数据,主数据库将联机重做日志归档到备用数据库,备用数据库自动应用这些日志进行数据库的恢复。

Read-only mode :

备用数据库不能应用归档日志。在这种模式下,只能对备用数据库进行查询。当备用数据库重新处于mount方式,主数据库继续将日志归档到备用数据库上。

  虽然备用数据库不能同时处于两种模式,但可在两种模式间进行切换。在大多数的Data Guard环境中,备用数据库应处于恢复管理模式。


3 . Failover 和 Switchover 的区别


Failover :



  • 将主数据库offline,备用数据库online,这种操作由系统和软件失败引起。
  • 即使在备用数据库上应用重做日志,也可能出现数据丢失的现象,除非备用数据库运行在 guaranteed protection 模式。
  • 原主数据库重新使用时必须重新启动实例。
  • 其它的备用数据库也需重新启动实例。

Switchover :



  • 故意将主数据库offline,而将另一备用数据库online,它能够切换到备用数据库而不需同步操作。如:可使用 Switchover 完成系统的平滑升级。
  • 即使在备用数据库上不应用重做日志,也不会造成数据的丢失。
  • 数据库不需重新启动实例。这使主数据库几乎能立即在备用数据库上恢复它的功能,因此可经常进行定期维护而不需中断操作。

  Failover和Switchover的区别为:当Failover发生,备用数据库切换为主数据库之后,它丢失了备用数据库的所有能力,也就是说,不能再返回到备用模式;而Switchover可以,备用数据库可切换为主数据库,也可从主数据库再切换回备用数据库。


4.主数据库与备用数据库的切换


  当主数据库操作在 Guaranteed protection 和 Instant protection 两种模式下,可保证数据库在切换的过程中不丢失数据,这意味着主数据库的所有归档日志都必须应用在备用数据库上。假如归档日志没有完全应用,或主数据库工作在 Rapid 和 Delayed protection 模式,数据库的切换将导致数据的丢失,数据丢失的总量可由主数据库归档日志路径属性和备用数据库归档日志的应用来决定。


二、 ORACLE 的高级复制技术


1.基本概念


  复制,顾名思义就是将数据库中的数据拷贝到不同物理地点的数据库中以支持分布式应用,它是整个分布式计算解决方案的一个重要组成部分。


2.高级复制技术的基本结构


  实体化视图在以前的Oracle 版本中叫做“快照”。它被用来复制数据到复制环境中的非主站点。


  实体化视图可以是只读的、可更新的或者是可写的。


(1) 只读实体化视图


  在一个基础结构中,实体化视图可以提供只读的访问表数据,这个表数据来源于一个主体站点或者一个主实体化视图站点。应用程序可以避免访问主体站点和不考虑网络是否可用,它可直接向只读实体化视图请求数据。下图表示只读实体化视图



(2) 可更新的实体化视图


  在一个更高级的结构中,可以创建一个可更新的实体化视图,它允许用户通过在这个可更新的实体化视图上的插入、更新和删除行的操作,来进行同样的插入、更新和删除主表或者主实体化视图上的行。下图表示使用可更新实体化视图



3.实现多主体复制的选择


  同步复制,复制数据在任何时间在任何复制节点均保持一致。如果复制环境中的任何一个节点的复制数据发生了更新操作,这种变化会立刻反映到其他所有的复制节点。这种技术适用于那些对于实时性要求较高的商业应用中。


  异步复制,所有复制节点的数据在一定时间内是不同步的。如果复制环境中的其中的一个节点的复制数据发生了更新操作,这种改变将在不同的事务中被传播和应用到其他所有复制节点。这些不同的事务间可以间隔几秒,几分种,几小时,也可以是几天之后。复制节点之间的数据临时是不同步的,但传播最终将保证所有复制节点间的数据一致。


  过程化复制,成批的处理应用可以在一个单独的事务中改变大量的数据。典型的行层次复制把许多数据改变加载到网络上,为了避免这种问题,一个在复制环境中的批处理应用操作可以使用过程化复制,它只用单一复制存储的过程调用来聚集数据复制品。


三、Oracle9i数据库:应用集群技术


  Oracle9i针对互联网上日益增长的在线应用市场进行了许多关键的改进,它最特别的技术就在于Oracle9i真正应用集群(Oracle9i Real Application )。作为Oracle的新一代群集技术,Oracle9i真正应用集群基于Oracle获得专利的高速缓存熔合体系结构,它能够迅速、有效地在群集的所有计算机上共享那些经常被访问的数据,以提供透明的应用可伸缩性。这一突破性技术,使Oracle9i真正应用集群能够提供超过四个节点的直线性可伸缩性。另一方面,借助Cache Fusion体系结构能够独立处理每个节点的特性,Oracle9i真正应用集群能够为电子商务应用提供令人振奋的可靠性。与其它厂商提供的集群技术相比,Oracle9i真正应用集群是利用独立的计算机专门处理特殊的计算任务,管理数据的特殊“分段”。这种集群技术能够使系统的可伸缩性、性能和可靠性获得最大程度的平衡。因此,在用户集群系统中增加计算机时,既不需要重新分配数据,也不需要重新编写应用程序,Oracle9i真正应用集群能够以透明的方式进行修改,以利用这些新的资源。


1.Real Application Clusters的体系结构


  Real Application Clusters 是由多个节点中能同时访问一个共享数据库的多个组件构成。如图:



Real Application Clusters 由下面组件构成:



  • Cluster Manager
  • The Global Cache Service and Global Enqueue Service
  • Cluster Interconnect and Interprocess Communication (Node-to-Node)
  • Disk Subsystems

  在Real Application Clusters环境中,所有的节点可在同一数据库上并发执行事务,Real Application Clusters保证每个节点访问共享数据的一致性和完整性。可以把大的事务分解为多个小事务,在不同的节点执行。它适合DSS、OLTP及混合系统。


2.Oracle9iRealApplicationClusters的特点:



  • “开箱即用”,近线性的透明缩放
  • 与其它程序的良好兼容性,无需重新设计
  • 快速增长的集群,可快速增添节点和磁盘

3.硬件组成


  采用集群数据库技术,最大程度节约硬件投资并保证企业信息存在于一个单一的数据库中。硬件与数据库的数据容量瓶颈曾经困扰企业的信息化建设。企业旧式的解决方法是不断添加成堆成堆的服务器,并让应用分散运行在多个服务器上的多个数据库上。现在的办法有所不同,比如Oracle 9i数据库采用了"集群技术"(Real Application Clusters),它能够让单一数据库同时在多台服务器上运行,而不需要对应用代码或体系结构做出任何修改,此特性极大地改善了系统可靠性:如果数据容量增大,企业可以通过增加小型服务器进行扩充;而在任何一个服务器出现故障时不会对系统造成损害,因为其他服务器可以十分轻松地分担起一部分新增加的负载。此特性还能够缩短数据库访问时间,从而改善应用性能。并使得由多台较便宜的计算机组成的IT数据中心取代昂贵的大型机成为可能,这随着CPU需求的增加能够节省近80%的硬件(在某些情况下,就是数百万美元)。Oracle数据库至今占据了Unix开放系统之下66%以上的份额,它提供了卓越的开放性能,并引领当今数据库技术标准。


高速缓存成亮点:


  Oracle9i Real Application Clusters采用了新的Cache Fusion(高速缓存熔接)技术,Cache Fusion是群集数据库技术的重大突破。在群集中,用户的请求可以被群集数据库的任何高速缓存所响应。当数据正在更新时,Cache Fusion能在各个服务器上的高速缓存之间进行协调,从而保证数据的正常读取和更新。


  如果一个查询请求由一个远程高速缓存所响应,数据块将在从一个节点到另一个节点之间的高速群集中传递,"缓存熔接"过程将自动发生。该过程对于应用是透明的,大大提高了群集的可伸缩性。


  Oracle9i Real Application Clusters几乎和已有的所有网络应用兼容,它支持群集功能,利用它可快速增加网络节点。Oracle9i Real Application Clusters为群集里的所有服务器提供透明的应用可伸缩性,从而解决了一个进程中服务器之间的争端问题。


  Oracle9i设置了一套新的标准,用以防止系统停机导致网络中断,保证系统的高可用性。这些新的功能包括灾难防止、系统错误快速恢复和人为错误的透明恢复等

oralce数据库日志查看方法探讨

研究了好几天,终于有了一个比较完整查看oracle的数据日志方法,oracle
没有想sqlserver那样有sqlE工具来辅助查询。只能利用oracle自己的工具。

一、如何分析即LogMiner解释

从目前来看,分析Oracle日志的唯一方法就是使用Oracle公司提供的LogMiner来进行, Oracle数据库的所有更改都记录在日志中,但是原始的日志信息我们根本无法看懂,而LogMiner就是让我们看懂日志信息的工具。从这一点上看,它和tkprof差不多,一个是用来分析日志信息,一个则是格式化跟踪文件。通过对日志的分析我们可以实现下面的目的:

1、查明数据库的逻辑更改;

2、侦察并更正用户的误操作;

3、执行事后审计;

4、执行变化分析。

不仅如此,日志中记录的信息还包括:数据库的更改历史、更改类型(INSERT、UPDATE、DELETE、DDL等)、更改对应的SCN号、以及执行这些操作的用户信息等,LogMiner在分析日志时,将重构等价的SQL语句和UNDO语句(分别记录在V$LOGMNR_CONTENTS视图的SQL_REDO和SQL_UNDO中)。这里需要注意的是等价语句,而并非原始SQL语句,例如:我们最初执行的是“delete a where c1 <>'cyx';”,而LogMiner重构的是等价的6条DELETE语句。所以我们应该意识到V$LOGMNR_CONTENTS视图中显示的并非是原版的现实,从数据库角度来讲这是很容易理解的,它记录的是元操作,因为同样是“delete a where c1 <>'cyx';”语句,在不同的环境中,实际删除的记录数可能各不相同,因此记录这样的语句实际上并没有什么实际意义,LogMiner重构的是在实际情况下转化成元操作的多个单条语句。

另外由于Oracle重做日志中记录的并非原始的对象(如表以及其中的列)名称,而只是它们在Oracle数据库中的内部编号(对于表来说是它们在数据库中的对象ID,而对于表中的列来说,对应的则是该列在表中的排列序号:COL 1, COL 2 等),因此为了使LogMiner重构出的SQL语句易于识别,我们需要将这些编号转化成相应的名称,这就需要用到数据字典(也就说LogMiner本身是可以不用数据字典的,详见下面的分析过程),LogMiner利用DBMS_LOGMNR_D.BUILD()过程来提取数据字典信息。

LogMiner包含两个PL/SQL包和几个视图:

1、dbms_logmnr_d包,这个包只包括一个用于提取数据字典信息的过程,即dbms_logmnr_d.build()过程。

2、dbms_logmnr包,它有三个过程:

add_logfile(name varchar2, options number) - 用来添加/删除用于分析的日志文件;

start_logmnr(start_scn number, end_scn number, start_time number,end_time number, dictfilename varchar2, options number) - 用来开启日志分析,同时确定分析的时间/SCN窗口以及确认是否使用提取出来的数据字典信息。

end_logmnr() - 用来终止分析会话,它将回收LogMiner所占用的内存。

与LogMiner相关的数据字典。

1、v$logmnr_dictionary,LogMiner可能使用的数据字典信息,因logmnr可以有多个字典文件,该视图用于显示这方面信息。

2、v$logmnr_parameters,当前LogMiner所设定的参数信息。

3、v$logmnr_logs,当前用于分析的日志列表。

4、v$logmnr_contents,日志分析结果。

二、Oracle9i LogMiner的增强:

1、支持更多数据/存储类型:链接/迁移行、CLUSTER表操作、DIRECT PATH插入以及DDL操作。在V$LOGMNR_CONTENTS的SQL_REDO中可以看到DDL操作的原句(CREATE USER除外,其中的密码将以加密的形式出现,而不是原始密码)。如果TX_AUDITING初始化参数设为TRUE,则所有操作的数据库账号将被记录。

2、提取和使用数据字典的选项:现在数据字典不仅可以提取到一个外部文件中,还可以直接提取到重做日志流中,它在日志流中提供了操作当时的数据字典快照,这样就可以实现离线分析。

3、允许对DML操作按事务进行分组:可以在START_LOGMNR()中设置COMMITTED_DATA_ONLY选项,实现对DML操作的分组,这样将按SCN的顺序返回已经提交的事务。

4、支持SCHEMA的变化:在数据库打开的状态下,如果使用了LogMiner的DDL_DICT_TRACKING选项,Oracle9i的LogMiner将自动对比最初的日志流和当前系统的数据字典,并返回正确的DDL语句,并且会自动侦察并标记当前数据字典和最初日志流之间的差别,这样即使最初日志流中所涉及的表已经被更改或者根本已经不存在,LogMiner同样会返回正确的DDL语句。

5、在日志中记录更多列信息的能力:例如对于UPDATE操作不仅会记录被更新行的情况,还可以捕捉更多前影信息。

6、支持基于数值的查询:Oracle9i LogMiner在支持原有基于元数据(操作、对象等)查询的基础上,开始支持基于实际涉及到的数据的查询。例如涉及一个工资表,现在我们可以很容易地查出员工工资由1000变成2000的原始更新语句,而在之前我们只能选出所有的更新语句。

三、Oracle8i/9i的日志分析过程

LogMiner只要在实例起来的情况下都可以运行,LogMiner使用一个字典文件来实现Oracle内部对象名称的转换,如果没有这个字典文件,则直接显示内部对象编号,例如我们执行下面的语句:

delete from "C"."A" where "C1" = ‘gototop’ and ROWID = 'AAABg1AAFAAABQaAAH';
如果没有字典文件,LogMiner分析出来的结果将是:
delete from "UNKNOWN"."OBJ# 6197" where "COL 1" = HEXTORAW('d6a7d4ae') and ROWID
= 'AAABg1AAFAAABQaAAH';



如果想要使用字典文件,数据库至少应该出于MOUNT状态。然后执行dbms_logmnr_d.build过程将数据字典信息提取到一个外部文件中。下面是具体分析步骤:

1、确认设置了初始化参数:UTL_FILE_DIR,并确认Oracle对改目录拥有读写权限,然后启动实例。示例中UTL_FILE_DIR参数如下:

SQL> show parameter utl
NAME                         TYPE        VALUE
------------------------ ----------- ------------------------------
utl_file_dir                 string      /data6/cyx/logmnr



这个目录主要用于存放dbms_logmnr_d.build过程所产生的字典信息文件,如果不用这个,则可以不设,也就跳过下面一步。

2、生成字典信息文件:

exec dbms_logmnr_d.build(dictionary_filename =>'
dic.ora',dictionary_location => '/data6/cyx/logmnr');



其中dictionary_location指的是字典信息文件的存放位置,它必须完全匹配UTL_FILE_DIR的值,例如:假设UTL_FILE_DIR=/data6/cyx/logmnr/,则上面这条语句会出错,只因为UTL_FILE_DIR后面多了一个“/”,而在很多其它地方对这一“/”是不敏感的。

dictionary_filename指的是放于字典信息文件的名字,可以任意取。当然我们也可以不明确写出这两个选项,即写成:

exec dbms_logmnr_d.build('dic.ora','/data6/cyx/logmnr');

如果你第一步的参数没有设,而直接开始这一步,Oracle会报下面的错误:

ERROR at line 1:
ORA-01308: initialization parameter utl_file_dir is not set
ORA-06512: at "SYS.DBMS_LOGMNR_D", line 923
ORA-06512: at "SYS.DBMS_LOGMNR_D", line 1938
ORA-06512: at line 1



需要注意的是,在oracle817 for Windows版中会出现以下错误:

14:26:05 SQL> execute dbms_logmnr_d.build('oradict.ora','c:\oracle\admin\ora\log');
BEGIN dbms_logmnr_d.build('oradict.ora','c:\oracle\admin\ora\log'); END;
*
ERROR at line 1:
ORA-06532: Subscript outside of limit
ORA-06512: at "SYS.DBMS_LOGMNR_D", line 793
ORA-06512: at line 1



解决办法:

编辑"$ORACLE_HOME/rdbms/admindbmslmd.sql"文件,把其中的
TYPE col_desc_array IS VARRAY(513) OF col_description;
改成:
TYPE col_desc_array IS VARRAY(700) OF col_description;



保存文件,然后执行一遍这个脚本:

15:09:06 SQL> @c:\oracle\ora81\rdbms\admin\dbmslmd.sql
Package created.
Package body created.
No errors.
Grant succeeded.



然后重新编译DBMS_LOGMNR_D包:

15:09:51 SQL> alter package DBMS_LOGMNR_D compile body;
Package body altered.
之后重新执行dbms_logmnr_d.build即可:
15:10:06 SQL> execute dbms_logmnr_d.build('oradict.ora','c:\oracle\admin\ora\log');
PL/SQL procedure successfully completed.



3、添加需要分析的日志文件

SQL>exec dbms_logmnr.add_logfile( logfilename=>'
/data6/cyx/rac1arch/arch_1_197.arc', options=>dbms_logmnr.new);
PL/SQL procedure successfully completed.



这里的options选项有三个参数可以用:

NEW - 表示创建一个新的日志文件列表

ADDFILE - 表示向这个列表中添加日志文件,如下面的例子

REMOVEFILE - 和addfile相反。

SQL> exec dbms_logmnr.add_logfile( logfilename=>'
/data6/cyx/rac1arch/arch_2_86.arc', options=>dbms_logmnr.addfile);
PL/SQL procedure successfully completed.



4、当你添加了需要分析的日志文件后,我们就可以让LogMiner开始分析了:

SQL> exec dbms_logmnr.start_logmnr(dictfilename=>'/data6/cyx/logmnr/dic.ora');
PL/SQL procedure successfully completed.



如果你没有使用字典信息文件(此时我们只需要启动实例就可以了),那么就不需要跟dictfilename参数:

SQL> exec dbms_logmnr.start_logmnr();
PL/SQL procedure successfully completed.



当然dbms_logmnr.start_logmnr()过程还有其它几个用于定义分析日志时间/SCN窗口的参数,它们分别是:

STARTSCN / ENDSCN - 定义分析的起始/结束SCN号,

STARTTIME / ENDTIME - 定义分析的起始/结束时间。

例如下面的过程将只分析从 '2003-09-21 09:39:00'到'2003-09-21 09:45:00'这段时间的日志:

SQL> exec dbms_logmnr.start_logmnr(dictfilename=>'/data6/cyx/logmnr/dic.ora' , -
starttime => '2003-09-21 09:39:00',endtime => '2003-09-21 09:45:00');
PL/SQL procedure successfully completed.



上面过程第一行结尾的“-”表示转行,如果你在同一行,则不需要。我们可以看到有效日志的时间戳:

SQL> select distinct timestamp from v$logmnr_contents;
TIMESTAMP
-------------------
2003-09-21 09:40:02
2003-09-21 09:42:39



这里需要注意的是,因为我之前已经设置NLS_DATE_FORMAT环境变量,所以上面的日期可以直接按这个格式写就行了,如果你没有设,则需要使用to_date函数来转换一下。

SQL> !env grep NLS
NLS_LANG=american_america.zhs16cgb231280
NLS_DATE_FORMAT=YYYY-MM-DD HH24:MI:SS
ORA_NLS33=/oracle/oracle9/app/oracle/product/9.2.0/ocommon/nls/admin/data
使用to_date的格式如下:
exec dbms_logmnr.start_logmnr(dictfilename=>'/data6/cyx/logmnr/dic.ora',-
starttime => to_date('2003-09-21 09:39:00','YYYY-MM-DD HH24:MI:SS'),-
endtime => to_date('2003-09-21 09:45:00','YYYY-MM-DD HH24:MI:SS'));



STARTSCN 和ENDSCN参数使用方法类似。

5、好了,在上面的过程执行结束之后,我们就可以通过访问与LogMiner相关的几个视图来提取我们需要的信息了。其中在v$logmnr_logs中可以看到我们当前分析的日志列表,如果数据库有两个实例(即OPS/RAC),在v$logmnr_logs中会有两个不同的THREAD_ID。

而真正的分析结果是放在v$logmnr_contents中,这里面有很多信息,我们可以根据需要追踪我们感兴趣的信息。后面我将单独列出来讲常见的追踪情形。

6、全部结束之后,我们可以执行dbms_logmnr.end_logmnr过程退出LogMiner分析过程,你也可以直接退出SQL*PLUS,它会自动终止。

 

About this Archive

This page is an archive of entries from December 2005 listed from newest to oldest.

November 2005 is the previous archive.

January 2006 is the next archive.

Find recent content on the main index or look in the archives to find all content.