<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet href='http://feed.feedsky.com/styles/feedsky6.xsl' type='text/xsl' ?><!--这是一个由Feedsy提供技术支持的Feed，为了提高读者阅读的体验，以及满足用户美化自己Feed的需要，我们设计了多种精美的Feed模板，提供给大家选择，所有最终呈现出来的样式，皆由用户自愿选择使用，未经许可，任何团体和个人，请不要擅自修改样式或者盗用，这是对于用户选择权的尊重。--><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:fs="http://www.feedsky.com/namespace/feed" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><atom:link href="http://feed.feedsky.com/hellodba" type="application/rss+xml" rel="self"></atom:link><fs:self_link href="http://feed.feedsky.com/hellodba" type="application/rss+xml"></fs:self_link><lastBuildDate>Wed, 10 Feb 2010 08:33:21 GMT</lastBuildDate><title>Hello DBA</title><description>他强任他强 清风拂山岗 他横任他横 明月照大江</description><image><url>http://www.feedsky.com/images/feedsky_logologo.gif</url><title>Hello DBA</title><link>http://www.hellodba.net</link></image><link>http://www.hellodba.net</link><language>en</language><pubDate>Wed, 10 Feb 2010 11:15:48 GMT</pubDate><item><title>Cassandra数据模型</title><link>http://www.hellodba.net/2010/02/cassandra.html</link><content:encoded>&lt;p&gt;提起NoSQL这个话题，仿佛不应该是DBA要关注的事，而是架构师应该关心的。但是作为一名DBA，在使用传统的关系型思想建模时，应该有必要了解NoSQL的建模方法。&lt;/p&gt;
&lt;p&gt;各种NoSQL数据库有很多，我最关注的还是&lt;strong&gt;BigTable&lt;/strong&gt;类型，因为它是一个高可用可扩展的分布式计算平台，用来处理海量的结构化数据，而数据库同样也是处理结构化数据，所以除了没有SQL，在数据模型方面有相似之处。&lt;strong&gt;Cassandra&lt;/strong&gt;是facebook开源出来的一个版本，可以认为是BigTable的一个开源版本，目前twitter和digg.com在使用。我们尝试从DBA的角度出发去理解Cassandra的数据模型。&lt;/p&gt;
&lt;p&gt;NoSQL并不能简单的理解为&lt;strong&gt;No SQL&lt;/strong&gt;，其本质应该是&lt;strong&gt;No Relational&lt;/strong&gt;，也就是说它不是基于关系型的理论基础，而我们所有传统的数据库都是基于这套理论而发展起来的，所以SQL并不是问题的关键所在，比如有些NoSQL数据库可以提供SQL类型的接口，允许你通过类SQL的语法去访问数据。而Friendfeed则是反其道而行之，利用关系型数据库MySQL，采用了去关系化的设计方法，去实现自己的KeyValue存储。所以NoSQL的本质是No Relational.&lt;/p&gt;
&lt;p&gt;Cassandra特点：&lt;/p&gt;
&lt;p&gt;1.灵活的schema，不需要象数据库一样预先设计schema，增加或者删除字段非常方便（on the fly）。&lt;/p&gt;
&lt;p&gt;2.支持range查询：可以对Key进行范围查询。&lt;/p&gt;
&lt;p&gt;3.高可用，可扩展：单点故障不影响集群服务，可线性扩展。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Keyspace&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cassandra中的最大组织单元，里面包含了一系列Column family，Keyspace一般是应用程序的名称。你可以把它理解为Oracle里面的一个schema，包含了一系列的对象。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Column family（CF）&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;CF是某个特定Key的数据集合，每个CF物理上被存放在单独的文件中。从概念上看，CF有点象数据库中的Table.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Key&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;数据必须通过Key来访问，Cassandra允许范围查询，例如：&lt;code&gt;start =&amp;gt; '10050', :finish =&amp;gt; '10070'&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Column&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;在Cassandra中字段是最小的数据单元，column和value构成一个对，比如：name:“jacky”，column是name，value是jacky，每个column:value后都有一个时间戳：timestamp。&lt;/p&gt;
&lt;p&gt;和数据库不同的是，Cassandra的一行中可以有任意多个column，而且每行的column可以是不同的。从数据库设计的角度，你可以理解为表上有两个字段，第一个是Key，第二个是长文本类型，用来存放很多的column。这也是为什么说Cassandra具备非常灵活schema的原因。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Super column&lt;br /&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Super column是一种特殊的column，里面可以存放任意多个普通的column。而且一个CF中同样可以有任意多个Super column，一个CF只能定义使用Column或者Super column，不能混用。下面是Super column的一个例子，homeAddress这个Super column有三个字段：分别是street，city和zip：&lt;/p&gt;
&lt;pre&gt;homeAddress: {street: &quot;binjiang road&quot;,city: &quot;hangzhou&quot;,zip: &quot;310052&quot;,}&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Sorting&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;不同于数据库可以通过Order by定义排序规则，Cassandra取出的数据顺序是总是一定的，数据保存时已经按照定义的规则存放，所以取出来的顺序已经确定了，这是一个巨大的性能优势。有意思的是，&lt;strong&gt;Cassandra按照column name而不是column value来进行排序，&lt;/strong&gt;它定义了以下几种选项：BytesType, UTF8Type, LexicalUUIDType, TimeUUIDType, AsciiType,  和LongType，用来定义如何按照column name来排序。实际上，就是把column name识别成为不同的类型，以此来达到灵活排序的目的。UTF8Type是把column name转换为UTF8编码来进行排序，LongType转换成为64位long型，TimeUUIDType是按照基于时间的UUID来排序。例如：&lt;/p&gt;
&lt;p&gt;Column name按照LongType排序：&lt;/p&gt;
&lt;pre&gt;{name: 3, value: &quot;jacky&quot;},
{name: 123, value: &quot;hellodba&quot;},
{name: 976, value: &quot;Cassandra&quot;},
{name: 832416, value: &quot;bigtable&quot;}&lt;/pre&gt;
&lt;p&gt;Column name按照UTF8Type排序：&lt;/p&gt;
&lt;pre&gt;{name: 123, value: &quot;hellodba&quot;},
{name: 3, value: &quot;jacky&quot;},
{name: 832416, value: &quot;bigtable&quot;}
{name: 976, value: &quot;Cassandra&quot;}&lt;/pre&gt;
&lt;p&gt;下面我们看twitter的Schema：&lt;/p&gt;
&lt;pre&gt;&amp;lt;Keyspace Name=&quot;Twitter&quot;&amp;gt;
  &amp;lt;ColumnFamily CompareWith=&quot;UTF8Type&quot; Name=&quot;Statuses&quot; /&amp;gt;
  &amp;lt;ColumnFamily CompareWith=&quot;UTF8Type&quot; Name=&quot;StatusAudits&quot; /&amp;gt;
  &amp;lt;ColumnFamily CompareWith=&quot;UTF8Type&quot; Name=&quot;StatusRelationships&quot;
    CompareSubcolumnsWith=&quot;TimeUUIDType&quot; ColumnType=&quot;Super&quot; /&amp;gt;
  &amp;lt;ColumnFamily CompareWith=&quot;UTF8Type&quot; Name=&quot;Users&quot; /&amp;gt;
  &amp;lt;ColumnFamily CompareWith=&quot;UTF8Type&quot; Name=&quot;UserRelationships&quot;
    CompareSubcolumnsWith=&quot;TimeUUIDType&quot; ColumnType=&quot;Super&quot; /&amp;gt;
