jh's profile柔嘉维则@life.oracle.engPhotosBlogLists Tools Help

Blog


    January 31

    (转)oracle ace 谈数据库技术学习

    【IT168技术资讯】
        主持人: 由于时间的关系我们就不多讲了,最后一个问题我想让大家跟网友们分享一下学习Oracle的经验,包括推荐一些好的书。跟网友分享一下学习Oracle的经验。
        石树斌: 我很早就接触Oracle了,从Oracle7版本就开始了,但是我觉得我做的比较杂,从应用开发、数据库、项目管理、销售等,很多都做。
        我真正喜欢Oracle是2000年。2000年,当时听说有一个Oracle技术最牛的人,前两年还搞一个培训,他原来在邮政银行,一个批量两个半小时,他去以后,8i的数据库,调了几个参数,只需要十几分钟就弄完了。那个时候我就比较感兴趣,觉得很神奇,后来就上ITPUB,因为ITPUB是国内公认Oracle技术最好的论坛。上ITPUB去看一些问题,当然自己也多看了一些别的书,论坛上交流是很重要的。
        我这里有几本书,自己看过觉得都还不错,其中有盖国强写的一本书《深入浅出Oracle》,《Oracle数据库性能优化》。另外,在学习方面,我知道biti是有两年一个帖子都没放过,所以这个很重要,学习的过程大家吃点苦肯定会有回报。
        冯春培: 这种东西就是说,其实当时就是因为你自己没有环境,我不干这个,我是做pro c开发的,没有数据库给你管,你也不是数据库管理员,那怎么办呢?就去看别人的问题,尝试着去理解别人的问题,然后尝试去引导别人解决问题,这个很重要。很多人他只看,不上论坛,不沟通,他只看书,但是当你要想引导人家去解决这个问题,当把你的想法表达出来让别人来理解你时,这个学习比你只看不说是完全不一样的,为什么很多人会觉得培训讲课自己收获非常大,那是因为你会发现自己有很多很多的漏洞,然后你会去尝试弥补这些漏洞,这样你自己的收获是最大的。不光自己要学,还要把学的东西share给大家,表达给大家,让别人明白,你在这个过程中受益是非常大的。当然这只是一个角度,学习这个东西大家以前都谈了很多了,我只是强调这一点。顺着这个话题说一下这种看法,不希望大家都去潜水,如果你想要学好的话千万不潜水。
        楼方鑫: 我觉得像biti说的挺好的,其实我会换一种思维,就是他把自己的成绩建立在别人的痛苦之上,别人犯了错,他去欣赏,其实这中间你要看到别人的东西,你要去思考,你要尝试想办法解决,这个是很重要,这个跟你讲课是一样的道理。
        我很清楚地记得2000年的时候,我给别人上培训课,在第三堂课时,对学生说,这堂课,你们其中的所有人,加起来学到的东西,都没有我学到的东西多。这样你会发现你要回答别人的问题,到最后真正你完全解决的时候,你会发现你会学到很多东西,也可能比你发问学到更多的东西,你很负责任地去查资料,尽量回答准确,而不是你来管理机器,专门入库,这样肯定不行。
        主持人: 这就是说,其实我们个人在工作当中不可能遇到这些所有不同的问题,只要把人家的问题当做自己的问题,你才能不断提高。
        黄老师: 社区就是用来交流经验嘛。
        楼方鑫: 其实就是说你当一个DBA,一开始你会遇到很多问题,但是慢慢的你会很难遇到问题,因为你把它变好了之后,你只有从别人那儿学习经验,看到别人的痛处,权当成你的开心了。
        主持人: 我觉得大辉自己个人网站写的东西是非常好的,你这边有没有什么学习经验跟大家分享一下。
        冯大辉: 我现在觉得,善于总结还是比较重要的,因为现在网上有各种渠道,这个信息量是相当大的,自己要适当做一些过滤和取舍。有的时候包括经常网上看到所谓的解决方案,但是不清楚到底这个东西搞下去之后,整个系统还是会弄得一塌糊涂。另外,多听取一些其他人的经验,或者站在其他人的角度考虑他当时弄出这个,或者如何解决这个问题的。从DBA的角度换位思考可能也会更方便。
        楼方鑫: 我补充一下,其实我们的目标不是拷贝下来,Save下来就好了,而是要真正的理解,这是非常重要的,我可以把它处理掉。但是整个拷贝下来,你会发现拷贝久了这个东西你是根本不会看的。
        冯春培: 这个东西就像我原来有一段时间,我去研究Oracle internal,我自己研究的,到现在我都很清楚地记得这个东西是怎么回事。三四年过去了,每一个细节我都记得很清楚,Oracle的DSI,那玩意儿的教材,内部流程,我跟你说,我就看过两页,其中两页是为了帮别人去找一个问题,我去查了两页,其他的我一律都没看过。因为我觉得看了DSI,再去看那个东西没用,一个星期忘不了,两个星期就忘了。
        楼方鑫: 其实像研究block格式,我从来没有看过DSI,我以前下载过,但是文档丢了,一个键全部删掉了。
        冯春培: 资料像很多东西只是你长久的测试或者是思考,有时候有些东西不是很有把握,然后某一个资料终于证明了我的想法,这个时候你豁然开朗,一千个问题一下迎刃而解,但是一开始就看资料的话。
        楼方鑫: 其实最关键的是,你看到他们的资料之后,能用自己的方法去印证它,这是很重要的。
        黄老师: 那么我觉得block结构里面有一些东西是很好猜的,但是有一些是不大好猜的。
        楼方鑫: 这个问题我很清楚的记得,我研究Block格式的时候曾经遇到过。我最近遇到的难题就是我把Block的每个字段,都是靠新的词儿,把那个分出来,我打印了一套Block格式,然后那次停住了,没事儿我就看两眼,没事儿再看两眼,结果过了一个月,有一天我在火车上。就那15分钟突然明白了,但是当时确实开心,整个人浑身轻松了。这个东西要完全用你自己的方法去研究,而不是你去千方百计找资料。我当时从来没有想过会有资料一步一步告诉你去怎样做。你还是要自己去发现它。
        黄老师: 张乐奕(kamus)也说一下,我觉得张乐奕(kamus)的经历会比较典型,因为他是一个文科书生,他是学日语的,然后现在是Oracle专业工程师。
        张乐奕(kamus): 其实一定要有热情,我举一个例子,前不久我刚碰到一个国内很大型的企业,国内的企业,也是这次Oracle Open World的赞助商之一,名字我不说了,当时我在一家很小型的公司里工作的时候,这个公司曾经是我的目标,就是我特别想去这样一个国内的大型企业,前不久碰到这个大型企业的工程师,他聊天时候就跟我说,他说我特别想进Oracle,跟我说了很多,后来第二天,客户要装一个东西,装了grid control,然后他做的事情就是下载好了,他说你来装grid control吧,我当时觉得很奇怪,如果这是在我之前,我从来没有装过的东西, 我会非常希望有这样一个机会让我去练手,这份经验是很难得的,因为不可能让你再有一个小型机,你自己的PC上你去装一份grid control。
        我记得很清楚,就是在我进入Oracle公司之后,因为Sql backup刚推出来不久,我们一个客户,应该是国内很早的,要试用这个Sql backup,但是不是我们部门的事儿,他们找的OSS,但是因为我听到了这个事儿,我特意的自己给客户打电话,我说没关系,ORACLE工程师可以在那装,但是我能够过去看一下,我觉得仍然对Oracle抱有很大的热情,我觉得这是非常重要的,你不能只是抱怨,仅仅一件小的事情,当一个你能赚取到经验的机会降临到你的头上推出来,让我去做,这样的话你可能永远会在这样的公司。
        我觉得就是说,你一定要去热爱一个东西,很多人可能只是把Oracle当做一个谋生的,手段会觉得比programer赚钱更多,所以我要去做DBA,可能就是这样去想,但是这样的我相信你做的不会太好,也许你可能会做sales,做别的东西,但是我觉得你不会做的很好的DBA,所以热情是一定要的。
        当时我想学Oracle的时候,大概我花一年的时候去考OCP,很多人都认为考OCP有什么意义,很多人说OCP这种东西总共就一百来道题,背一套下去,99分很快就拿到了,其实对我来说,当时考OCP就是一个学习的动力,因为交了钱你就一定要考过去,这就是给自己学习的动力,那时候我每天白天要写程序,然后晚上回去学会花两个小时,周末的时候,除了周末每天晚上会花两个小时去看student guide,然后周六、周日会全天的看student guide,然后自己做实验。我记得很清楚,刚开始的时候,我的很多问题是eygle,然后还有Biti,他们有回答,那时候我在数据库的OCP吧,就是渐渐的你会发现当时自己从一个提问者变成一个回答问题的时候,这种分享的快感和你成长的快感,你会觉得是非常值得的。
        盖国强: 我个人觉得,包括刚才大家都说这么多,我觉得有一点共同,就是大家对这个技术,或者对Oracle这个产品抱有极大的兴趣,或者对你从事的这份工作,不管你研究数据库、存储、操作系统,,自己所做的事情都抱有极大的兴趣,而且我一致认为,兴趣是最好的老师,有兴趣在引导着你,去激励着你,这样的话不管你去学习,你去探索,包括一个Block看了几个月,我觉得这个东西很大一部分是由兴趣推动的,如果你对这个东西不感兴趣,只是作为一个谋生的手段,我觉得很多人的研究就是浅尝辄止,你无法深入,你无法深入你就无法……
        张乐奕: 因为你从一件事情没有办法获得愉快感觉的话,你一定会放弃它的,你觉得它只是我要去做这件事情,你一定会放弃他。
        盖国强: 所以刚才讨论的问题就是说,Oracle越来越自动化了,就是说DBA以后会不会没有工作,或者是找不到工作,或者是就业形势不好。实际上我回过头来说,我反而觉得这个软件更加自动化了,反而是一个机会,是一个机遇,这是个什么概念呢?我是觉得一个软件虽然更加自动化了,但是那些晚来的人,后接触的人,他可能越来越不知道这个数据库真正的运行原理和机制,那么你那些更早来接触的,或者你学习研究更深入的人,你就能更深入了解它的运行机制,运行原理,那么你比别人拥有更多的底蕴,你能够解决更深层次的问题,我觉得反而对于先来者和先入者,还是有好处的。
        楼方鑫: 这个是有好处的,这个东西你要去找高手的话,他们的代价是非常非常高的。
        张乐奕: 开始对Oracle感兴趣的时候,sql expert那个叫做什么工具来的?
        楼方鑫: sql expert。
        张乐奕: 那是我刚开始对Oracle数据库感兴趣,那时候我们公司也只有我知道Oracle是这么样一个东西,大概有些什么可以自己独立地安装Oracle的数据库,只有我可以。然后写程序,那时候说一个SQl tuning一下,那我会把SQl放进去,然后按一下run,然后比一下,我记得很清楚它有一个SQl,从十几分钟一下调到了几秒,然后我当时就会把这个SQl直接给研发人员,我说你就用这个SQl,然后开发人员一看,效率真的很高。这个得到了第一点是我在公司的形象提升了,这是第一点,因为其实他不知道我只是按了一个run就出来了这个东西,但是第二点,我就发现这个SQl是怎么调的,它把一个索引后面加了竖线,再加了两个单引号,当时我根本不知道这是什么含义,现在我知道了,就是把这个索引禁止掉了,等于是没有索引了。所以我就觉得如果Oracle也自动到这样的程度,你只能说是我能给你好的结果,但是为什么你可能就不知道了,别人问你,你干嘛给我这个SQl,你感觉是什么意思?你不知道。
        盖国强: 有一回一个人问我一个问题,sql的执行计划很奇怪,可能在9203和9204上是完全不同的一个效果,然后我还让他把英文的数据给我导出来一份,那份数据我现在还留着,我就会在我的环境下来测试这到底是一个什么样的效果,所以我觉得另外一点,对于学习来说是非常重要的,就是一个求知的欲望,大家要有一个很好的求知欲望,你有探索这个这个的兴趣、冲动,对知识的一种渴望,然后你才能够不断地去探索,我觉得这个是非常重要的。
        楼方鑫: 其实现在很多人只是怕Oracle,觉得Oracle太复杂了。
        盖国强: 我觉得跟一个人的学习态度是有关系的,你的态度,你的求知,比如说一个DBA,我们说一个好的DBA你必须要研究这个存储和操作系统,你都要去研究,你才能更好地掌握和管理这个数据,但是很多人不是这样的,他觉得这个操作系统跟我没有什么关系,出了一点问题把SA喊过来,改一个参数,SA一个人来做这个事情,这样的话,我觉得从公司层面来说是另外一回事儿,但是从个人求知的角度来说这不是一种好的态度,你必须是对这些知识具有一种很active 。
        张乐奕: 确实Oracle越来越复杂,8i的时候,以前是五个进程多清爽,现在……!
        盖国强: 你这个说起来,就是说什么样的公司用什么样的产品,这有一个很重要的概念,一个前提,比如阿里巴巴他们还用9i,自己也调整优化的很好,但是你可能觉得这个后台这么多的进程在跑,还是影响我,对不对? 但是没有那么多资深的DBA在那儿管理,能不能用好,没有一个比较好的DBA,可能8i你会用得很差。所以看现在很多用户都用Oracle7,基本的功能都能够满足我的需要。
        主持人: 好了,由于时间的关系,我们今天的讨论就到此结束。我记得上次跟小盖我们在一起时,说过这样一句话, “Oracle数据库就像一座迷宫,尽管如此,在这个迷宫当中,我们总是能够找到答案和出路,总是能够找到惊喜。”
        今天的Oracle Open World大会,我们看到是一个Open的大会,那么我们也希望Oracle这个数据库更加的开放,让我们这些痴迷的开发者们,在这个迷宫里面永远能够找到快乐! 好,感谢大家!
    November 06

    谁能告诉我,感觉它是什么东西

    1年前我在一家公司面试,我说我对oracle有感觉,就因为这句话,对方咄咄逼人否定了我。
    1年后我去一家公司面试,对方说我少一点感觉,于是也......
     
    谁能告诉我,感觉它是什么东西。每个人有每个人的眼光和局限,感觉是不是也跟着每个人的姓?
     
    我从来不愿跟人分担我的辛苦,只愿跟人分享我的结果。可如今,我郁郁,傻傻。突然想起,自从认识lg,我的一切完全变化,包括,工作,我是否还执着?我是否还应该执着?
    September 11

    关注oracle 11g重要新特性

    前言
     
        oracle7月11日在美国纽约发布了11g版本,可惜迟迟没有可公开下载的版本,只有加入oracle的测试计划的合作客户才可以得到beta版本试用。但这并不妨碍oracle爱好者们根据一些流传出来的文档来了解oracle 11g。7月30日开始的上海oracle open world,oracle宣称11g是30年来最重要的一次版本发布。对这样一个噱头我们还是比较冷静的看待的。OOW期间在一个采访oracle ACE 的活动中,我们几个ACE都不大赞同这样一种说法,其实oracle 一直以来都在前进,不断地改进以满足客户的需要。应该说,11g达到了许多客户所期望的目标,是一个关注细节的版本。那么11g到底有哪些重要的值得关注的地方呢,不妨挑一些特性做个简要分析。
     
     
    关注应用、关注性能
     
        SQL replay
     
        OOW后 rich Niemiec(www.tusc.com) 先生趁着来中国的机会各地巡游,期间到了我们公司,他问我在oracle 数据库的使用中我最大的困难是什么?我最大的困难是应用为了应对多变的商业需求,频繁地发布。而应用变化则带来schema的变化,尤其严重的是对于数据库来说可能需要新增加index。增加index绝对是一件危险的事情,这本是为了优化查询而增加,但却可能导致原来的某些查询选择了错误的index,运气好则是应用性能少量下降,运气不好则是数据库立即crash!每年这么多变化,我如何来保证每次都是正常的?数据库可靠性要求很高,任何意外都不是我所期望的。为了避免这种情况,通常我们会尽力在测试环境中做尽量多的测试。但任何的变化若都要进行回归测试,QA通常都是比较紧缺的资源。这种现状,中外都一样,只是我们通常没老外做的好。
        那么这件事情跟SQL replay有什么关系呢。我们来看看这个功能,在系统中捕获某个时段所运行的所有SQL,然后我们可以搭建一个和当前系统一样的测试环境,这样我们可以在测试环境中做我们想做的事情,如增加index,准备好之后我们可以重现搜集时段内数据库所执行的SQL(replay)。 通过观察replay期间的表现和性能信息,我们可以方便的看到哪些sql性能降低了,然后做出修正再replay,直到满意为止。这样做的好处是,我们可以不再倚赖于QA资源。要知道对于一个复杂庞大的系统,做回归测试工作量巨大。Oracle这个特性为我们提供了方便。
     
        Database workload capture and replay
     
        这一项与SQL replay不同的是搜集了整个数据库的负载情况。比如我们曾经出现过一个存储系统IO能力表现不佳的情况,厂商为了证明存储性能新搭建了一套环境,但我们却很难把真实应用放到新环境中去测试。最多也只是使用一些工具来模拟。后来打算换新存储,实际上在新系统上线前,我们无法预测新存储的表现到底能好到什么程度,这就存在着风险。如果有了Database workload capture and replay 这项功能,那么我们的困难也将迎刃而解。包括数据库要升级,也可以通过这个功能来做很好的性能预测。
     
        Result Set Caching
     
        这项功能的推出,再次表明oracle对细节的关注程度。当然,换个角度来讲,现代关系型数据库和计算机技术的发展,一直没有出现重大的突破,都是在几十年前的基础上不断地升级、修补。现在已经关注到客户应用的一些非常具体的需求上。这点其实从很多oracle有关执行计划的特点上也能看出来。Oracle推出了大量的只适合某些特定情况的执行计划,优化的触角伸到了非常精细的领域。回过来说result set caching 这项功能。这其实是我们众多用户在一些特定情况下所期望的但又和早先数据库系统的设计思想不一致的地方。oracle为了满足大家的要求,做出了这么一项功能。在还没有真切地感受这项功能的好处和限制之前,我们不妨先看一看特点。这项功能可以使得用户在使用 /*+result_cache*/ 提示的情况下,将查询的结果缓存。当查询被反复地执行的时候,不再需要到表中去获取,只需要来这个存放结果的地方就可以了。实际上这跟我们当前的一些web cache 的功能非常相似。这种cache应该更倾向于对结果集比较小、查询频繁切查询语句固定的情况。问题接踵而来,如果支持频繁的变化的数据,对性能有多大的影响,在使用上到底有些什么限制?很遗憾,我无法在这里详细地解释这些问题。一切都待我们做更多的实验来检验。
     
        Invisible index
     
        这是一项非常有用的功能,oracle虽然在8i就推出了虚拟索引的功能,但是,毕竟那还只是针对某个session的执行计划的观察和调整。现在我们可以选择实实在在的创建好index但却是invisiable 的状态,DML 也依然在维护这个index。然后我们可以通过使用提示走到index上来测试性能。当我们发现一切正常的时候,可以选择将index设置为visible 状态。如果我们想drop掉某个index但又担心不保险的时候,也可以选择将index设置为invisible状态,发现有问题再设置回visible状态。这样就可以避免经历drop之后再重新create的状况,在联机事务处理的大表上,create  index是一个非常消耗资源的任务。
     
        关于性能方面的补充
     
        当然在应用性能方面除了以上几种特性外,还有很多的新的特性,如SQL Plan Management 提供能类似store outline 的功能,Auto sql tuning可以自动的协助用户来对sql进行优化,更强大的ADDM,提高lob类型数据的io性能,总之,有非常多的值得关注的内容等待大家去探索。
     
     
    关注维护、关注管理
     
        Online Patch
     
        作为维护高可用数据库系统的DBA,最担忧的事情之一,就是遭遇无法回避的bug而被要求升级!以往升级有一个很重要的问题,那就是需要数据库停机!如果仅仅是更换rdbms obj文件并重新link,那么似乎rac可能在应用配合切换的前提下做到不停机。但如果升级需要在startup migrate下运行catpatch.sql ,则停机不可避免。虽然正常状况下这个过程不是特别长,如果在正运行的机器上使用独立的安装目录来打补丁,打完再替换原来的rdbms软件,则down time大约是替换时间加上运行catpatch.sql 的时间之和。也就是说运气不错的话能控制在5—10 分钟内。但应用的起停,往往却异常复杂。比如我们有几百台连接数据库的服务器包含了几十种形形色色的应用,做一个停机维护是一件大事。这直接就延长了down time。所以打补丁一事我们非常慎重,新上线数据库选择的版本也非常慎重。一定要选择稳定可靠的版本,应用一定要使用传统、可靠的数据库功能。这也使得很多新出来的数据库新特性我们不能及时地使用。传闻ebay一轮数据库升级大概需要2年时间,希望11g的online  patch 和Database workload capture and replay能缩短这个周期,也让DBA们能轻松一些。
        online patch 这类特性,我一直都期待数据库能实现。现在开放平台os的kernel升级基本做不到online,似乎只有存储在这方面做的不错,高端存储的软件和硬件升级都可以online(基本使用的是cluster接管交替升级模式)。主机也许因为变化太频繁以及成本原因,难以实现cluster交替升级的模式。但其实我也希望尽快研究一下oracle实现online patch的原理,是如何解决link与正在运行的程序之间的关系,以及catpatch时刻如何解决数据库内部对象的变化问题。
     
        Object dependency tracking
     
        在oracle中我们可以通过dba_dependencies查找到对象之间的依赖关系,如果被依赖的对象发生了DDL,不论这个改变是否会影响到依赖对象,依赖对象都invalid并需要重新编译。很多人在繁忙的oltp系统中遭遇过类似困境。比如表中lob的storage属性发生变化会影响到引用这个表的对象如procedure、function、trigger等。往往不经意之间,dba的一个改动,系统突然就挂了。那么11g在这方面有所改进,如果对象属性的变化不会影响到依赖对象,那么依赖对象就不会需要重新编译。
        既然oracle都实现online patch了,强烈希望将来在对象重新进行编译的时候可以手工控制,预先编译完成择机切换,类似表的online redefine一样。希望11g未来某个版本可以实现这个功能。
     
        Data Guard Snapshot
     
        这个特性是使得我们可以在standby上做出快照而保留下standby在若干时间点上状态的版本。这样我们就可以挑选某一个快照出来使用。可以做测试、可以核对数据。当然,我在netapp filesystem 上做oracle 9i版本standby snapshot 已经有几年了,这项功能我非常喜欢,可以随意open read only一个2星期甚至3星期前的数据库去查找当时的某些数据。现在11g提供了这项功能,则我们就不必局限在存储厂商所提供的快照功能上了。
     
        Query on Physical standby database
     
        这个消息犹如一个重磅炸弹,在众多资深DBA中激起了无穷的想象。Oracle在9iR2中实现了logical standby(传闻是quest工程师的支援下用logmnr实现),logical standby只能存在一个,可以被用于产生报表。如果oracle可以在物理standby上做查询,那么这个意义就重大的多。一个主数据库可以拖多个物理standby,假定采用最大数据保护模式(事务能及时地传递到standby并且立即被应用到standby),那么这跟mysql的集群类似了,一个写多个读。ebay就是在负载均衡设备F5 加quest同步工具shareplex的帮助下,实现了一个写入多个读的模式,从而支持了数据库性能的扩展,也使得数据库的维护变的更容易, 不再担心单个数据库的灾难带来致命的影响。那么现在oracle 似乎朝这个方向又迈进了一步。9iR2 提出并在10g大加宣扬的oracle streams在11g中并没有成为重点,看起来streams还不如shareplex和realsync更获得用户的认可。那么query on physical standby 看起来则是一个简单的廉价的解决方案。这个功能最终能做到什么程度,还有待实践来检验。但是,这个消息,给予了我们太多的期望!
     
        Auto Memory Tuning
     
        Oracle 从9i 开始,让PGA可以自动管理,不必为单独进程的各个pga组件设置大小,减轻了dba的工作量,让进程内存管理更容易。同时sga可以通过设置sga max size 上限,sga内部各组件可以动态调整大小,系统也根据动态统计信息给出sga组件设置大小建议。到了10g 开始可以支持sga各组件由系统自动调整分配。虽然这个功能还让大家放心不下,但毕竟自动化管理的方向是得到大家认可的。现在11g走的更进一步,sga和pga合起来可以由数据库自动分配。DBA只需要告诉oracle可以使用多少内存而不必去关注各组件的具体分配。看起来,DBA们的日子又将轻松一些。
     
        ASM and ILM
     
        存储厂商早就提出了信息生命周期管理的概念,看起来一切那么美好。当然,在存储厂商炒作这个概念的时候,我发现对于一般客户这并不是一个可行的低成本方案。我们关注新技术新概念(实际上大多都是老技术组合包装稍微加工一下就成了新技术),切实地分析其对我们能产生什么价值,实际上成本是一个非常重要的因素。Oracle 在10g中推出ASM是一个重大的新特性。但可惜ASM稳定性相对raw device还没得到用户的广泛认可。ASM 是oracle向存储管理软件延伸的一个重要标志。在我看来,除了在无传统cluster软件下做rac之外,更重要的是存储负载均衡的功能。当新增加存储设备的时候,oracle可以在系统IO相对空闲时期将数据移动到新存储设备上达到均衡分布的目的。尤其在数据仓库中这个功能非常好用。
        我一听见oracle  ILM 第一印象就是想到ASM,它应该可以配合ILM做很多的事情,ASM可以帮助DBA将不活跃数据在线迁移到其他设备上,这是信息生命周期管理的基础。oracle在不断地尝试,放弃被市场淘汰的功能,发展被市场认可的特性。
        我以前曾经多次论述oracle 跟 os之间相互学习的过程,现在看起来,数据库不仅跟os,还跟存储搅和在一起了。将来三者之间是相互竞争、相互合作的过程。不管如何,对于我们客户来说,能从中受益,那就是好事。
     
     
    后记
     
        Oracle数据库技术的发展,其实最近几年一直都在朝着关注细节的方向,如何满足客户差异化的需求,为客户提供特定环境下的最佳性能,是oracle领先于其他数据库厂商的重要原因。数据库、os、存储在某些功能上的融合,也有利于我们客户降低投资成本和管理成本。最后要感谢oracle的设计者,你们能真切地感受到客户的需求,并转变为现实。
        今年oracle将在北京、上海、广州、成都四地分别举办oracle DB 11g launch大会,9月19日在上海,开场15分钟我受邀将做一个不限制内容的演讲。从包括今年oracle open world的状况来看,oracle对中国市场的重视程度明显提高,对中国网络社区的关注程度也明显提高。希望大家可以加强交流,共同提高。
     
    May 15

    Rollback per transaction

    用这个关键词去google,结果,比如 http://www.eygle.com/statspack/statspack11.htm
     
    我来补充一点^_^
    sys@MYDB>col name for a24
    sys@MYDB>select * from v$sysstat where name in ('user rollbacks','transaction rollbacks','user commits');
    STATISTIC# NAME                          CLASS      VALUE
    ---------- ------------------------ ---------- ----------
             4 user commits                      1          3
             5 user rollbacks                    1          7
           172 transaction rollbacks           128          3
    sys@MYDB>rollback;
    回退已完成。
    sys@MYDB>select * from v$sysstat where name in ('user rollbacks','transaction rollbacks','user commits');
    STATISTIC# NAME                          CLASS      VALUE
    ---------- ------------------------ ---------- ----------
             4 user commits                      1          3
             5 user rollbacks                    1          8
           172 transaction rollbacks           128          3
    sys@MYDB>select count(*) from test;
      COUNT(*)
    ----------
            24
    sys@MYDB>rollback;
    回退已完成。
    sys@MYDB>select * from v$sysstat where name in ('user rollbacks','transaction rollbacks','user commits');
    STATISTIC# NAME                          CLASS      VALUE
    ---------- ------------------------ ---------- ----------
             4 user commits                      1          3
             5 user rollbacks                    1          9
           172 transaction rollbacks           128          3
    sys@MYDB>commit;
    提交完成。
    sys@MYDB>select * from v$sysstat where name in ('user rollbacks','transaction rollbacks','user commits');
    STATISTIC# NAME                          CLASS      VALUE
    ---------- ------------------------ ---------- ----------
             4 user commits                      1          3
             5 user rollbacks                    1          9
           172 transaction rollbacks           128          3
    sys@MYDB>insert into test select * from test;
    已创建24行。
    sys@MYDB>rollback;
    回退已完成。
    sys@MYDB>select * from v$sysstat where name in ('user rollbacks','transaction rollbacks','user commits');
    STATISTIC# NAME                          CLASS      VALUE
    ---------- ------------------------ ---------- ----------
             4 user commits                      1          3
             5 user rollbacks                    1         10
           172 transaction rollbacks           128          4
    sys@MYDB>insert into test select * from test;
    已创建24行。
    sys@MYDB>commit;
    提交完成。
    sys@MYDB>select * from v$sysstat where name in ('user rollbacks','transaction rollbacks','user commits');
    STATISTIC# NAME                          CLASS      VALUE
    ---------- ------------------------ ---------- ----------
             4 user commits                      1          4
             5 user rollbacks                    1         10
           172 transaction rollbacks           128          4
     
    这3个的解释分别是:
    user commits
      Number of user commits. When a user commits a transaction, the redo generated that reflects the changes made to database blocks must be written to disk. Commits often represent the closest thing to a user transaction rate.
    user rollbacks
      Number of times users manually issue the ROLLBACK statement or an error occurs during a user's transactions
    transaction rollbacks
      Number of transactions being successfully rolled back
     
    我们可以看到,有事务rollback 了,那么transaction rollbacks,user rollbacks 的值都会增加,如果没有事务rollback,仅仅发出命令rollback,那么user rollbacks 的值增加,transaction rollbacks 不增加。而commit 命令只有user commits 这一项统计值,在有事务commit 或者仅仅发出commit 的时候,都会增加。
     
    statspack 中的Rollback per transaction 公式为:
    Rollback per transaction% = user rollbacks / (user rollbacks + user commits)
     
    那么这个值过高,并不能说明一定是rollback 的事务过多,也不能说明对系统一定没有影响。如果你有事没事去rollback,这里的统计值就不准了。比如有些应用架构,查询完毕都发出rollback 命令,所以我们需要根据实际来分析。
     
    April 27

    2个问题

    一个是ORA-03106
    在linux 9204 上通过dblink 到远端hp unix 9206 上取数据,在某些大表上执行一段时间之后出错,数据量是取2000万中的500万:
    create table test_001 as
    select *
    from aicbs.cm_user@to_bcs
    where region_code = '571'
    ORA-03106: fatal two-task communication proto error
     
    同事在metalink 上开tar,最后的结果是需要在远端数据库打patch,但是因为某些原因不能打。
    我现在的想法是通过网络来exp/imp,也是因为某些原因未测试,如果exp 不报错的话就大功告成,否则。。。
     
    另一个是aix 5.3 9204 RAC 上一个节点down 掉了,起来又down,反复了几次,最后才没问题。
    在metalink 上找到一bug,在9208 已修复,但是也不是完全确定,现在的想法是升级到9208。
    不过升级嘛总是有风险,就像买彩票总是有中奖的可能,我想,把升级计划准备好,等到节点下次再down 掉再升级好了,反正也是RAC 环境。我除了写计划,就是祈祷老天保佑我。
     
    第3个问题是如何过一个快乐有意义的51长假。
    April 18

    凡事都是有原因的

    我们在做一个T数量级的数据库容灾项目。
    经过全库导出导入结构之后,两边数据库的对象有些不一致,包括有和没有的,有效和失效的,不一致的有近2000个,当然表和索引占多数。
    我仔细地一一检查了除'INDEX','INDEX PARTITION','TABLE','TABLE PARTITION' 之外的不一致对象,主要是一些procedure,view,原因大多是跟dblink,listener,tnsname 相关的东西有关,还有涉及到一些lob 对象的名称;此外,还可以从为什么不一致推算出来之前什么时间做了什么操作。
    所以说,凡事都是有原因的。
    April 04

    lan sql 无数

    其实我也不懂
     
      delete from get_month_total_fee_G;
      commit;
      FOR C IN (SELECT DISTINCT USER_ID FROM ALL_SUM_G_571_200703
               ) LOOP
      insert into get_month_total_fee_G
       (select ......
          from all_sum_G_571_200703 a,cfg_total_fee b
          where a.acc_code=b.acc_code
            and a.user_id=c.user_id
          group by a.user_id);
       commit;
      END LOOP;

    这个逻辑复杂啊^_^
    可改为
      execute immediate 'truncate get_month_total_fee_G';
      insert into get_month_total_fee_G
       (select ......
          from all_sum_G_571_200703 a,cfg_total_fee b
          where a.acc_code=b.acc_code
          group by a.user_id);
       commit;

    ================================================================

    SELECT ... FROM "PIONEER
    "."GET_PREPAY_USER" "A1" WHERE "A1".ROWID= (SELECT MAX("A2".ROWI
    D) FROM "PIONEER"."GET_PREPAY_USER" "A2" WHERE "A2"."USER_ID"="A
    1"."USER_ID")

    上面sql就是根据每一个USER_ID 随机取一条记录,可以改成
    select  DONE_CODE,...  from
    (select   row_number()  over(partition by  user_id order by rowid desc)  rn, A1.*
       from "PIONEER"."GET_PREPAY_USER" "A1" )
    where  rn = 1;

    ================================================================

    update user_photo_2006 a set ls_flag='流失' where not exists (se
    lect 1 from CM_USER_SNAPSHOT120_200702_571 where lose_month is n
    ot null and user_Id=a.user_id)
    update user_photo_2006 a set ls_flag='流失' where not exists (se
    lect 1 from CM_USER_SNAPSHOT120_200702_571 where lose_month is
    null and user_Id=a.user_id)

    以上2句可以合并为:
    begin
    for c in (select  /*+ ordered use_hash(a b) */  a.rowid  rid
     from  user_photo_2006 a,CM_USER_SNAPSHOT120_200702_571 b
     where  a.user_id = b.user_id(+)   and  b.user_id is null )  loop
    update user_photo_2006 set  ls_flag='流失' where  rowid =  c.rid;
    end loop;
    commit;
    end;
     
    January 31

    关于XX系统性能慢的分析和总结

    新年开始,我犯了一个严重的错误,非常自责和追悔。以下是我的检讨书,希望能够常常自省,也请大家不吝批判教训。  
     
     
         自从......以来,前台操作慢的问题一直存在,并且一直找不到原因,直到12月31号晚XXX找到并且解决了问题。问题主要不在应用,网络和存储,问题主要在数据库,是一条sql没有使用绑定变量,执行频率也不低,但是该走索引却走了全表扫描。
     
         我一直觉得数据库方面是没有什么大问题的,包括30号晚做的对几个表的move 和rebuild index,我都认为对数据库性能提高不会有太大起色。但现在看来,其实从statspack 就可以看出一点苗头,而我却忽略了。究其原因,主要有以下几点:
     
         1 沟通方面存在问题,我没有跟前台的人直接沟通过,都是从同事那里问过来的,这样导致信息不准确和不全面,比如不确定是哪个页面的操作慢,当时的判断是操作是时快时慢的,如果是数据库索引问题,一般都会是一直慢的。没有具体到前台实地考察,对问题不够重视,不够主动地帮助解决。
     
         2 对应用不了解,对应用普遍存在的没有使用绑定变量的事实没有引起高度重视,这样导致我在检查statspack 的时候没有把未使用绑定变量联系起来,只检查了别的执行代价高的sql 而忽视了这条问题sql。结果经过statpack 的检查,轻信数据库方面没有问题,没有做进一步深究。
     
         3 本来我想最后的办法是用trace 跟踪session 的具体等待,这样也能找到问题所在,但是在XXX找到问题之前我没有来得及做。
     
         总之,是我的工作方式和沟通上存在问题,对应用不够了解,对这类问题不够敏感,种种小的因素叠加在一起正好导致了严重的后果。
     
         这个事件的教训是深刻的。
     
         1 首先我在技术上,问题诊断,性能调优方面,有了深刻的感受,关于绑定变量和statspack 的关系,我想不会再犯同样的错误,在技术上要更加深入地学习。
     
         2 工作方式和态度方面,应该主动了解客户的问题和要求,主动直接和最终客户进行沟通,而不是通过其它中间环节获取信息。当这方面遇到问题时,宁可把问题当成数据库的问题,而不是说数据库看上去没有问题我就不管了。
     
         以上是我对这个事件的分析和总结。
    November 16

    读书笔记

    如磁盘上数据文件的最小io单元叫block一样,buffer cache的最小单元(或者说结构)叫buffer,每个buffer跟x$bh中每条记录有一一对应关系。
     
    从使用维护buffer这个角度讲,存在一些链表主要的有LRU list 和dirty list(checkpoint queue),当从磁盘读取数据到buffer中时,需要到LRU list上寻找free buffer,如果没有则采用LRU算法把一些buffer清空,然后继续。buffer修改后,从LRU list上移到dirty list上,dirty list根据低重做值排序,由dbwr写出到数据文件。
     
    LRU list上的latch是cache buffer lru chain,latch的数量由_db_block_lru_latches控制,当这个latch竞争激烈,可能是数据老化,全表扫描频繁。
     
    从如何搜索buffer这个角度讲,存在这么一个数据结构,有一定数量的hash bucket,每个bucket下面是一个双向链表cache buffer chain,链表上挂着一个一个buffer。如何搜索一个buffer在哪里,以及如何定位一个buffer应该放到哪里,是通过hash算法找到那个bucket,然后遍历cache buffer chain。bucket的数量由_db_block_hash_buckets控制。
     
    这个链表上的latch是cache buffer chain,latch的数量由_db_block_hash_latches控制,主要是热点块的问题,可以结合v$session_wait,v$latch_children,x$bh,v$sqltext,dba_extents找到sql。
     
    ------ ------ ------ ------
    shared pool的最小单元叫chunk,每个chunk跟x$ksmsp中每条记录有一一对应关系,chunk的状态有4种:free(空的),recreate(需要释放的),freeable(一会儿可以释放的),perm(不能释放的)。
     
    可用的chunk由一个叫free list的结构管理,它是由一定数量的bucket组成,oracle9i中有255个bucket,后面的bucket容量较前面的大。每个bucket下面是chunk list。
     
    reserved pool是单独开辟出来的供连续的大内存分配,大小由shared_pool_reserved_size决定。当需要一块内存时,先扫描free list,如果找到就分割使用,找不到就通过LRU算法释放一些recreate的,合并一些free的,如果还不够,则到reserved pool中分配一块比_shared_pool_reserved_min_alloc这个值大的空间。
     
    如果sql没有绑定变量,则一次一次地分割shared pool,很可能产生大量碎片导致ORA-04031错误。除了绑定变量,还可检查shared_pool_size,shared_pool_reserved_size,shared_pool_reserved_min_alloc这些参数的值,当然,bug也有可能。
     
    shared pool中最重要的latch是shared pool latch,library cache latch。shared pool latch是管理和搜索free list时需要获取的,在oracle9i中有7个。library cache latch是增加新的sql到library cache时需要获取的,它的数量由_kgl_latch_count控制。如果sql没有充分共享,反复解析,很容易造成这两个latch的竞争或者ORA-04031错误。解决办法是sql中尽量使用绑定变量,除此,数据库里使用cursor_sharing参数强制绑定变量,当然这个参数有副作用,或者强制刷新共享池alter system flush shared_pool,当然这个治标不治本。
     
    还有library cache pin,library cache lock,通常发生在授予权限,重编译对象,以及存在较复杂的dependence的时候。
    September 26

    delete,truncate,drop 区别

    Windows XP + 9206, google + check


    • delete/truncate 只删除数据不删除表,索引的结构。
      drop 将删除表的结构被依赖的 index/constrain/trigger,依赖于该表的 procedure/function 将保留,但是变为 invalid 状态。

    • delete 是 dml,写 rollback segement,可回滚,速度慢,事务提交之后才生效。在 9i 满足 undo_retention 条件下可使用 flashback。一次性大批量数据的 delete 可能导致回滚段急剧扩展从而影响到数据库,慎用。触发 trigger。
      truncate/drop 是 ddl,隐式提交,不写 rollback segment,不能回滚,速度快。9i 不能使用 flashback。不触发 trigger。

    • delete 不影响表所占用的 extent,HWM 保持原位置不动,即使删除的是最靠近 HWM 的数据。delete 其实也可以释放空间,但是不降低 HWM,delete 后 block 的空闲空间达到 pct_used,就可以重用。
      truncate 缺省情况下将空间(表和索引)释放到 minextents 个 extent,除非使用 reuse storage。truncate 会将高水线复位(回到最开始)。
      drop 将表所占用的空间全部释放,segment 不存在,无所谓 HWM 的概念。

    • truncate/drop 的对象必须是本模式下的,或者被授予 drop any table 的权限,但 drop any table 权限不能 truncate/drop sys 的表。
      delete 的对象必须是本模式下的,或者被授予 delete on SCHEMA.table 或 delete any table 的权限,但 delete any table 权限不能 delete sys 的表。

    • 不能 truncate 一个带有 enable 外键的表,不管表里有没有数据,如果要 truncate,首先要 disable 外键或者删除外键(drop 外键的表肯定是删除了外键)。
      不能 drop 一个带有 enable 外键的表,不管表里有没有数据,如果要 drop,首先要删除外键,或者直接用 drop table TABLE_NAME cascade constraints; 级联删除外键。
      delete 可以。
    September 14

    如此bug

    堕落了好几个月了,终于决定startup 我的数据库看看,结果不妙,回滚段坏了,数据库打不开。
    用了 _corrupted_rollback_segments,_allow_resetlogs_corruption,_offline_rollback_segments,
    加了60个回滚段,试了无数遍,死活打不开,基本上报错都是:
     
    Wed Sep 13 13:02:03 2006
    Errors in file e:\oracle\admin\mydb\udump\mydb_ora_3912.trc:
    ORA-00704: bootstrap process failure
    ORA-00604: error occurred at recursive SQL level 1
    ORA-00376: file 2 cannot be read at this time
    ORA-01110: data file 2: 'E:\ORACLE\ORADATA\MYDB\UNDOTBS01.DBF'

    Wed Sep 13 13:02:03 2006
    Error 704 happened during db open, shutting down database
    USER: terminating instance due to error 704
    Instance terminated by USER, pid = 3912
    ORA-1092 signalled during: alter database open...
     
    最后还出了一个600[25012]的错。。。。。。
     
    大师一边看电视一边说改系统表空间块,这么没有诚心的样子,我还是重建db算了。
     
    然后,
     
    SQL> create table test as select * from dba_tables where 1=0;
    Table created.
    SQL> select segment_name,bytes/1024/1024,blocks,extents from dba_segments where segment_name='TEST';
    SEGMENT_NAME         BYTES/1024/1024     BLOCKS    EXTENTS
    -------------------- --------------- ---------- ----------
    TEST                           .0625          8          1
    SQL> insert into test select * from dba_tables;
    480 rows created.
    SQL> insert into test select * from test;
    480 rows created.
    SQL> /
    ......
    SQL> commit;
    Commit complete.
    SQL> select segment_name,bytes/1024/1024,blocks,extents from dba_segments where segment_name='TEST';
    SEGMENT_NAME         BYTES/1024/1024     BLOCKS    EXTENTS
    -------------------- --------------- ---------- ----------
    TEST                               7        896         22
    SQL> truncate table test;
    Table truncated.
    SQL> select segment_name,bytes/1024/1024,blocks,extents from dba_segments where segment_name='TEST';
    SEGMENT_NAME         BYTES/1024/1024     BLOCKS    EXTENTS
    -------------------- --------------- ---------- ----------
    TEST                               7        896         22
     
    这个结果狠狠地吓了我一跳,差一点让我晕过去。
    还好大师告知这是9206的bug,否则我要洗脑了,不过,我居然从来都不知道,汗。
    August 31

    规范

    有一次跟朋友吃饭的时候,我们谈到了数据库的规范化,如安装,配置,监控等等。
    大师说:“我们的数据库,除了SID其它都一样。”
    而我只能说:“我们的数据库,除了SID其它都不一样。”
     
    One day at dinner with friends, we talked about the standards for databases, such as installation, configuration, monitoring, etc.
    Biti said:" in our databases all the things are the same except SID."
    But I can only say:" in our databases all the things are NOT the same except SID."
    July 31

    (ZT)CLOSE_WAIT状态以及应对策略

     

    摘要:今天发现一台机器上的Web Server工作不正常了,通过netstat一看,这台机器和另一台美国的服务器之间许多连接都处于CLOSE_WAIT状态。本地的到底什么原因导致连接无法关闭一直处于这种状态呢?想起一篇文章。虽然它也没有找到原因,却对这种状态有一个详细的描述。


    本文阐述了为何socket连接锁定在CLOSE_WAIT状态,以及通过什么措施力求避免这种情况。

    不久前,我的Socket Client程序遇到了一个非常尴尬的错误。它本来应该在一个socket长连接上持续不断地向服务器发送数据,如果socket连接断开,那么程序会自动不断地重试建立连接。有一天发现程序在不断尝试建立连接,但是总是失败。用netstat查看,这个程序竟然有上千个socket连接处于CLOSE_WAIT状态,以至于达到了上限,所以无法建立新的socket连接了。为什么会这样呢?它们为什么会都处在CLOSE_WAIT状态呢?

    CLOSE_WAIT
    状态的生成原因首先我们知道,如果我们的Client程序处于CLOSE_WAIT状态的话,说明套接字是被动关闭的!因为如果是Server端主动断掉当前连接的话,那么双方关闭这个TCP连接共需要四个packet

    Server ---> FIN ---> Client

    Server <--- ACK <--- Client
    这时候Server端处于FIN_WAIT_2状态;而我们的程序处于CLOSE_WAIT状态。

    Server <--- FIN <--- Client
    这时Client发送FINServerClient就置为LAST_ACK状态。

    Server ---> ACK ---> Client
    Server
    回应了ACK,那么Client的套接字才会真正置为CLOSED状态。

    我们的程序处于CLOSE_WAIT状态,而不是LAST_ACK状态,说明还没有发FINServer,那么可能是在关闭连接之前还有许多数据要发送或者其他事要做,导致没有发这个FIN packet

    原因知道了,那么为什么不发FIN包呢,难道会在关闭己方连接前有那么多事情要做吗?还有一个问题,为什么有数千个连接都处于这个状态呢?难道那段时间内,服务器端总是主动拆除我们的连接吗?

    不管怎么样,我们必须防止类似情况再度发生!首先,我们要防止不断开辟新的端口,这可以通过设置SO_REUSEADDR套接字选项做到:重用本地地址和端口以前我总是一个端口不行,就换一个新的使用,所以导致让数千个端口进入CLOSE_WAIT状态。如果下次还发生这种尴尬状况,我希望加一个限定,只是当前这个端口处于CLOSE_WAIT状态!在调用

    sockConnected = socket(AF_INET, SOCK_STREAM, 0);
    之后,我们要设置该套接字的选项来重用:

    ///
    允许重用本地地址和端口:
    ///
    这样的好处是,即使socket断了,调用前面的socket函数也不会占用另一个,而是始终就是一个端口
    ///
    这样防止socket始终连接不上,那么按照原来的做法,会不断地换端口。

    int nREUSEADDR = 1;
    setsockopt(sockConnected,
    SOL_SOCKET,
    SO_REUSEADDR,
    (const char*)&nREUSEADDR,
    sizeof(int));

    教科书上是这么说的:这样,假如服务器关闭或者退出,造成本地地址和端口都处于TIME_WAIT状态,那么SO_REUSEADDR就显得非常有用。也许我们无法避免被冻结在CLOSE_WAIT状态永远不出现,但起码可以保证不会占用新的端口。其次,我们要设置SO_LINGER套接字选项:从容关闭还是强行关闭?

    LINGER
    是“拖延”的意思。默认情况下(Win2k)SO_DONTLINGER套接字选项的是1SO_LINGER选项是,linger{l_onoff0l_linger0}如果在发送数据的过程中(send()没有完成,还有数据没发送)而调用了closesocket(),以前我们一般采取的措施是“从容关闭”:因为在退出服务或者每次重新建立socket之前,我都会先调用

    ///
    先将双向的通讯关闭
    shutdown(sockConnected, SD_BOTH);

    ///
    安全起见,每次建立Socket连接前,先把这个旧连接关闭
    closesocket(sockConnected);

    我们这次要这么做:设置SO_LINGER为零(亦即linger结构中的l_onoff域设为非零,但l_linger0),便不用担心closesocket调用进入 “锁定”状态(等待完成),不论是否有排队数据未发送或未被确认。这种关闭方式称为“强行关闭”,因为套接字的虚电路立即被复位,尚未发出的所有数据都会丢失。在远端的recv()调用都会失败,并返回WSAECONNRESET错误。connect成功建立连接之后设置该选项:

    linger m_sLinger;
    m_sLinger.l_onoff = 1; // (
    closesocket()调用,但是还有数据没发送完毕的时候容许逗留)
    m_sLinger.l_linger = 0; // (
    容许逗留的时间为0)
    setsockopt(sockConnected,
    SOL_SOCKET,
    SO_LINGER,
    (const char*)&m_sLinger,
    sizeof(linger));

    总结:也许我们避免不了CLOSE_WAIT状态冻结的再次出现,但我们会使影响降到最小,希望那个重用套接字选项能够使得下一次重新建立连接时可以把CLOSE_WAIT状态踢掉。

    (ZT)NETSTAT命令详解

     
     
    netstat命令是一个监控TCP/IP网络的非常有用的工具,它可以显示路由表、实际的网络连接以及每一个网络接口设备的状态信息,在我的计算机上执行netstat后,其输出结果为:

    Active Internet connections (w/o servers)
    Proto Recv-Q Send-Q Local Address Foreign Address State
    tcp 0 2 210.34.6.89:telnet 210.34.6.96:2873 ESTABLISHED
    tcp 296 0 210.34.6.89:1165 210.34.6.84:netbios-ssn ESTABLISHED
    tcp 0 0 localhost.localdom:9001 localhost.localdom:1162 ESTABLISHED
    tcp 0 0 localhost.localdom:1162 localhost.localdom:9001 ESTABLISHED
    tcp 0 80 210.34.6.89:1161 210.34.6.10:netbios-ssn CLOSE

    Active UNIX domain sockets (w/o servers)
    Proto RefCnt Flags Type State I-Node Path
    unix 1 [ ] STREAM CONNECTED 16178 @000000dd
    unix 1 [ ] STREAM CONNECTED 16176 @000000dc
    unix 9 [ ] DGRAM 5292 /dev/log
    unix 1 [ ] STREAM CONNECTED 16182 @000000df

    从整体上看,netstat的输出结果可以分为两个部分,一个是Active Internet connections,称为有源TCP连接,另一个是Active UNIX domain sockets,称为有源Unix域套接口。在上面的输出结果中,第一部分有5个输出结果,显示有源TCP连接的情况,而第二部分的输出结果显示的是Unix域套接口的连接情况。Proto显示连接使用的协议;RefCnt表示连接到本套接口上的进程号;Types显示套接口的类型;State显示套接口当前的状态;Path表示连接到套接口的其它进程使用的路径名。
    事实上,netstat是若干个工具的汇总。

    ◆ 显示路由表
    在随- r标记一起调用n e t s t a t时,将显示内核路由表,就像我们利用r o u t e命令一样。产生的输出如下:

    [root@machine1 /]$ netstat -nr
    Kernel IP routing table
    Destination Gateway Genmask Flags MSS Window irtt Iface
    210.34.6.0 0.0.0.0 255.255.255.128 U 0 0 0 eth0
    192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
    127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
    0.0.0.0 210.34.6.2 0.0.0.0 UG 0 0 0 eth0

    - n 选项令netstat以点分四段式的形式输出IP地址,而不是象征性的主机名和网络名。如果想避免通过网络查找地址(比如避开DNS或NIS服务器),这一点是特别有用的。
    netstat输出结果中,第二列展示的是路由条目所指的网关,如果没有使用网关,就会出现一个星号(*)或者0.0.0.0;第三列展示路由的概述,在为具体的I P地址找出最恰当的路由时,内核将查看路由表内的所有条目,在对找到的路由与目标路由比较之前,将对I P地址和genmask进行按位“与”计算;第四列显示了不同的标记,这些标记的说明如下:

    ■ G 路由将采用网关。
    ■ U 准备使用的接口处于“活动”状态。
    ■ H 通过该路由,只能抵达一台主机。
    ■ D 如果路由表的条目是由ICMP重定向消息生成的,就会设置这个标记。
    ■ M 如果路由表条目已被ICMP重定向消息修改,就会设置这个标记。

    netstat输出结果的Iface显示该连接所用的物理网卡,如eth0表示用第一张,eth1表示用第二张。

    ◆ 显示接口特性

    在随- i标记一起调用时, netstat将显示网络接口的当前配置特性。除此以外,如果调用时还带上-a选项,它还将输出内核中所有接口,并不只是当前配置的接口。netstat-i的输出结果是这样的:

    [root@machine1 /]$ netstat -i
    Kernel Interface table
    Iface MTU Met RX-OK RX-ERR RX-DRP RX-OVR TX-OK TX-ERR TX-DRP TX-OVR Flg
    eth0 1500 0 787165 0 0 1 51655 0 0 0 BRU
    eth1 1500 0 520811 0 0 0 1986 0 0 0 BRU
    lo 3924 0 1943 0 0 0 43 0 0 0 LRU

    MTU和Met字段表示的是接口的MTU和度量值值;RX和TX这两列表示的是已经准确无误地收发了多少数据包( RX - OK / TX - OK)、产生了多少错误( RX-ERR/TX-ERR)、丢弃了多少包(RX-DRP/TX-DRP),由于误差而遗失了多少包(RX-OVR/TX-OVR);最后一列展示的是为这个接口设置的标记,在利用ifconfig显示接口配置时,这些标记都采用一个字母。它们的说明如下:

    ■ B 已经设置了一个广播地址。
    ■ L 该接口是一个回送设备。
    ■ M 接收所有数据包(混乱模式)。
    ■ N 避免跟踪。
    ■ O 在该接口上,禁用A R P。
    ■ P 这是一个点到点链接。
    ■ R 接口正在运行。
    ■ U 接口处于“活动”状态。

    ◆ 显示链接
    netstat支持用于显示活动或被动套接字的选项集。选项- t、- u、- w和- x分别表示TCP、UDP、RAW和UNIX套接字连接。如果你另外还提供了一个- a标记,还会显示出等待连接(也就是说处于监听模式)的套接字。这样就可以得到一份服务器清单,当前所有运行于系统中的所有服务器都会列入其中。

    调用netstat -ta时,输出结果如下:

    [root@machine1 /]$ netstat -ta
    Active Internet connections (servers and established)
    Proto Recv-Q Send-Q Local Address Foreign Address State
    tcp 0 2 210.34.6.89:telnet 210.34.6.96:2873 ESTABLISHED
    tcp 0 0 210.34.6.89:1165 210.34.6.84:netbios-ssn ESTABLISHED
    tcp 0 0 localhost.localdom:9001 localhost.localdom:1162 ESTABLISHED
    tcp 0 0 localhost.localdom:1162 localhost.localdom:9001 ESTABLISHED
    tcp 0 0 *:9001 *:* LISTEN
    tcp 0 0 *:6000 *:* LISTEN
    tcp 0 0 *:socks *:* LISTEN
    tcp 0 80 210.34.6.89:1161 210.34.6.10:netbios-ssn CLOSE

    上面的输出表明部分服务器处于等待接入连接状态。利用- a选项的话,netstat还会显示出所有的套接字。注意根据端口号,可以判断出一条连接是否是外出连接。对呼叫方主机来说,列出的端口号应该一直是一个整数,而对众所周知服务(well known service)端口正在使用中的被呼叫方来说,netstat采用的则是取自/etc/services文件的象征性服务名。
    May 30

    吸取教训

    1 不要相信别人
    2 不要没事找事做
    May 05

    你这是给biti丢脸

    rac,不会装
    老师说
    你这是给biti丢脸
     
    哎。。。。。。
    生活如此艰辛
    半夜三更的装rac
    早知困到眼皮打架
    何必上课聊天
    小惠惠啊加油
    否则biti要换女朋友了不一定
    April 25

    全局检查点和增量检查点(二)

    我来补充一些

    这里有一个讨论讲得很清楚:heartbeat


    1. oracle 7 中只有全局检查点,因为没有checkpoint queue,dirty buffer是无序的,所以必须一次性写出,写出的过程中要lock dirty buffer不能再被修改。

    oracle 8 中全局检查点变成了增量检查点,它是和checkpoint queue一起出现的。增量检查点发生的时候,ckpt检查点进程将已经完成的最后一个检查点写到数据文件头和控制文件,通知dbwr开始写数据文件写到检查点触发这个时刻(也就是当前时刻)。在checkpoint queue中,dirty buffer按照低重做值(第一次变脏的顺序)排序,所以在写出的时候dirty buffer可以同时被修改。这是增量检查点最重要的作用。

    有一个叫heartbeat的概念,也就是ckpt检查点进程每3秒将当前dbwr写的进度(rba)写到控制文件中。于是这个就缩短了instance recovery和media recovery的过程(当然这个过程也不是越短越好,否则dbwr写太频繁会带来I/O方面的问题)。这是增量检查点的另一个好处。


    2. 这几个参数就是通过oracle的算法,决定了下一次增量检查点发生的时间或者说位置。


    3. 9i开始推荐使用fast_start_mttr_target,另外的参数都置0。

    Whenever you set FAST_START_MTTR_TARGET to a nonzero value, and while MTTR advisory is ON, Oracle Corporation recommends that you disable (set to 0) the following parameters:

    • LOG_CHECKPOINT_TIMEOUT
    • LOG_CHECKPOINT_INTERVAL
    • FAST_START_IO_TARGET

    Because these initialization parameters either override FAST_START_MTTR_TARGET or potentially drive checkpoints more aggressively than FAST_START_MTTR_TARGET does, they can interfere with the simulation.

    这里“MTTR advisory is ON”的条件是,STATISTICS_LEVEL is set to TYPICAL or ALL,以及the initialization parameter FAST_START_MTTR_TARGET is set to a nonzero value。

    全局检查点和增量检查点

    摘自blue_prince的blog,注意拉注意拉,某公司的一面试题。^_^


    由于Oracle中LGWR和DBWR工作的不一致,Oracle引入了检查点的概念,用于同步数据库,保证数据库的一致性。在Oracle里面,检查点分为两种:完全检查点和增量检查点。下面我们分别介绍这两种检查点的作用:


    1、 完全检查点

    在Oracle8i之前,数据库的发生的检查点都是完全检查点,完全检查点会将数据缓冲区里面所有的脏数据块写入相应的数据文件中,并且同步数据文件头和控制文件,保证数据库的一致。完全检查点在8i之后只有在下列两种情况下才会发生:

    (1、)DBA手工执行alter system checkpoint的命令;

    (2、)数据库正常shutdown(immediate,transcational,normal)。

    由于完全检查点会将所有的脏数据库块写入,巨大的IO往往会影响到数据库的性能。因此Oracle从8i开始引入了增量检查点的概念。


    2、 增量检查点

    Oracle从8i开始引入了检查点队列这么一种概念,用于记录数据库里面当前所有的脏数据块的信息,DBWR根据这个队列而将脏数据块写入到数据文件中。检查点队列按时间先后记录着数据库里面脏数据块的信息,里面的条目包含RBA(Redo Block Address,重做日志里面用于标识检查点期间数据块在重做日志里面第一次发生更改的编号)和数据块的数据文件号和块号。在检查点期间不论数据块更改几次,它在检查点队列里面的位置始终保持不变,检查点队列也只会记录它最早的RBA,从而保证最早更改的数据块能够尽快写入。当DBWR将检查点队列里面的脏数据块写入到数据文件后,检查点的位置也要相应地往后移,CKPT每三秒会在控制文件中记录检查点的位置,以表示Instance Recovery时开始恢复的日志条目,这个概念称为检查点的“心跳”(heartbeat)。检查点位置发生变更后,Oracle里面通过4个参数用于控制检查点位置和最后的重做日志条目之间的距离。在这里面需要指出的是,多数人会将这4个参数看作控制增量检查点发生的时间。事实上这是错误的,这4个参数是用于控制检查点队列里面的条目数量,而不是控制检查点的发生。

    (1、)fast_start_io_target

    该参数用于表示数据库发生Instance Recovery的时候需要产生的IO总数,它通过v$filestat的AVGIOTIM来估算的。比如我们一个数据库在发生Instance Crash后需要在10分钟内恢复完毕,假定OS的IO每秒为500个,那么这个数据库发生Instance Recovery的时候大概将产生500*10*60=30,000次IO,也就是我们将可以把fast_start_io_target设置为30000。

    (2、)fast_start_mttr_target

    我们从上面可以看到fast_start_io_target来估算检查点位置比较麻烦。Oracle为了简化这个概念,从9i开始引入了fast_start_mttr_target这么一个参数,用于表示数据库发生Instance Recovery的时间,以秒为单位。这个参数我们从字面上也比较好理解,其中的mttr是mean time to recovery的简写,如上例中的情况我们可以将fast_start_mttr_target设置为600。当设置了fast_start_mttr_target后,fast_start_io_target这个参数将不再生效,从9i后fast_start_io_target这个参数被Oracle废除了。

    (3、)log_checkpoint_timeout

    该参数用于表示检查点位置和重做日志文件末尾之间的时间间隔,以秒为单位,默认情况下是1800秒。

    (4、)log_checkpoint_interval

    该参数是表示检查点位置和重做日志末尾的重做日志块的数量,以OS块表示。

    (5、)90% OF SMALLEST REDO LOG

    除了以上4个初始化参数外,Oracle内部事实上还将重做日志文件末尾前面90%的位置设为检查点位置。在每个重做日志中,这么几个参数指定的位置可能不尽相同,Oracle将离日志文件末尾最近的那个位置确认为检查点位置。

    oracle 9i instance recovery

    我摘了以下几个人写过的话,基本上可以搞清楚instance crash之后instance recovery的过程,这个比看英文文档要简单多多了。^_^


    wanghai---

    1. 增量检查点
    在checkpoint queue的基础上实现了增量检查点,每3秒发生一次checkpoint heartbeat,记录dbwr上次写成功的最大RBA(redo block address)。这样的话做instance recovery的时候就从这个rba开始,而不是从上次checkpoint scn开始,大大节省了恢复时间。
     
    2. twice scan of redo log
    在应用redo之前,redo将会被操作两次,第一次去扫描哪些redo record需要被应用,因为9i在redo里添加了dbwr写数据块的信息,所以dbwr发生前的日志将不会被应用。第二步就是选出需要被应用的日志然后开始rollforward。
     
    3. rollforward
    在做instance recovery时必须先定位到redo log 然后应用所有日志到datafile,这时候包括了committed和uncommitted的数据。当做完rollward,数据库就可以open了。
     
    4. rollback
    因为rollforward产生了uncommitted数据,所以必须回滚这些数据。这将由smon和on-demand rollback来实现。smon将会扫描undo segment header去标志所有活动事务为dead,然后会逐渐去回滚这些事务。另外on-demand rollback提供了前台进程进行rollback,当前台进程企图获得被dead事务占用row lock,这时候前台进程将会去undo segment取得before image去回滚这个块,至于其他被这个dead事务lock的块就等待smon去回滚。
     
    另外,如果在数据库打开的过程中process crash导致transaction dead,resource不能被释放的情况,这时候如果另一个进程需要这些resource,那么这个进程将会等待直到pmon清理dead process释放出resource。


    eygle---

    如果数据库Crash,重新启动,很久远以前的未提交事务并不在Redo的恢复序列中。
    但是未提交事务一定在回滚段事务表上存在,并且State=10,为活动事务。这就够了。

    数据库启动之后,这些事务会被SMON逐个标记为Dead(不可能再活过来了),然后由SMON慢慢去回滚这些事务;也存在另外一种情况,后来的进程会去读这些未提交数据,发现Dead事务未提交,则主动进行回滚。


    kamus---

    1. 一个数据块发生更新,必然写回滚
    2. 回滚段的block变化也记录在redo中

    一份未提交的数据必定在回滚中有相应的前镜像,任何正常的恢复都一定会把这些变化重新构建出来。


    想像一下

    1. update事务1更新了block 1
    2. 回滚段1记录了block1的前镜像
    3. checkpoint
    4. update事务2更新了block2
    5. 回滚段2记录了block2的前镜像
    6. instance crash

    现在重启数据库

    1. 根据redo重新构建block2
    2. 根据redo重新构建回滚段2
    3. database open
    4. SMON用回滚段2的数据回滚block2,SMON用回滚段1的数据回滚block1

    最后一步也可能是
    在另外一个select检索到block1或者block2的时候,发现这两个block的数据都是未提交的,此时再回滚block1和block2。

    所以,只要有相应的回滚数据存在,无论什么时候oracle都可以找到一致的数据,oracle只需要知道这个事务是提交了的还是没提交了的,而这点在block header ITL中有记录。