&amp;lt;/Keyspace&amp;gt;&lt;/pre&gt;
&lt;p&gt;我们看到一个叫Twitter的keyspace，包含若干个CF，其中StatusRelationships和UserRelationships被定义为包含Super column的CF，CompareWith定义了column的排序规则，CompareSubcolumnsWith定义了subcolumn的排序规则，这里使用了两种：TimeUUIDType和UTF8Type。我们没有看到任何有关column的定义，这意味着column是可以灵活变更的。&lt;/p&gt;
&lt;p&gt;为了方便大家理解，我会尝试着用关系型数据库的建模方法去描述Twitter的Schema，但&lt;strong&gt;千万不要误解为这就是Cassandra的数据模型&lt;/strong&gt;，对于Cassandra来说，每一行的colunn都可以是任意的，而不是象数据库一样需要在建表时就创建好。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/twitter.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1376&quot; title=&quot;twitter&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/twitter.png&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;242&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Users CF记录用户的信息，Statuses CF记录tweets的内容，StatusRelationships CF记录用户看到的tweets，UserRelationships CF记录用户看到的followers。我们注意到排序方式是TimeUUIDType，这个类型是按照时间进行排序的UUID字段，column name是用UUID函数产生（这个函数返回了一个UUID，这个UUID反映了当前的时间，可以根据这个UUID来排序，有点类似于timestamp一样），所以得到结果是按照时间来排序的。使用过twitter的人都知道，你总是可以看到自己最新的tweets或者最新的friends.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;存储&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Cassandra是基于列存储的(Bigtable也是一样)，这个和基于列的数据库是一个道理。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/cassandra_data_model.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1382&quot; title=&quot;cassandra_data_model&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/cassandra_data_model.png&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;155&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;API&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;下面是数据库，Bigtable和Cassandra API的对比：&lt;/p&gt;
&lt;pre&gt;Relational			SELECT `column` FROM `database`.`table` WHERE `id` = key;
BigTable			table.get(key, &quot;column_family:column&quot;)
Cassandra: standard model	keyspace.get(&quot;column_family&quot;, key, &quot;column&quot;)
Cassandra: super column model	keyspace.get(&quot;column_family&quot;, key, &quot;super_column&quot;, &quot;column&quot;)&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;我对Cassandra数据模型的理解：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;1.column name存放真正的值，而value是空。因为Cassandra是按照column name排序，而且是按列存储的，所以往往利用column name存放真正的值，而value部分则是空。例如：“jacky”:“null”，“fenng”:&amp;#8221;null&amp;#8221;&lt;/p&gt;
&lt;p&gt;2.Super column可以看作是一个索引，有点象关系型数据库中的外键，利用super column可以实现快速定位，因为它可以返回一堆column，而且是排好序的。&lt;/p&gt;
&lt;p&gt;3.排序在定义时就确定了，取出的数据肯定是按照确定的顺序排列的，这是一个巨大的性能优势。&lt;/p&gt;
&lt;p&gt;4. 非常灵活的schema，column可以灵活定义。实际上，colume name在很多情况下，就是value（是不是有点绕）。&lt;/p&gt;
&lt;p&gt;5.每个column后面的timestamp，我并没有找到明确的说明，我猜测可能是数据多版本，或者是底层清理数据时需要的信息。&lt;/p&gt;
&lt;p&gt;最后说说架构，我认为架构的核心就是&lt;strong&gt;有所取舍&lt;/strong&gt;，不管是&lt;strong&gt;CAP&lt;/strong&gt;还是&lt;strong&gt;BASE&lt;/strong&gt;，讲的都是这个原则。架构之美在于没有任何一种架构可以完美的解决各种问题，数据库和NoSQL都有其应用场景，我们要做的就是为自己找到合适的架构。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;
&lt;p&gt;这篇文章，我参考了&lt;a href=&quot;http://blog.evanweaver.com/articles/2009/07/06/up-and-running-with-cassandra/&quot;&gt;up and running with cassandra&lt;/a&gt;，除此以外，我还参考了twitter提供的API，它帮助我理解twitter的schema设计。这篇文章，肯定有很多理解不正确的地方，希望朋友们指正。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617845/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/02/cassandra.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617845/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617845/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2010/02/cassandra.html/feed</wfw:commentRss><description>提起NoSQL这个话题，仿佛不应该是DBA要关注的事，而是架构师应该关心的。但是作为一名DBA，在使用传统的关系型思想建模时，应该有必要了解NoSQL的建模方法。
各种NoSQL数据库有很多，我最关注的还是BigTable类型，因为它是一个高可用可扩展的分布式计算平台，用来处理海量的结构化数据，而数据库同样也是处理结构化数据，所以除了没有SQL，在数据模型方面有相似之处。Cassandra是facebook开源出来的一个版本，可以认为是BigTable的一个开源版本，目前twitter和digg.com在使用。我们尝试从DBA的角度出发去理解Cassandra的数据模型。
NoSQL并不能简单的理解为No SQL，其本质应该是No Relational，也就是说它不是基于关系型的理论基础，而我们所有传统的数据库都是基于这套理论而发展起来的，所以SQL并不是问题的关键所在，比如有些NoSQL数据库可以提供SQL类型的接口，允许你通过类SQL的语法去访问数据。而Friendfeed则是反其道而行之，利用关系型数据库MySQL，采用了去关系化的设计方法，去实现自己的KeyValue存储。所以NoSQL的本质是No Relational.
Cassandra特点：
1.灵活的schema，不需要象数据库一样预先设计schema，增加或者删除字段非常方便（on the fly）。
2.支持range查询：可以对Key进行范围查询。
3.高可用，可扩展：单点故障不影响集群服务，可线性扩展。
Keyspace
Cassandra中的最大组织单元，里面包含了一系列Column family，Keyspace一般是应用程序的名称。你可以把它理解为Oracle里面的一个schema，包含了一系列的对象。
Column family（CF）
CF是某个特定Key的数据集合，每个CF物理上被存放在单独的文件中。从概念上看，CF有点象数据库中的Table.
Key
数据必须通过Key来访问，Cassandra允许范围查询，例如：start =&amp;#62; '10050', :finish =&amp;#62; '10070'

Column
在Cassandra中字段是最小的数据单元，column和value构成一个对，比如：name:“jacky”，column是name，value是jacky，每个column:value后都有一个时间戳：timestamp。
和数据库不同的是，Cassandra的一行中可以有任意多个column，而且每行的column可以是不同的。从数据库设计的角度，你可以理解为表上有两个字段，第一个是Key，第二个是长文本类型，用来存放很多的column。这也是为什么说Cassandra具备非常灵活schema的原因。
Super column

Super column是一种特殊的column，里面可以存放任意多个普通的column。而且一个CF中同样可以有任意多个Super column，一个CF只能定义使用Column或者Super column，不能混用。下面是Super column的一个例子，homeAddress这个Super column有三个字段：分别是street，city和zip：
homeAddress: {street: &quot;binjiang road&quot;,city: &quot;hangzhou&quot;,zip: &quot;310052&quot;,}
Sorting
不同于数据库可以通过Order by定义排序规则，Cassandra取出的数据顺序是总是一定的，数据保存时已经按照定义的规则存放，所以取出来的顺序已经确定了，这是一个巨大的性能优势。有意思的是，Cassandra按照column name而不是column value来进行排序，它定义了以下几种选项：BytesType, UTF8Type, LexicalUUIDType, TimeUUIDType, AsciiType,  和LongType，用来定义如何按照column name来排序。实际上，就是把column name识别成为不同的类型，以此来达到灵活排序的目的。UTF8Type是把column name转换为UTF8编码来进行排序，LongType转换成为64位long型，TimeUUIDType是按照基于时间的UUID来排序。例如：
Column name按照LongType排序：
{name: 3, value: &quot;jacky&quot;},
{name: 123, value: &quot;hellodba&quot;},
{name: 976, value: &quot;Cassandra&quot;},
{name: 832416, value: &quot;bigtable&quot;}
Column name按照UTF8Type排序：
{name: 123, value: &quot;hellodba&quot;},
{name: 3, value: &quot;jacky&quot;},
{name: [...]&lt;img src=&quot;http://www1.feedsky.com/t1/331617845/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/02/cassandra.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617845/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617845/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>NoSQL</category><category>Cassandra</category><category>大话技术</category><pubDate>Wed, 10 Feb 2010 16:33:21 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/02/cassandra.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1362</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/02/cassandra.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617845/5126880</fs:itemid></item><item><title>Oracle Exadata技术浅析</title><link>http://www.hellodba.net/2010/02/oracle_exadata.html</link><content:encoded>&lt;p&gt;自从Oracle和HP推出Exadata之后，我就很关注这个产品，之前也写了一篇&lt;a href=&quot;http://www.hellodba.net/2008/10/oracle-database-machine.html&quot;&gt;Oracle database machine&lt;/a&gt;介绍它。去年，Oracle和SUN合并后，推出了Oracle Exadata V2，相比较上一代产品有几个变化：第一，使用SUN的硬件；第二，宣称支持OLTP应用；第三，Oracle 11g R2提供了更多的新特性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Exadata Smart Flash Cache&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Exadata V2整体架构并没有太多改变，换用了SUN的硬件，除了采用intel最新的nehalem CPU以外，每台storage cell更是配置了384GB的flash，这也是为什么V2可以支持OLTP应用的关键。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/exadata.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1348&quot; title=&quot;exadata&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/exadata.jpg&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;293&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Flash cache完全是自动管理，Oracle会根据数据的访问情况，决定哪些数据放在flash cache中。所有的数据都是先被写到普通磁盘上，再根据访问情况读入flash cache的，所以如果flash card发生故障，数据不会丢失。当然，Oracle提供了方式，可以让用户手动将表或者索引pin在flash cache中。&lt;/p&gt;
&lt;p&gt;在自动管理的方式之外，Oracle还允许用户人工创建flash disks，和普通磁盘一样，这些flash disks通过ASM输出给数据库使用，用户可以把一些访问非常频繁的数据文件放在上面。这些flash disks不仅仅是cache了，所以ASM会在cell和cell之间做镜像。如果某块卡发生故障，那么整个storage cell上的flash disks会offline，保证数据不会丢失。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Smart scan&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Smart scan是Exadata最重要的一个功能，它的作用就是把SQL放在每个cell上去运行，然后每个cell只返回符合条件的数据给数据库，这样就极大的降低了数据库服务器的负载和网络流量，并充分利用了cell的计算资源和IO资源。&lt;/p&gt;
&lt;p&gt;传统方式：所有的数据都需要返回给数据库服务器，网络带宽要求高，所有的计算在数据库服务器上完成。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/smart_scan1.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1350&quot; title=&quot;smart_scan1&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/smart_scan1.jpg&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;241&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Smart scan：只返回符合条件的数据，减少网络带宽，并充分利用了cell上的计算和IO资源。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/smart_scan2.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1351&quot; title=&quot;smart_scan2&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/smart_scan2.jpg&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;196&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;这里有一点要注意，在使用smart scan时，每个cell返回给DB server的是结果集，而不再是传统的block，DB server完成结果集的处理，并返回给客户端。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Smart scan如何处理join？&lt;/strong&gt;是我一直想要搞清楚的问题。事实上，smart scan只能处理join filtering，而真正join的工作必须在DB Server上完成，而且smart scan仅适合于处理DSS环境的复杂join，对于OLTP类型的简单join，smart scan并不能发挥其优势。设想下面的查询：&lt;/p&gt;
&lt;p&gt;select e.ename,d.dname from emp e, dept d where and e.ename=&amp;#8217;Jacky&amp;#8217; and e.deptno=d.deptno;&lt;/p&gt;
&lt;p&gt;假设采用nested loops join，smart scan只能完成e.ename=&amp;#8217;Jacky&amp;#8217;这个条件的过滤，然后将符合条件的emp表的数据返回到DB server，然后由DB Server完成join的工作，逐条查询dept表(e.deptno=d.deptno)的数据。&lt;strong&gt;所以smart scan并不适合nested loop join（我认为smart scan只有在适合的条件下才会启用）&lt;/strong&gt;，只有DSS环境的大数据量复杂join才会发挥出优势。而且smart scan只能完成filtering的工作，而不能真正完成join的工作，这个与Greenplum数据库是不同的（有兴趣可以看我的文章，&lt;a href=&quot;http://www.hellodba.net/2009/07/greenplum.html&quot;&gt;Greenplum技术浅析&lt;/a&gt;）。设想下面的查询（emp和dept都是大表）：&lt;/p&gt;
&lt;p&gt;select e.ename,d.dname from emp e, dept d where e.deptno=d.deptno;&lt;/p&gt;
&lt;p&gt;假设采用hash join，由于没有任何过滤条件，smart scan只能把两个表的数据全部返回到DB Server上进行join操作，不过smart scan也不是一点用都没有，至少还可以进行column的过滤，只返回需要的字段就可以了。&lt;/p&gt;
&lt;p&gt;Oracle的文档中，曾经提到对于一个大表和小表join时，smart scan会采用&lt;strong&gt;bloom filter&lt;/strong&gt;来快速定位（可以看我以前的文章，&lt;a href=&quot;http://www.hellodba.net/2009/04/bloom_filter.html&quot;&gt;有趣的bloom filter&lt;/a&gt;）。方法是把小表build成为bloom filter，然后在每个storage cell上对大表做scan，利用bloom filter快速定位符合条件的结果，并返回给DB Server作join。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Storage index&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;存储索引，顾名思义是在存储级别建立的索引，简单的说就是为表中的每一列数据建立一个索引，每个index entry记录一段数据区间的最大值，最小值以及它们的物理位置，文档上说1MB数据对应一条index entry，见下图：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/storage_index.jpg&quot;&gt;&lt;img class=&quot;alignnone size-medium wp-image-1354&quot; title=&quot;storage_index&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/storage_index-234x300.jpg&quot; alt=&quot;&quot; width=&quot;234&quot; height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;如果我们查询B&amp;lt;2，或者B&amp;gt;8的数据，根据存储索引，我们就可以跳过这些不在min和max之间的数据块，极大的提高了扫描的速度，这就是存储索引的意义。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hybrid Columnar Compressed&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;首先我们要搞清楚，什么是行压缩，什么叫列压缩。我们熟悉的数据库，如Oracle，MySQL等都是基于行的数据库，就是行的不同字段物理上存放在一起，还有一种是基于列的数据库，就是每个字段的不同行物理上存放在一起。他们的优缺点同样突出：&lt;/p&gt;
&lt;p&gt;基于行的数据库，访问一行非常方便，但是由于同一列的数据是分开存放的，如果要针对某一列进行查询时，几乎要扫描整个表才能得到结果。基于行数据库的压缩，称为行压缩。&lt;/p&gt;
&lt;p&gt;基于列的数据库，因为同一列的数据物理上放在一起，所以访问一列非常方便，也就是说如果针对某一列进行查询时，不需要扫描整个表，只需要扫描这一列的数据就可以了，但是访问一行的全部字段非常不方便（又是废话）。基于列数据库的压缩，称为列压缩。&lt;/p&gt;
&lt;p&gt;Oracle通常说的compress功能（包括11g R2的Advanced compress），都是行压缩，因为Oracle是个基于行的数据库。大概的方法就是在block头部存放一个symbol table，然后将相同的值放在那里，每行上相同的数据指向symbol table，以此来达到压缩的目的。行压缩的效果通常不好，因为我们知道行与行之间，其实相同的数据并不多。但是列压缩则不同，因为相同列的数据类型相同，很容易达到很好的压缩效果。&lt;/p&gt;
&lt;p&gt;行压缩和列压缩都有其优缺点，而Oracle的混合列压缩技术，实际上是融合了列压缩的高压缩比和行数据库的访问特性，将两者的优点结合起来。Oracle提出了CU的概念（compress unit），在一个CU内，是一个基于列的存储方式，采用列压缩，但是一个CU内保存了行的所有字段信息，所以在CU与CU之间，Oracle还是一个基于行的数据库，访问某一行，总是只在一个CU内。每个CU由一些连续的block组成，CU header中记录了每一行的各个列在CU中的分布情况，在混合列压缩模式下，一行通常是跨多个block的。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/compress.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1356&quot; title=&quot;compress&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/02/compress.jpg&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;142&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;所以说混合列压缩，结合了列压缩和行访问的特点，即可以提供非常高的压缩率，又很好的保证了基于行类型的访问。&lt;/p&gt;
&lt;p&gt;Exadata的另一个重要功能是IO resource management，如果我们在一个Exadata上部署了很多个数据库，可以用它来管理IO资源，这里就不作阐述了。&lt;/p&gt;
&lt;p&gt;目前，我还没有了解到在国内有Exadata的应用，而且资料也是比较少的。希望有机会可以真实的测试一下它的性能，我不怀疑他在DSS环境下的表现，但是对于OLTP类型的应用，是否真的象Oracle说的那么强劲，还有待于验证。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617855/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/02/oracle_exadata.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617855/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617855/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2010/02/oracle_exadata.html/feed</wfw:commentRss><description>自从Oracle和HP推出Exadata之后，我就很关注这个产品，之前也写了一篇Oracle database machine介绍它。去年，Oracle和SUN合并后，推出了Oracle Exadata V2，相比较上一代产品有几个变化：第一，使用SUN的硬件；第二，宣称支持OLTP应用；第三，Oracle 11g R2提供了更多的新特性。
Exadata Smart Flash Cache
Exadata V2整体架构并没有太多改变，换用了SUN的硬件，除了采用intel最新的nehalem CPU以外，每台storage cell更是配置了384GB的flash，这也是为什么V2可以支持OLTP应用的关键。

Flash cache完全是自动管理，Oracle会根据数据的访问情况，决定哪些数据放在flash cache中。所有的数据都是先被写到普通磁盘上，再根据访问情况读入flash cache的，所以如果flash card发生故障，数据不会丢失。当然，Oracle提供了方式，可以让用户手动将表或者索引pin在flash cache中。
在自动管理的方式之外，Oracle还允许用户人工创建flash disks，和普通磁盘一样，这些flash disks通过ASM输出给数据库使用，用户可以把一些访问非常频繁的数据文件放在上面。这些flash disks不仅仅是cache了，所以ASM会在cell和cell之间做镜像。如果某块卡发生故障，那么整个storage cell上的flash disks会offline，保证数据不会丢失。
Smart scan
Smart scan是Exadata最重要的一个功能，它的作用就是把SQL放在每个cell上去运行，然后每个cell只返回符合条件的数据给数据库，这样就极大的降低了数据库服务器的负载和网络流量，并充分利用了cell的计算资源和IO资源。
传统方式：所有的数据都需要返回给数据库服务器，网络带宽要求高，所有的计算在数据库服务器上完成。

Smart scan：只返回符合条件的数据，减少网络带宽，并充分利用了cell上的计算和IO资源。

这里有一点要注意，在使用smart scan时，每个cell返回给DB server的是结果集，而不再是传统的block，DB server完成结果集的处理，并返回给客户端。
Smart scan如何处理join？是我一直想要搞清楚的问题。事实上，smart scan只能处理join filtering，而真正join的工作必须在DB Server上完成，而且smart scan仅适合于处理DSS环境的复杂join，对于OLTP类型的简单join，smart scan并不能发挥其优势。设想下面的查询：
select e.ename,d.dname from emp e, dept d where and e.ename=&amp;#8217;Jacky&amp;#8217; and e.deptno=d.deptno;
假设采用nested loops join，smart scan只能完成e.ename=&amp;#8217;Jacky&amp;#8217;这个条件的过滤，然后将符合条件的emp表的数据返回到DB server，然后由DB Server完成join的工作，逐条查询dept表(e.deptno=d.deptno)的数据。所以smart scan并不适合nested loop join（我认为smart scan只有在适合的条件下才会启用），只有DSS环境的大数据量复杂join才会发挥出优势。而且smart [...]&lt;img src=&quot;http://www1.feedsky.com/t1/331617855/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/02/oracle_exadata.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617855/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617855/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>ORACLE</category><category>Exadata</category><category>大话技术</category><pubDate>Mon, 01 Feb 2010 21:37:53 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/02/oracle_exadata.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1089</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/02/oracle_exadata.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617855/5126880</fs:itemid></item><item><title>如何控制SQL执行计划之9i篇</title><link>http://www.hellodba.net/2010/01/tuning_sql_execution_plan.html</link><content:encoded>&lt;p&gt;对于一个高并发的OLTP系统，SQL执行计划的改变往往意味着灾难。很多因素都可能导致执行计划发生不可预期的改变，比如表结构，索引，统计信息等变化，甚至我们发生过一个小小的grant操作，导致执行计划失效，重新解析后生成了一个不正确的执行计，让整个系统Crash的案例。最近，我们对一个分区表增加分区后，导致了执行计划发生改变，故障再次重演。&lt;/p&gt;
&lt;p&gt;如何控制SQL的执行计划就成为了一个课题，之前我曾经写过一篇关于&lt;a href=&quot;http://www.hellodba.net/2009/05/tuning_sql.html&quot;&gt;调整SQL执行计划&lt;/a&gt;的文章，但是内容比较粗略。因为Oracle提供了很多手段去控制执行计划，所以我打算为每个版本都整理一个最佳实践。&lt;/p&gt;
&lt;p&gt;我们设想一个场景，一个SQL本来应该走nested loop join，但是由于某种原因，突然变成了hash join，调整统计信息无效，数据库load不断升高，只留给你很少的时间，怎么办？最直接有效的方法是在SQL上加hints，但是需要程序发布，或者程序根本无法修改。&lt;/p&gt;
&lt;p&gt;9i为我们提供了Stored outline，大家都非常熟悉，但是对于上面的场景，还是需要点技巧。方法是：生成两个stored outline，一条是错误的，一条是正确的（加hints），两个然后将其执行计划交换。看下面的步骤：&lt;/p&gt;
&lt;p&gt;1.创建两个public stroed outline，第一个是目前运行的，第二个是加了hints.&lt;/p&gt;
&lt;pre&gt;create or replace outline OUTLN1 on select e.ename from emp e, dept d where e.deptno=d.deptno;
create or replace outline OUTLN2 on select /*+ use_nl(e d)*/ e.ename from emp e, dept d
where e.deptno=d.deptno;&lt;/pre&gt;
&lt;p&gt;拷贝成为private outline&lt;/p&gt;
&lt;pre&gt;create or replace private outline PRIV_OUTLN1 from OUTLN1;
create or replace private outline PRIV_OUTLN2 from OUTLN2;&lt;/pre&gt;
&lt;p&gt;交换两个stored outline的执行计划&lt;/p&gt;
&lt;pre&gt;update ol$ set ol_name=decode(ol_name,'PRIV_OUTLN1','PRIV_OUTLN2','PRIV_OUTLN2','PRIV_OUTLN1')
where ol_name in ('PRIV_OUTLN1','PRIV_OUTLN2');&lt;/pre&gt;
&lt;p&gt;设置本session生效，并测试结果&lt;/p&gt;
&lt;pre&gt;alter session set use_private_outlines=true;&lt;/pre&gt;
&lt;p&gt;刷新&lt;/p&gt;
&lt;pre&gt;execute dbms_outln_edit.refresh_private_outline('PRIV_OUTLN1');
execute dbms_outln_edit.refresh_private_outline('PRIV_OUTLN2');&lt;/pre&gt;
&lt;p&gt;发布到public outline&lt;/p&gt;
&lt;pre&gt;create or replace outline OUTLN1 from private PRIV_OUTLN1;
create or replace outline OUTLN2 from private PRIV_OUTLN2;&lt;/pre&gt;
&lt;p&gt;设置使用，调整完毕&lt;/p&gt;
&lt;pre&gt;alter system set use_stored_outlines=true;&lt;/pre&gt;
&lt;p&gt;这样操作的原因是因为stroed outline必须依赖SQL的文本匹配，所以，我们利用加hints之后的SQL产生正确的执行计划，并通过交换的方式，让SQL的执行计划变成我们想要的结果。当然，如果你愿意，也可以直接修改ol$hints表的内容，同样可以达到改变执行计划的目的。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617862/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/tuning_sql_execution_plan.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617862/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617862/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2010/01/tuning_sql_execution_plan.html/feed</wfw:commentRss><description>对于一个高并发的OLTP系统，SQL执行计划的改变往往意味着灾难。很多因素都可能导致执行计划发生不可预期的改变，比如表结构，索引，统计信息等变化，甚至我们发生过一个小小的grant操作，导致执行计划失效，重新解析后生成了一个不正确的执行计，让整个系统Crash的案例。最近，我们对一个分区表增加分区后，导致了执行计划发生改变，故障再次重演。
如何控制SQL的执行计划就成为了一个课题，之前我曾经写过一篇关于调整SQL执行计划的文章，但是内容比较粗略。因为Oracle提供了很多手段去控制执行计划，所以我打算为每个版本都整理一个最佳实践。
我们设想一个场景，一个SQL本来应该走nested loop join，但是由于某种原因，突然变成了hash join，调整统计信息无效，数据库load不断升高，只留给你很少的时间，怎么办？最直接有效的方法是在SQL上加hints，但是需要程序发布，或者程序根本无法修改。
9i为我们提供了Stored outline，大家都非常熟悉，但是对于上面的场景，还是需要点技巧。方法是：生成两个stored outline，一条是错误的，一条是正确的（加hints），两个然后将其执行计划交换。看下面的步骤：
1.创建两个public stroed outline，第一个是目前运行的，第二个是加了hints.
create or replace outline OUTLN1 on select e.ename from emp e, dept d where e.deptno=d.deptno;
create or replace outline OUTLN2 on select /*+ use_nl(e d)*/ e.ename from emp e, dept d
where e.deptno=d.deptno;
拷贝成为private outline
create or replace private outline PRIV_OUTLN1 from OUTLN1;
create or replace private outline PRIV_OUTLN2 from OUTLN2;
交换两个stored outline的执行计划
update ol$ [...]&lt;img src=&quot;http://www1.feedsky.com/t1/331617862/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/tuning_sql_execution_plan.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617862/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617862/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>最佳实践</category><category>ORACLE</category><category>大话技术</category><pubDate>Thu, 28 Jan 2010 20:07:05 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/01/tuning_sql_execution_plan.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1342</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/01/tuning_sql_execution_plan.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617862/5126880</fs:itemid></item><item><title>online rebuild发生的问题</title><link>http://www.hellodba.net/2010/01/online_rebuil.html</link><content:encoded>&lt;p&gt;朋友遇到一个问题，当建立一个包含varchar2(4000)的索引时，直接创建没有问题，但是如果加上online子句，则报错：&lt;/p&gt;
&lt;p&gt;ORA-00604: error occurred at recursive SQL level 1&lt;br /&gt;
ORA-01450: maximum key length (3215) exceeded&lt;/p&gt;
&lt;p&gt;这里实际上包含了两个问题：&lt;/p&gt;
&lt;p&gt;1.索引的key到底可以有多大？因为索引的key是不可以跨越block的，所以最直接的决定因素是block size，Oracle的文档给出了一个计算公式：&lt;/p&gt;
&lt;pre&gt;&lt;span&gt;&lt;span style=&quot;font-family: Courier New,Courier,mono;&quot;&gt;DB_BLOCK_SIZE:                  Maximum Index Key Length:
==============                  =========================

2K  (2048)                       758  Bytes
4K  (4096)                       1578 Bytes
8K  (8192)                       3218 Bytes
16K (16384)                      6498 Bytes
&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;文档中说：每个index leaf block至少有两行记录，考虑block header，PCTFREE，INITRANS等因素，每个index key最大可以为block size的40%。但是我测试了一下（8K block size），发现并不是如此。&lt;/p&gt;
&lt;p&gt;create table test(id varchar2(4000),id2 varchar2(3000));&lt;br /&gt;
create index test_ind on test(id,id2);&lt;br /&gt;
ORA-01450: maximum key length (6398) exceeded&lt;/p&gt;
&lt;p&gt;最大的长度是6398，而不是文档中提到的3218，后来我把block dump出来，发现每个index leaf block中只有一行，而不是文档中所说的至少有两行，这样index key的最大值就自然变大了，大约为block size的80%。为什么与文档上不一致，应该是版本的问题，文档描述的是在9i之前的情况，而9i之后Oracle作了改进（没有8i的环境，没法证实）。&lt;/p&gt;
&lt;p&gt;2.为什么online无法创建，而直接创建没有问题呢？&lt;/p&gt;
&lt;p&gt;因为online创建的过程中会生成一个中间表，用来记录创建过程中的变化，而这个表是IOT表。经过测试，发现IOT表的限制比较严格，8k的block size，最大长度只能有3215，所以普通创建可以成功，而online创建则不行，关键还在背后的IOT表上。&lt;/p&gt;
&lt;p&gt;怎么解决这个问题，Oracle的官方说法是加大block size，但是对于IOT表，我们发现加大block size并没有太大作用，最大长度也只有3800。看来，对于INDEX每个block可以只存放一条，而IOT比较特殊，每个block需要至少存放两条记录。简单点说，IOT的限制比普通INDEX更严格一些，至于为什么，我想也许没什么特别的原因吧，也许只是版本改进过程中的代码问题。&lt;/p&gt;
&lt;p&gt;我很奇怪，怎么会在varchar2(4000)的字段上建索引呢？一问才知道，原来这个字段实际内容并不长，但是当时设计时，可能是为了方便，直接设计成最大值了，才导致现在的问题。现在只能想办法，重新建一个适当长度的字段，把内容拷贝过去，然后再建立索引。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617901/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/online_rebuil.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617901/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617901/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2010/01/online_rebuil.html/feed</wfw:commentRss><description>朋友遇到一个问题，当建立一个包含varchar2(4000)的索引时，直接创建没有问题，但是如果加上online子句，则报错：
ORA-00604: error occurred at recursive SQL level 1
ORA-01450: maximum key length (3215) exceeded
这里实际上包含了两个问题：
1.索引的key到底可以有多大？因为索引的key是不可以跨越block的，所以最直接的决定因素是block size，Oracle的文档给出了一个计算公式：
DB_BLOCK_SIZE:                  Maximum Index Key Length:
==============                  =========================

2K  (2048) [...]&lt;img src=&quot;http://www1.feedsky.com/t1/331617901/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/online_rebuil.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617901/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617901/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>ORACLE</category><category>大话技术</category><pubDate>Tue, 26 Jan 2010 21:12:20 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/01/online_rebuil.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1337</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/01/online_rebuil.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617901/5126880</fs:itemid></item><item><title>我这五年</title><link>http://www.hellodba.net/2010/01/five_years.html</link><content:encoded>&lt;p&gt;不知不觉，来杭州已经五年了。翻看了以前的blog，里面记录了我这五年的心路历程。&lt;/p&gt;
&lt;p&gt;2004年12月27日，&lt;a href=&quot;http://freezr.itpub.net/post/2382/12008&quot;&gt;《新的征程》&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“上帝关上了一扇门，总会打开一扇窗。所以，别担心。”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2005年3月19日，&lt;a href=&quot;http://freezr.itpub.net/post/2382/22795&quot;&gt;《杭州两个月》&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;“说说工作吧，刚来的时候，我感觉到很大的压力，毕竟我和周围的同事相比，水平还差很多。但是发现 BITI，RUDOLF，GRASSBELL，FENNG，WANGHAI，CHENYP，CHENJP，都对我非常的好。虽然我的水平很差，但是有什么 问题，都耐心的给我讲，让我很感动，尤其是BITI，能在这样的环境中工作，我感觉很满足。”&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2005年7月28日，&lt;a href=&quot;http://freezr.itpub.net/post/2382/36560&quot;&gt;《一致读的实现》&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一次有点技术含量的文章，现在看起来依然很优雅，短短几句话，就将一致读的原理解释的清清楚楚:)&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2007年3月4日，&lt;a href=&quot;http://freezr.itpub.net/post/2382/276043&quot;&gt;《细节决定成败》&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;做DBA的第一次犯错。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2007年5月19日，&lt;a href=&quot;http://freezr.itpub.net/post/2382/288635&quot;&gt;《IBM P570+DMX3》&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;第一次跟着老大做项目，学到了很多东西，现在仍然受益匪浅。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2008年1月1日，&lt;a href=&quot;http://freezr.itpub.net/post/2382/448318&quot;&gt;《我的2007》&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2007年，终于实现了梦寐以求的目标，正式当上了DBA。比当DBA更重要的是，当上了别人的爹。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;2008年3月6日，&lt;a href=&quot;http://freezr.itpub.net/post/2382/456581&quot;&gt;《我有压力 未解决》&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;“工作是挣扎滴，前途是渺茫滴&lt;br /&gt;
压力是很大滴，解决是没有滴&lt;br /&gt;
抱怨是没用滴，开心是重要滴&lt;br /&gt;
&lt;strong&gt;未来是光明滴，什么都会有滴&lt;/strong&gt;”&lt;/p&gt;
&lt;p&gt;五年时光，很快就过去了，虽然没成就什么大事业，不过也算是小有成就，感谢家人和朋友的支持，真是挺不容易的。&lt;/p&gt;
&lt;p&gt;一直一来，我的梦想是成为象BITI那样的技术大牛，也一直为了这个目标而努力，但是今年情况可能发生了变化，我从技术岗位调整为管理岗位，这本不是我的意愿和初衷，但是我也欣然接受。未来我将把更多的心思放在团队身上，努力让每个人都能从团队发展的过程中受益。&lt;/p&gt;
&lt;p&gt;我不会放弃自己的梦想，大师说过：只有自己坚信，才会有人同路。我坚信现在的工作是有价值的，我坚信所有的痛都是暂时的，我坚信付出总有一天会有回报的，我坚信&amp;#8230;&amp;#8230;&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617905/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/five_years.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617905/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617905/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2010/01/five_years.html/feed</wfw:commentRss><description>不知不觉，来杭州已经五年了。翻看了以前的blog，里面记录了我这五年的心路历程。
2004年12月27日，《新的征程》
“上帝关上了一扇门，总会打开一扇窗。所以，别担心。”
2005年3月19日，《杭州两个月》
“说说工作吧，刚来的时候，我感觉到很大的压力，毕竟我和周围的同事相比，水平还差很多。但是发现 BITI，RUDOLF，GRASSBELL，FENNG，WANGHAI，CHENYP，CHENJP，都对我非常的好。虽然我的水平很差，但是有什么 问题，都耐心的给我讲，让我很感动，尤其是BITI，能在这样的环境中工作，我感觉很满足。”
2005年7月28日，《一致读的实现》
第一次有点技术含量的文章，现在看起来依然很优雅，短短几句话，就将一致读的原理解释的清清楚楚:)
2007年3月4日，《细节决定成败》
做DBA的第一次犯错。
2007年5月19日，《IBM P570+DMX3》
第一次跟着老大做项目，学到了很多东西，现在仍然受益匪浅。
2008年1月1日，《我的2007》
2007年，终于实现了梦寐以求的目标，正式当上了DBA。比当DBA更重要的是，当上了别人的爹。
2008年3月6日，《我有压力 未解决》
“工作是挣扎滴，前途是渺茫滴
压力是很大滴，解决是没有滴
抱怨是没用滴，开心是重要滴
未来是光明滴，什么都会有滴”
五年时光，很快就过去了，虽然没成就什么大事业，不过也算是小有成就，感谢家人和朋友的支持，真是挺不容易的。
一直一来，我的梦想是成为象BITI那样的技术大牛，也一直为了这个目标而努力，但是今年情况可能发生了变化，我从技术岗位调整为管理岗位，这本不是我的意愿和初衷，但是我也欣然接受。未来我将把更多的心思放在团队身上，努力让每个人都能从团队发展的过程中受益。
我不会放弃自己的梦想，大师说过：只有自己坚信，才会有人同路。我坚信现在的工作是有价值的，我坚信所有的痛都是暂时的，我坚信付出总有一天会有回报的，我坚信&amp;#8230;&amp;#8230;
&amp;#8211;EOF&amp;#8211;&lt;img src=&quot;http://www1.feedsky.com/t1/331617905/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/five_years.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617905/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617905/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>一地鸡毛</category><category>无病呻吟</category><category>it's my life</category><pubDate>Tue, 26 Jan 2010 13:59:36 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/01/five_years.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1326</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/01/five_years.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617905/5126880</fs:itemid></item><item><title>一种并行加载的方法</title><link>http://www.hellodba.net/2010/01/parallel_apply.html</link><content:encoded>&lt;p&gt;一个数据库的同步系统，可以分为三部分：抓取变化，传输和加载。抓取数据库变化，最通常的做法是用trigger记录到表中，或者通过解析Oracle redo log中的信息来抓取。传输是将数据库变化记录到特定格式的文件中，通过网络推送到目标数据库上。加载则是指在目标数据库上应用这些变化（SQL），这里主要是讨论并行加载的实现思路。&lt;/p&gt;
&lt;p&gt;我们通过trigger或者redo log得到了数据库变化的事务流，这个流是按照事务的提交顺序排列的，最简单的方法是在目标端按照这个事务流顺序执行，就是串行执行。这么做的最大优点是可以完全保证事务的一致性，但是缺点是性能很差。如果采用并行加载，就需要考虑事务相关性的问题，所谓事务相关性，是指两个或多个事务更新了同一条或者多条记录，他们之前存在时间上的依赖关系。如果将具有相关性的事务分在不同的并发进程上加载，可能出现后面的事务被前面的事务覆盖掉的情况，最终导致事务混乱。&lt;/p&gt;
&lt;p&gt;我们设计一个并行加载的方法，目标是尽可能快的加载数据，保证不会产生数据混乱的情况，但是不能保证事务完全的一致性。这句话如何理解，假设两个事务不相关，A事务只更新A表，B事务只更新B表，如果在源库A事务先于B事务完成，那么在目标库可以让B事务先于A事务执行，或者两个事务并行执行，虽然事务的顺序与主库并不一致，但是数据是正确的，因为两个事务不相关。&lt;/p&gt;
&lt;p&gt;我们如果按照事务去分拆并行的话，设计比较困难，因为涉及到事务的相关性分析。换个思路，我们可以按照数据来拆分并行，也就是把同一个事务拆分到不同的并发进程中，保证表的同一行记录的所有更改都由一个并发进程处理。按照这个思路，我们首先把事务流加载到一个队列或者一个内存结构中去，为了理解方便，我们可以认为放在了一张内存表中，这个表有以下几个字段，事务ID，表名，PK，SQL，时间序列号。首先&lt;strong&gt;按照不同的表分组&lt;/strong&gt;，将不同的表的操作分配给不同的进程处理，每个并发进程按照事务提交的时间顺序来执行。比如：A事务更新A,B,C三张表的A1,B1,C1记录，B事务更新A,B,C三张表的A2,B2,C2记录，C事务更新A,B,C三张表的A3,B3,C3记录。三个事务的提交顺序是A,B,C，这时我们可以启动三个并发进程，分别处理A表，B表和C表的操作，顺序是A1,A2,A3&amp;#8230;&amp;#8230;这样就实现了最简单的并行，虽然目标库的事务与主库并不一致，但是数据是完整和正确的。&lt;/p&gt;
&lt;p&gt;按照表来做并行可能还不足够，如果某张表的更改量特别大，这时我们还可以进一步分组，针对同一张表中的操作再&lt;strong&gt;按照行（PK）分组&lt;/strong&gt;，保证同一行的不同操作分配到同一个的并发进程处理。这里有一些小的技巧，在很多情况下，我们可以只关注某行的最后一个操作就可以了，比如某行的最后一个操作是delete，那么我们只需要执行delete，之前的操作就可以直接丢弃，如果是insert，那么我们可以在目标库先执行delete，然后再insert，针对我们自己的系统，有些表的update是全部字段更新，所以我们直接采用了merge操作，相当于对同一行的不同操作，我们做了合并处理。因为系统是自己开发的，所以可以针对我们自己的特性定制了功能。&lt;/p&gt;
&lt;p&gt;有人说这个思路有些土，Oracle logical standby，Goldengate或者Shareplex这些商业软件是怎么做的？我之前也写过一篇文章探讨这个问题：&lt;a href=&quot;http://www.hellodba.net/2009/05/logical-standby.html&quot;&gt;Oracle Logical Standby SQL Apply Architecture&lt;/a&gt;，这些商业软件都声称自己分析了事务的相关性，可以做到并行加载，但是同样也存在事务不一致的问题，但是分析事务的相关性肯定要按照表或者行来分析，所以思路应该不会差太远，无非是他们包装得更好。&lt;/p&gt;
&lt;p&gt;PS:这个方法并不是我想出来的，是团队的智慧。现在看起来思路挺简单，但是其实困扰了我们很长的时间。当然如果你有更好的方法，欢迎和我讨论。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617907/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/parallel_apply.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617907/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617907/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2010/01/parallel_apply.html/feed</wfw:commentRss><description>一个数据库的同步系统，可以分为三部分：抓取变化，传输和加载。抓取数据库变化，最通常的做法是用trigger记录到表中，或者通过解析Oracle redo log中的信息来抓取。传输是将数据库变化记录到特定格式的文件中，通过网络推送到目标数据库上。加载则是指在目标数据库上应用这些变化（SQL），这里主要是讨论并行加载的实现思路。
我们通过trigger或者redo log得到了数据库变化的事务流，这个流是按照事务的提交顺序排列的，最简单的方法是在目标端按照这个事务流顺序执行，就是串行执行。这么做的最大优点是可以完全保证事务的一致性，但是缺点是性能很差。如果采用并行加载，就需要考虑事务相关性的问题，所谓事务相关性，是指两个或多个事务更新了同一条或者多条记录，他们之前存在时间上的依赖关系。如果将具有相关性的事务分在不同的并发进程上加载，可能出现后面的事务被前面的事务覆盖掉的情况，最终导致事务混乱。
我们设计一个并行加载的方法，目标是尽可能快的加载数据，保证不会产生数据混乱的情况，但是不能保证事务完全的一致性。这句话如何理解，假设两个事务不相关，A事务只更新A表，B事务只更新B表，如果在源库A事务先于B事务完成，那么在目标库可以让B事务先于A事务执行，或者两个事务并行执行，虽然事务的顺序与主库并不一致，但是数据是正确的，因为两个事务不相关。
我们如果按照事务去分拆并行的话，设计比较困难，因为涉及到事务的相关性分析。换个思路，我们可以按照数据来拆分并行，也就是把同一个事务拆分到不同的并发进程中，保证表的同一行记录的所有更改都由一个并发进程处理。按照这个思路，我们首先把事务流加载到一个队列或者一个内存结构中去，为了理解方便，我们可以认为放在了一张内存表中，这个表有以下几个字段，事务ID，表名，PK，SQL，时间序列号。首先按照不同的表分组，将不同的表的操作分配给不同的进程处理，每个并发进程按照事务提交的时间顺序来执行。比如：A事务更新A,B,C三张表的A1,B1,C1记录，B事务更新A,B,C三张表的A2,B2,C2记录，C事务更新A,B,C三张表的A3,B3,C3记录。三个事务的提交顺序是A,B,C，这时我们可以启动三个并发进程，分别处理A表，B表和C表的操作，顺序是A1,A2,A3&amp;#8230;&amp;#8230;这样就实现了最简单的并行，虽然目标库的事务与主库并不一致，但是数据是完整和正确的。
按照表来做并行可能还不足够，如果某张表的更改量特别大，这时我们还可以进一步分组，针对同一张表中的操作再按照行（PK）分组，保证同一行的不同操作分配到同一个的并发进程处理。这里有一些小的技巧，在很多情况下，我们可以只关注某行的最后一个操作就可以了，比如某行的最后一个操作是delete，那么我们只需要执行delete，之前的操作就可以直接丢弃，如果是insert，那么我们可以在目标库先执行delete，然后再insert，针对我们自己的系统，有些表的update是全部字段更新，所以我们直接采用了merge操作，相当于对同一行的不同操作，我们做了合并处理。因为系统是自己开发的，所以可以针对我们自己的特性定制了功能。
有人说这个思路有些土，Oracle logical standby，Goldengate或者Shareplex这些商业软件是怎么做的？我之前也写过一篇文章探讨这个问题：Oracle Logical Standby SQL Apply Architecture，这些商业软件都声称自己分析了事务的相关性，可以做到并行加载，但是同样也存在事务不一致的问题，但是分析事务的相关性肯定要按照表或者行来分析，所以思路应该不会差太远，无非是他们包装得更好。
PS:这个方法并不是我想出来的，是团队的智慧。现在看起来思路挺简单，但是其实困扰了我们很长的时间。当然如果你有更好的方法，欢迎和我讨论。
&amp;#8211;EOF&amp;#8211;&lt;img src=&quot;http://www1.feedsky.com/t1/331617907/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/parallel_apply.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617907/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617907/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>ORACLE</category><category>大话技术</category><pubDate>Thu, 07 Jan 2010 23:05:20 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/01/parallel_apply.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1315</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/01/parallel_apply.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617907/5126880</fs:itemid></item><item><title>《我的2009》定妆照</title><link>http://www.hellodba.net/2010/01/2009_photo.html</link><content:encoded>&lt;p&gt;打算每年都给自己和家人拍几张照片，以此来纪念每一年的变化。本来是想照几张严肃点的，但是室内的效果实在不怎么样。元旦天气不错，带家人去了趟玉皇山，就作为《我的2009》的定妆照吧。&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;tt-flickr tt-flickr-Medium&quot; title=&quot;DSC_1991&quot; href=&quot;http://www.flickr.com/photos/hellodba/4247615066/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4009/4247615066_ca65f69d63.jpg&quot; alt=&quot;DSC_1991&quot; width=&quot;500&quot; height=&quot;333&quot; /&gt;&lt;/a&gt; &lt;a class=&quot;tt-flickr tt-flickr-Medium&quot; title=&quot;DSC_2006&quot; href=&quot;http://www.flickr.com/photos/hellodba/4246842783/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4066/4246842783_a25c23f08f.jpg&quot; alt=&quot;DSC_2006&quot; width=&quot;500&quot; height=&quot;333&quot; /&gt;&lt;/a&gt; &lt;a class=&quot;tt-flickr tt-flickr-Medium&quot; title=&quot;DSC_1986&quot; href=&quot;http://www.flickr.com/photos/hellodba/4246840679/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4051/4246840679_8520b49daf.jpg&quot; alt=&quot;DSC_1986&quot; width=&quot;500&quot; height=&quot;333&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在玉皇山顶，因为可以看到西湖，又可以看到钱塘江，所以叫“一统江湖”，希望2010年我也可以达成自己的目标，在自己的江湖世界里，一统江湖！&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617909/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/2009_photo.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617909/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617909/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2010/01/2009_photo.html/feed</wfw:commentRss><description>打算每年都给自己和家人拍几张照片，以此来纪念每一年的变化。本来是想照几张严肃点的，但是室内的效果实在不怎么样。元旦天气不错，带家人去了趟玉皇山，就作为《我的2009》的定妆照吧。
  
在玉皇山顶，因为可以看到西湖，又可以看到钱塘江，所以叫“一统江湖”，希望2010年我也可以达成自己的目标，在自己的江湖世界里，一统江湖！
&amp;#8211;EOF&amp;#8211;&lt;img src=&quot;http://www1.feedsky.com/t1/331617909/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/2009_photo.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617909/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617909/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>一地鸡毛</category><category>摄影</category><category>it's my life</category><category>边走边拍</category><pubDate>Tue, 05 Jan 2010 17:12:20 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/01/2009_photo.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1317</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/01/2009_photo.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617909/5126880</fs:itemid></item><item><title>我的2009</title><link>http://www.hellodba.net/2010/01/2009.html</link><content:encoded>&lt;p&gt;又到了一年一度总结的时候了，其实挺害怕总结这事的，因为每次回头看过去的一年，总是感觉有些失落。&lt;/p&gt;
&lt;p&gt;2009年最大的事就是搬进了自己的家，不管装修的过程多么曲折，但是结局是圆满的。同事们戏称我是“品质”男，殊不知追求品质是要付出代价的。&lt;/p&gt;
&lt;p&gt;工作上逐步脱离了一线环境，带了一个小团队，负责了一个项目，为了这个团队和项目，付出了很多心血。谋事在人，成事在天，不管结果怎样，我问心无愧。&lt;/p&gt;
&lt;p&gt;这一年我一直在寻找自己的方向，如何在远离一线环境后，继续提高技术水平。“多读，多写，多教”是我摸索出来的方法：从问题出发，在找寻答案的过程中，不断思考，最终提炼为简单的道理。“教是最好的学”，所以我会尽可能的讲给别人，或者与别人讨论，从中发现漏洞并完善。&lt;/p&gt;
&lt;p&gt;这一年，同事们都说我越来越能“忽悠”了，我觉得这句话是在夸我，因为我大部分忽悠的是技术问题，尤其是当我弄明白了某件事情之后，就有强烈的欲望与别人分享。最近尤其喜欢和别人切磋技术，很多东西不辨不明。遇到志同道合的人讨论技术，很快乐，很鸡冻。&lt;/p&gt;
&lt;p&gt;Blog还在写，大道至简是我的风格，期望用最简单的语言把技术问题讲明白，不会有任何操作手册类的文章，虽然篇幅不多，但是每一篇都经过了思考和提炼。Twitter每天都在写，大部分是工作和生活中的感悟，有时候也会写点小抱怨，这个东西，真得挺好。&lt;/p&gt;
&lt;p&gt;2009年另外一个技术上的提升是，熟练掌握了翻墙的技能，并在各种场合教别人如何翻墙，就算我们不关心政治，翻墙去寻找一些技术上的资料，也是一个技术人员必备的技能。&lt;/p&gt;
&lt;p&gt;我这个岁数的老男人，已经进入了一个舒适区，每天上班下班回家抱孩子，不希望有什么改变。明年要打破这个舒适区，给自己更高的期望，寻求突破。&lt;/p&gt;
&lt;p&gt;2009年就这样了，虽然没啥大成就，但是也没虚度光阴。路在前方，还得继续走，看看2010年的几个事：&lt;/p&gt;
&lt;p&gt;家庭和谐是最高目标，为老爸当好IT支持，为老婆当好司机，为儿子当好爸爸，为老妈当好儿子。&lt;/p&gt;
&lt;p&gt;工作上继续为那个小团队和那个项目努力，兄弟们跟着我，我总得走在前面吧。&lt;/p&gt;
&lt;p&gt;多读，多写，多教，技术上提高，突破自我，影响团队，努力向大牛们靠拢。&lt;/p&gt;
&lt;p&gt;旅游什么就不指望了，等儿子长大了，财务自由了，全部补回来。&lt;/p&gt;
&lt;p&gt;苦练内功，我为自己定了一个目标，三年内要&amp;#8230;&amp;#8230;不成功就转行娱乐圈了。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;
&lt;p&gt;“他强任他强 清风拂山岗 他横任他横 明月照大江”&amp;#8212;给所有为了生活苦苦奋斗的70后老男人。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617910/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/2009.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617910/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617910/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2010/01/2009.html/feed</wfw:commentRss><description>又到了一年一度总结的时候了，其实挺害怕总结这事的，因为每次回头看过去的一年，总是感觉有些失落。
2009年最大的事就是搬进了自己的家，不管装修的过程多么曲折，但是结局是圆满的。同事们戏称我是“品质”男，殊不知追求品质是要付出代价的。
工作上逐步脱离了一线环境，带了一个小团队，负责了一个项目，为了这个团队和项目，付出了很多心血。谋事在人，成事在天，不管结果怎样，我问心无愧。
这一年我一直在寻找自己的方向，如何在远离一线环境后，继续提高技术水平。“多读，多写，多教”是我摸索出来的方法：从问题出发，在找寻答案的过程中，不断思考，最终提炼为简单的道理。“教是最好的学”，所以我会尽可能的讲给别人，或者与别人讨论，从中发现漏洞并完善。
这一年，同事们都说我越来越能“忽悠”了，我觉得这句话是在夸我，因为我大部分忽悠的是技术问题，尤其是当我弄明白了某件事情之后，就有强烈的欲望与别人分享。最近尤其喜欢和别人切磋技术，很多东西不辨不明。遇到志同道合的人讨论技术，很快乐，很鸡冻。
Blog还在写，大道至简是我的风格，期望用最简单的语言把技术问题讲明白，不会有任何操作手册类的文章，虽然篇幅不多，但是每一篇都经过了思考和提炼。Twitter每天都在写，大部分是工作和生活中的感悟，有时候也会写点小抱怨，这个东西，真得挺好。
2009年另外一个技术上的提升是，熟练掌握了翻墙的技能，并在各种场合教别人如何翻墙，就算我们不关心政治，翻墙去寻找一些技术上的资料，也是一个技术人员必备的技能。
我这个岁数的老男人，已经进入了一个舒适区，每天上班下班回家抱孩子，不希望有什么改变。明年要打破这个舒适区，给自己更高的期望，寻求突破。
2009年就这样了，虽然没啥大成就，但是也没虚度光阴。路在前方，还得继续走，看看2010年的几个事：
家庭和谐是最高目标，为老爸当好IT支持，为老婆当好司机，为儿子当好爸爸，为老妈当好儿子。
工作上继续为那个小团队和那个项目努力，兄弟们跟着我，我总得走在前面吧。
多读，多写，多教，技术上提高，突破自我，影响团队，努力向大牛们靠拢。
旅游什么就不指望了，等儿子长大了，财务自由了，全部补回来。
苦练内功，我为自己定了一个目标，三年内要&amp;#8230;&amp;#8230;不成功就转行娱乐圈了。
&amp;#8211;EOF&amp;#8211;
“他强任他强 清风拂山岗 他横任他横 明月照大江”&amp;#8212;给所有为了生活苦苦奋斗的70后老男人。&lt;img src=&quot;http://www1.feedsky.com/t1/331617910/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/01/2009.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617910/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617910/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>一地鸡毛</category><category>it's my life</category><pubDate>Fri, 01 Jan 2010 00:10:27 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/01/2009.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1299</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/01/2009.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617910/5126880</fs:itemid></item><item><title>Oracle排序算法</title><link>http://www.hellodba.net/2009/12/oracle_sort.html</link><content:encoded>&lt;p&gt;大牛jonathan lewis在圣诞节出了一个小题目：&lt;a rel=&quot;bookmark&quot; href=&quot;http://jonathanlewis.wordpress.com/2009/12/24/holiday-quiz/&quot;&gt;Holiday Quiz&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I have a table with one million rows, there are no indexes on the table. The table has a column called &lt;em&gt;&lt;strong&gt;sortcode &lt;/strong&gt;&lt;/em&gt;which has no nulls, and has been generated in a highly random way so that no value appears more than four times. Consider the following queries:&lt;/p&gt;
&lt;div id=&quot;highlighter_32022&quot; class=&quot;syntaxhighlighter  sql&quot;&gt;
&lt;div class=&quot;lines&quot;&gt;
&lt;p class=&quot;line alt1&quot;&gt;
&lt;table style=&quot;height: 130px;&quot; border=&quot;0&quot; width=&quot;287&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td class=&quot;number&quot;&gt;select sortcode&lt;br /&gt;
from t1&lt;br /&gt;
order by sortcode;&lt;/p&gt;
&lt;p&gt;select  sortcode&lt;br /&gt;
from (&lt;br /&gt;
select sortcode&lt;br /&gt;
from t1&lt;br /&gt;
order by sortcode&lt;br /&gt;
) where rownum &amp;lt;= 10;&lt;/td&gt;
&lt;td class=&quot;content&quot;&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;How many rows are sorted in each of these two queries – and roughly how much memory would you expect Oracle to use ?&lt;/p&gt;
&lt;p&gt;从表面上看，两个SQL仅仅是返回数量的不同，因为没有索引，所以就算只返回10行，但是也必须完成整个排序过程，所以从排序的资源消耗上，两者应该没有太大差异。&lt;/p&gt;
&lt;p&gt;Jonathan公布了答案：&lt;a href=&quot;http://jonathanlewis.wordpress.com/2009/12/28/short-sorts/&quot;&gt;Short sort&lt;/a&gt;，主要是Oracle引入了一个针对sort的改进，即&lt;strong&gt;version 1 sort&lt;/strong&gt;，大致原理是用一个&lt;strong&gt;二叉树&lt;/strong&gt;来保存最终需要返回的记录，并且记录这个二叉树中最大的值，针对每个值逐一与这个最大值比较，如果大于这个最大值就直接丢弃（因为这里要寻找最小的10条记录），如果小于最大值，则插入到这个二叉树中去，最终返回这10条记录。因为普通的排序要返回所有记录，如果也采用这个存储方式，即用二叉树来存储排序的结果，可能非常耗费内存，所以这个改进只针对返回结果集比较少的情况。另外用二叉树，可以迅速的找到插入的位置，减少比较的次数。最后Jonathan还用三个极端情况来证明了这个排序算法的效果，正序，反序和随机，正序和随机时，因为大部分值都在第一次比较就被丢弃，所以占用内存和比较次数都很少；相反，如果是反序的情况，因为几乎所有的值都需要插入到这个二叉树中，占用内存和比较次数都大幅度增加，关于这个话题大家可以看Jonathan的博客，这里不再赘述。&lt;/p&gt;
&lt;p&gt;我这里想讨论另外一个话题，Oracle到底采用什么排序算法？我查阅了很多资料，都没有提及。学过计算机的人都知道排序算法是一个古老而又有趣的话题，我们熟知的有：冒泡排序，选择排序和插入排序，这三种排序算法比较简单，但是效率不高。高效率的排序算法有：快速排序，堆排序和归并排序，我们下来大致介绍下这三个排序算法。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;快速排序&lt;/strong&gt;是采用分治法的策略，即分而治之，首选选取一个中枢值（一般选序列中的第一个数），每次规划将序列按照这个中枢值分成两个序列，左边的序列都比中枢值小，而右边的序列都比中枢值大，一次规划完成后，中枢值找到了其最终的位置，并且将原有序列分为两个部分，然后再用同样的方法分别处理这两个序列，直到排序全部完成。快速排序是一种效率很高的排序算法，如果采用原地分割的算法，快速排序占用很少的额外空间。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;堆排序&lt;/strong&gt;有点类似于插入排序，但是他利用了堆积树（堆）这种数据结构，堆积树其实就是一棵完全二叉树，但是又满足堆属性：子节点的属性总是大于或者小于其父节点，即所谓的大根堆和小根堆。排序的过程实际上就是把数据不断插入到堆积树上，而返回排序结果的过程就是不断取堆的最大（大根堆）或者最小值（小根堆），并不断缩小堆的过程。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;归并排序&lt;/strong&gt;就是将两个或多个有序的序列合并为一个有序序列的排序过程，称为两路归并排序和多路归并排序。归并排序的算法是在每个有序队列上设置一个指针，通过不断移动指针，在每个序列上取出元素进行比较，并合并的过程。归并排序通常使用在外部排序中。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;内排序和外排序&lt;/strong&gt;，内排序指在内存中完成的排序过程，外排序指排序内容无法在内存中一次完成，而需要借助外部存储来完成排序的过程。&lt;/p&gt;
&lt;p&gt;根据Jonathan的实验，我们可以看到上面这个排序优化的例子，实际上利用了&lt;strong&gt;堆排序&lt;/strong&gt;的特性，但是由于堆积树本身需要额外的空间，在返回记录数很多的情况下，并不适合，实验也证明，如果采用堆积树来保存所有记录，需要占用更多的空间。关于Oracle的排序算法，虽然不是很明确，但是很可能是&lt;strong&gt;快速排序&lt;/strong&gt;的一种，因为快速排序占用稳定的空间，通常情况下可以提供很好的效率。如果排序无法在内存中一次完成，Oracle需要借助Temp空间，这就是&lt;strong&gt;外排序&lt;/strong&gt;，Oracle使用&lt;strong&gt;多路归并排序&lt;/strong&gt;算法，按照排序区大小把结果集切分成多个子集，每个子集在内存中完成排序，然后将他们合并起来。排序区大小对归并排序的性能影响很大，排序区应该能至少容纳每个子集中的一条记录，否则性能会急剧下降。&lt;/p&gt;
&lt;p&gt;Oracle的排序算法我们并不了解，以上内容很多也是基于Jonathan的实验的猜测，所以大家别较真。对于排序算法本身，我的描述并不一定正确，欢迎大家批评指正。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617922/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2009/12/oracle_sort.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617922/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617922/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2009/12/oracle_sort.html/feed</wfw:commentRss><description>大牛jonathan lewis在圣诞节出了一个小题目：Holiday Quiz
I have a table with one million rows, there are no indexes on the table. The table has a column called sortcode which has no nulls, and has been generated in a highly random way so that no value appears more than four times. Consider the following queries:






select sortcode
from t1
order by sortcode;
select  sortcode
from (
select [...]&lt;img src=&quot;http://www1.feedsky.com/t1/331617922/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2009/12/oracle_sort.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617922/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617922/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>ORACLE</category><category>大话技术</category><pubDate>Wed, 30 Dec 2009 13:07:51 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2009/12/oracle_sort.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1287</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2009/12/oracle_sort.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617922/5126880</fs:itemid></item><item><title>用ASM和iSCSI实现的另类HA方案</title><link>http://www.hellodba.net/2009/12/asm_iscsi_heartbeat.html</link><content:encoded>&lt;p&gt;普通PC本地磁盘，没有共享存储，如何实现HA？Dataguard挺好，但是存在数据丢失的可能性，而且很难做到应用透明切换。我们用ASM,Heartbeat和iSCSI可以实现一个廉价的HA方案，如下图：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2009/12/myimage2.png&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1282&quot; title=&quot;myimage2&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2009/12/myimage2.png&quot; alt=&quot;&quot; width=&quot;500&quot; height=&quot;238&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;用iSCSI将本地磁盘输出到对方的机器上，利用ASM的failgroup做mirror，保证数据mirror在两台不同的机器上，就算一台机器完全损坏，数据可以做到百分之百不丢失。用Heartbeat作HA探测，如果发现主机故障，则强行关闭DB和ASM，并在备机启动ASM和DB。如果使用Oracle 11g R2，还可以利用Preferred mirror read的特性，保证主库读自己的本地磁盘，而不是通过iSCSI读备机磁盘，这样可以达到更好的性能。&lt;/p&gt;
&lt;p&gt;缺点：Heartbeat作为HA软件，我们并不是十分了解其探测机制，可能出现误判或者无法切换的情况。但是其实IBM hacmp这种HA软件一样有问题，比如Oracle hang住时，现在的hacmp根本无法探测，因为hacmp只是判断Oracle的进程在不在，而不管数据库是否活着。&lt;/p&gt;
&lt;p&gt;我想不管什么HA软件，都无法处理所有的异常情况，我们只要有完善的监控和应对措施就可以了。比如我们现在所有的DB都有一个监控，就是定时模拟应用去更新数据库中的数据，如果发现超时或者报错，就认为数据库出现hang的情况，并发出报警。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;
&lt;p&gt;另：之前我有一篇文章介绍用ASM和iSCSI搭建RAC的文章，在实际测试过程中，发现存在一些问题，因为在11g R2之前，voting disk和OCR都必须放在RAW devices上。因为没有共享存储，如果发生某台机器全部宕机，voting disk可能会丢失一部分，造成RAC的cluster机制发生误判。所以在11g R2之前，这个方案是有问题的，在11g R2中，Oracle几乎所有的东西都可以放在ASM中，这个方案也许可行，我还没有测试过。&lt;/p&gt;
&lt;p&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;在我写完这篇博文后，发现这个方案存在一些问题，通过iscsi将online redo输出到另外一个主机后，log file sync的响应时间需要40-60ms，这个响应时间肯定是无法接受的。现在两台主机的互连是四块千兆网卡直连，通过Linux的Multipath来管理多路径，为什么响应时间这么久，我们还在进一步查找问题。&lt;/span&gt;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/331617933/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2009/12/asm_iscsi_heartbeat.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617933/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617933/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</content:encoded><wfw:commentRss>http://www.hellodba.net/2009/12/asm_iscsi_heartbeat.html/feed</wfw:commentRss><description>普通PC本地磁盘，没有共享存储，如何实现HA？Dataguard挺好，但是存在数据丢失的可能性，而且很难做到应用透明切换。我们用ASM,Heartbeat和iSCSI可以实现一个廉价的HA方案，如下图：

用iSCSI将本地磁盘输出到对方的机器上，利用ASM的failgroup做mirror，保证数据mirror在两台不同的机器上，就算一台机器完全损坏，数据可以做到百分之百不丢失。用Heartbeat作HA探测，如果发现主机故障，则强行关闭DB和ASM，并在备机启动ASM和DB。如果使用Oracle 11g R2，还可以利用Preferred mirror read的特性，保证主库读自己的本地磁盘，而不是通过iSCSI读备机磁盘，这样可以达到更好的性能。
缺点：Heartbeat作为HA软件，我们并不是十分了解其探测机制，可能出现误判或者无法切换的情况。但是其实IBM hacmp这种HA软件一样有问题，比如Oracle hang住时，现在的hacmp根本无法探测，因为hacmp只是判断Oracle的进程在不在，而不管数据库是否活着。
我想不管什么HA软件，都无法处理所有的异常情况，我们只要有完善的监控和应对措施就可以了。比如我们现在所有的DB都有一个监控，就是定时模拟应用去更新数据库中的数据，如果发现超时或者报错，就认为数据库出现hang的情况，并发出报警。
&amp;#8211;EOF&amp;#8211;
另：之前我有一篇文章介绍用ASM和iSCSI搭建RAC的文章，在实际测试过程中，发现存在一些问题，因为在11g R2之前，voting disk和OCR都必须放在RAW devices上。因为没有共享存储，如果发生某台机器全部宕机，voting disk可能会丢失一部分，造成RAC的cluster机制发生误判。所以在11g R2之前，这个方案是有问题的，在11g R2中，Oracle几乎所有的东西都可以放在ASM中，这个方案也许可行，我还没有测试过。
在我写完这篇博文后，发现这个方案存在一些问题，通过iscsi将online redo输出到另外一个主机后，log file sync的响应时间需要40-60ms，这个响应时间肯定是无法接受的。现在两台主机的互连是四块千兆网卡直连，通过Linux的Multipath来管理多路径，为什么响应时间这么久，我们还在进一步查找问题。&lt;img src=&quot;http://www1.feedsky.com/t1/331617933/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2009/12/asm_iscsi_heartbeat.html&quot; border=&quot;0&quot; height=&quot;0&quot; width=&quot;0&quot; style=&quot;position:absolute&quot; /&gt;&lt;p class=&quot;fswww1&quot;&gt;&lt;a href=&quot;http://www1.feedsky.com/r/l/feedsky/hellodba/331617933/art01.html&quot; target=&quot;_blank&quot;&gt;&lt;img border=&quot;0&quot; ismap=&quot;ismap&quot; src=&quot;http://www1.feedsky.com/r/i/feedsky/hellodba/331617933/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>ORACLE</category><category>HA</category><category>大话技术</category><pubDate>Thu, 10 Dec 2009 11:45:46 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2009/12/asm_iscsi_heartbeat.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1281</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2009/12/asm_iscsi_heartbeat.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/331617933/5126880</fs:itemid></item></channel></rss>