<?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:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" 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>Sat, 04 Sep 2010 17:59:31 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><sy:updatePeriod>hourly</sy:updatePeriod><sy:updateFrequency>1</sy:updateFrequency><language>en</language><pubDate>Tue, 07 Sep 2010 01:39:50 GMT</pubDate><item><title>Oracle cluster使用场景分析</title><link>http://www.hellodba.net/2010/09/oracle-hash-cluster.html</link><content:encoded>&lt;p&gt;Oracle中普通的表称为堆表（heap table），堆表中的数据是无序存放的，往往在使用一段时间后，数据就变得非常无序。如下图所示，索引中相同的key对应的数据存放在不同的block中，这时，如果要通过索引查询某个key的数据，就需要访问很多不同的block，代价非常高。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/09/hash_cluster.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1714&quot; title=&quot;hash_cluster&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/09/hash_cluster.jpg&quot; alt=&quot;&quot; width=&quot;620&quot; height=&quot;303&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Oracle中有一个统计信息clustering factor，它就是用来反映索引中键值在表中的有序程度，clustering factor的值如果接近表的blocks的数量，表明数据在表中的是有序的，而如果这个值接近表的行数，则表明表中的数据是无序存放的。因为clustring factor对于索引查询的影响很大，所以在CBO计算cost时，这个值非常重要。&lt;/p&gt;
&lt;p&gt;我们可以通过创建一个单表的hash cluster，将相同键值的数据物理存放在一起，达到提高性能的目的。创建cluster有两个最重要的参数：hashkeys和size，前者表示cluster中有多少个不同的键值，后者表示每个键值需要分配的空间。因为hash cluster的空间是预先分配的，这两个值的正确设置对cluster的性能影响非常大。hashkeys设置过大，会造成空间浪费，而如果设置过小，则会产生大量的hash碰撞，极大影响性能。size也是一样，设置过大会浪费空间，而设置过小，数据超过预先分配的空间时，会通过链接方式存放在溢出段中，影响性能。而这两个值一旦设置，就无法更改，除非重建cluster。&lt;/p&gt;
&lt;p&gt;hash cluster简单的说就是通过预先分配空间的方式，将相同key的数据存放在一起，以提高查询性能的一种手段，所以准确的设置hashkeys和size参数是使用hash cluster的关键，使用的前提是key的数量是可以估算的，而且每个key的数据是基本平均的。但是，在实际使用的环境中，数据量的变化往往是不可预知的，这也造成hash cluster的应用场景非常有限。&lt;/p&gt;
&lt;p&gt;Index cluster和hash cluster类似，只不过index cluster是通过索引实现数据定位，而且index cluster的空间是动态分配的，但是同样存在正确设置size参数的问题，设置过大过小都会产生性能问题。&lt;/p&gt;
&lt;p&gt;个人观点：Oracle cluster更适合相对静态数据的存储，对于OLTP应用来说，cluster在大部分情况下都不太适用，因为我们都无法预估到数据量的变化，根本无法合理设置cluster的参数。&lt;/p&gt;
&lt;p&gt;任何技术都要找到合适的应用场景，有利一定有弊，有些技术确实是看上去很美，但是并不实用，而有些方案看上去很土，但是可以解决问题，找到最合适的就好。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;
&lt;p&gt;如果哪位兄弟有oracle cluster解决实际问题方面的案例，也请和我一起交流。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409719424/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/09/oracle-hash-cluster.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/409719424/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/409719424/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/09/oracle-hash-cluster.html/feed</wfw:commentRss><slash:comments>0</slash:comments><description>Oracle中普通的表称为堆表（heap table），堆表中的数据是无序存放的，往往在使用一段时间后，数据就变得非常无序。如下图所示，索引中相同的key对应的数据存放在不同的block中，这时，如果要通过索引查询某个key的数据，就需要访问很多不同的block，代价非常高。

Oracle中有一个统计信息clustering factor，它就是用来反映索引中键值在表中的有序程度，clustering factor的值如果接近表的blocks的数量，表明数据在表中的是有序的，而如果这个值接近表的行数，则表明表中的数据是无序存放的。因为clustring factor对于索引查询的影响很大，所以在CBO计算cost时，这个值非常重要。
我们可以通过创建一个单表的hash cluster，将相同键值的数据物理存放在一起，达到提高性能的目的。创建cluster有两个最重要的参数：hashkeys和size，前者表示cluster中有多少个不同的键值，后者表示每个键值需要分配的空间。因为hash cluster的空间是预先分配的，这两个值的正确设置对cluster的性能影响非常大。hashkeys设置过大，会造成空间浪费，而如果设置过小，则会产生大量的hash碰撞，极大影响性能。size也是一样，设置过大会浪费空间，而设置过小，数据超过预先分配的空间时，会通过链接方式存放在溢出段中，影响性能。而这两个值一旦设置，就无法更改，除非重建cluster。
hash cluster简单的说就是通过预先分配空间的方式，将相同key的数据存放在一起，以提高查询性能的一种手段，所以准确的设置hashkeys和size参数是使用hash cluster的关键，使用的前提是key的数量是可以估算的，而且每个key的数据是基本平均的。但是，在实际使用的环境中，数据量的变化往往是不可预知的，这也造成hash cluster的应用场景非常有限。
Index cluster和hash cluster类似，只不过index cluster是通过索引实现数据定位，而且index cluster的空间是动态分配的，但是同样存在正确设置size参数的问题，设置过大过小都会产生性能问题。
个人观点：Oracle cluster更适合相对静态数据的存储，对于OLTP应用来说，cluster在大部分情况下都不太适用，因为我们都无法预估到数据量的变化，根本无法合理设置cluster的参数。
任何技术都要找到合适的应用场景，有利一定有弊，有些技术确实是看上去很美，但是并不实用，而有些方案看上去很土，但是可以解决问题，找到最合适的就好。
&amp;#8211;EOF&amp;#8211;
如果哪位兄弟有oracle cluster解决实际问题方面的案例，也请和我一起交流。&lt;img src=&quot;http://www1.feedsky.com/t1/409719424/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/09/oracle-hash-cluster.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/409719424/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/409719424/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>大话技术</category><pubDate>Sun, 05 Sep 2010 01:59:31 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/09/oracle-hash-cluster.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1713</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/09/oracle-hash-cluster.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409719424/5126880</fs:itemid></item><item><title>写在3PAR被HP收购之后</title><link>http://www.hellodba.net/2010/09/3par-hp.html</link><content:encoded>&lt;p&gt;3PAR最终被HP收购，想想HP一直没什么可以拿得出手的存储产品，高端的XP系列其实是HDS的USP，而与3PAR理念接近的EVA，始终没有进入高端行列。不知道HP收购3PAR后，是用来替换XP还是EVA系列。&lt;/p&gt;
&lt;p&gt;通过我这几年使用硬件的经验来看，对HP的产品始终不太感冒。产品路线不清晰，小型机性能不佳，存储没有特色，PC服务器故障率高，价格没有优势，服务也很一般，销售换了一茬又一茬。&lt;/p&gt;
&lt;p&gt;对于3PAR这个产品，我还是挺有好感的，设计理念很有特色，在实际测试中性能不俗，印象最深刻的是命令行界面非常好用，对于运维人员来说，这点是非常重要的。当初，曾经写过一篇文章介绍3PAR的产品：&lt;a href=&quot;http://www.hellodba.net/2008/04/3par_storage.html&quot;&gt;我看3PAR&lt;/a&gt;，有兴趣的可以看看。&lt;/p&gt;
&lt;p&gt;随着技术的发展和公司策略的转变，我们对小型机和高端存储的需求已经越来越少了，分布式计算已经成为未来发展的趋势，当然，在传统行业中，这种高端硬件还是很有市场的。&lt;/p&gt;
&lt;p&gt;在国外，这种收购的案例非常多，被收购的小公司都有非常鲜明的特点，大公司通过收购来提升自我的竞争力，小公司则在收购中得到收益，鼓励更多人去创新，形成良性循坏。但是在国内，这种案例就非常少见，大公司占有绝对优势，可以轻松的通过模仿等手段，挤垮这些小公司。归根结底，还是创新不够的原因，所以模仿的成本很低，比如微博，团购网等等，几乎都是照搬国外的模式，又没有太多技术门槛，所以就变成了大家一起上的局面。&lt;/p&gt;
&lt;p&gt;Alibaba最近也收购了一些公司，但是基本都在电子商务这个领域，我觉得这点公司做的挺好，坚守在自己的领域。最近有人骂腾讯，其实腾讯没做错什么，只是什么都想做，树敌太多。我觉得每个企业都应该有自己的道德底线，不能什么赚钱就做什么，价值观也很重要。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;
&lt;p&gt;附：《我看3PAR》，发表于2008年4月&lt;/p&gt;
&lt;p&gt;最近测试了3par的存储，这个厂商在存储领域算是比较新的。以前看myspace的架构时，才第一次听说了这个产品，目前在国内才刚刚开始做。&lt;br /&gt;
这个存储有一些特点：&lt;br /&gt;
1.中端存储高端化：3PAR定为于高端存储，但是它的架构有点类似中端存储的架构，有控制器的概念，最多可以有8个控制器（S400最多有4个控制 器，S800可以有8个），控制器之间由一个网状背板连接起来，每个控制器有两个INTEL的CPU负责控制指令，还有一个3PAR自己控制器的ASIC 完成数据移动。普通的中端存储，一个LUN只能属于一个控制器，用户必须将LUN人工分布到两个控制器上，而3PAR每个LUN实际上是由多个控制器并行 处理的。&lt;br /&gt;
2.非常有特点的盘盒：3PRA插盘的方式非常独特，和其他存储都完全不同，在4U高度的盘盒中，有10个盘包，每个盘包可以纵向插入4块盘，相当于其他 存储一块盘的位置插入了四块，所以3PAR的盘的密度非常高。当然这也有问题，比如在换盘时，每次需要将整个盘包拔出，或者盘包自身的背板损坏，可能造成 数据丢失等等。不过3PAR已经考虑了这些情况，并有解决方案。&lt;br /&gt;
3.虚拟卷管理：第一层：每个盘都被划分为256M的小块(chunklet)，由于每个盘盒都和两个控制器相连，所以这些存储块都有两个访问通道。第二 层：将这些存储块，基于RAID类型和存储块的位置组成逻辑盘(LD)。第三层：将一个或多个LD映射成为了一个虚拟卷(VV)，并最终以LUN的形式输 出给主机(VLUN)。这样可以将IO分散到系统所有的磁盘，光纤连接和控制器上，而不象某些存储，必须要借助主机的LVM才能实现。如果我们使用文件系 统或者ASM的话，将会很方便。另外一个特点就是管理非常方便，只需要告诉系统我要多大的LUN，其他系统会自动完成。&lt;br /&gt;
4.精简配置：也叫做瘦存储(Thin  Provisioning)，就是将”使用的存储”和”分配的存储”分开了。比如用户规划需要2T的空间，但是目前只需要500G空间，这样存储可以实际 只有500G空间，但是告诉主机我有2T的空间。对主机来说，存储的管理将是透明的，当未来存储扩容后，主机不需要再做任何配置工作。&lt;br /&gt;
5.动态优化：当存储扩容时，可以动态的将数据重新分布，更改RAID类型，硬盘类型等等。&lt;br /&gt;
6.性能：从测试的结果看，3PAR表现相当不错，iops和相应时间都很理想。测试结果就不写了，免得有做广告的嫌疑。&lt;br /&gt;
7.界面：个人觉得3PAR的命令行界面很好用，图形界面没见过，不便评论。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409540952/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/09/3par-hp.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/409540952/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/409540952/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/09/3par-hp.html/feed</wfw:commentRss><slash:comments>4</slash:comments><description>3PAR最终被HP收购，想想HP一直没什么可以拿得出手的存储产品，高端的XP系列其实是HDS的USP，而与3PAR理念接近的EVA，始终没有进入高端行列。不知道HP收购3PAR后，是用来替换XP还是EVA系列。
通过我这几年使用硬件的经验来看，对HP的产品始终不太感冒。产品路线不清晰，小型机性能不佳，存储没有特色，PC服务器故障率高，价格没有优势，服务也很一般，销售换了一茬又一茬。
对于3PAR这个产品，我还是挺有好感的，设计理念很有特色，在实际测试中性能不俗，印象最深刻的是命令行界面非常好用，对于运维人员来说，这点是非常重要的。当初，曾经写过一篇文章介绍3PAR的产品：我看3PAR，有兴趣的可以看看。
随着技术的发展和公司策略的转变，我们对小型机和高端存储的需求已经越来越少了，分布式计算已经成为未来发展的趋势，当然，在传统行业中，这种高端硬件还是很有市场的。
在国外，这种收购的案例非常多，被收购的小公司都有非常鲜明的特点，大公司通过收购来提升自我的竞争力，小公司则在收购中得到收益，鼓励更多人去创新，形成良性循坏。但是在国内，这种案例就非常少见，大公司占有绝对优势，可以轻松的通过模仿等手段，挤垮这些小公司。归根结底，还是创新不够的原因，所以模仿的成本很低，比如微博，团购网等等，几乎都是照搬国外的模式，又没有太多技术门槛，所以就变成了大家一起上的局面。
Alibaba最近也收购了一些公司，但是基本都在电子商务这个领域，我觉得这点公司做的挺好，坚守在自己的领域。最近有人骂腾讯，其实腾讯没做错什么，只是什么都想做，树敌太多。我觉得每个企业都应该有自己的道德底线，不能什么赚钱就做什么，价值观也很重要。
&amp;#8211;EOF&amp;#8211;
附：《我看3PAR》，发表于2008年4月
最近测试了3par的存储，这个厂商在存储领域算是比较新的。以前看myspace的架构时，才第一次听说了这个产品，目前在国内才刚刚开始做。
这个存储有一些特点：
1.中端存储高端化：3PAR定为于高端存储，但是它的架构有点类似中端存储的架构，有控制器的概念，最多可以有8个控制器（S400最多有4个控制 器，S800可以有8个），控制器之间由一个网状背板连接起来，每个控制器有两个INTEL的CPU负责控制指令，还有一个3PAR自己控制器的ASIC 完成数据移动。普通的中端存储，一个LUN只能属于一个控制器，用户必须将LUN人工分布到两个控制器上，而3PAR每个LUN实际上是由多个控制器并行 处理的。
2.非常有特点的盘盒：3PRA插盘的方式非常独特，和其他存储都完全不同，在4U高度的盘盒中，有10个盘包，每个盘包可以纵向插入4块盘，相当于其他 存储一块盘的位置插入了四块，所以3PAR的盘的密度非常高。当然这也有问题，比如在换盘时，每次需要将整个盘包拔出，或者盘包自身的背板损坏，可能造成 数据丢失等等。不过3PAR已经考虑了这些情况，并有解决方案。
3.虚拟卷管理：第一层：每个盘都被划分为256M的小块(chunklet)，由于每个盘盒都和两个控制器相连，所以这些存储块都有两个访问通道。第二 层：将这些存储块，基于RAID类型和存储块的位置组成逻辑盘(LD)。第三层：将一个或多个LD映射成为了一个虚拟卷(VV)，并最终以LUN的形式输 出给主机(VLUN)。这样可以将IO分散到系统所有的磁盘，光纤连接和控制器上，而不象某些存储，必须要借助主机的LVM才能实现。如果我们使用文件系 统或者ASM的话，将会很方便。另外一个特点就是管理非常方便，只需要告诉系统我要多大的LUN，其他系统会自动完成。
4.精简配置：也叫做瘦存储(Thin  Provisioning)，就是将”使用的存储”和”分配的存储”分开了。比如用户规划需要2T的空间，但是目前只需要500G空间，这样存储可以实际 只有500G空间，但是告诉主机我有2T的空间。对主机来说，存储的管理将是透明的，当未来存储扩容后，主机不需要再做任何配置工作。
5.动态优化：当存储扩容时，可以动态的将数据重新分布，更改RAID类型，硬盘类型等等。
6.性能：从测试的结果看，3PAR表现相当不错，iops和相应时间都很理想。测试结果就不写了，免得有做广告的嫌疑。
7.界面：个人觉得3PAR的命令行界面很好用，图形界面没见过，不便评论。&lt;img src=&quot;http://www1.feedsky.com/t1/409540952/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/09/3par-hp.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/409540952/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/409540952/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>IT江湖</category><pubDate>Sat, 04 Sep 2010 13:33:02 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/09/3par-hp.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1708</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/09/3par-hp.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409540952/5126880</fs:itemid></item><item><title>浅谈数据库系统中的cache</title><link>http://www.hellodba.net/2010/08/db-storage.html</link><content:encoded>&lt;p&gt;Cache和Buffer是两个不同的概念，简单的说，Cache是加速“读”，而buffer是缓冲“写”，前者解决读的问题，保存从磁盘上读出的数据，后者是解决写的问题，保存即将要写入到磁盘上的数据。在很多情况下，这两个名词并没有严格区分，常常把读写混合类型称为buffer cache，本文后续的论述中，统一称为cache。&lt;/p&gt;
&lt;p&gt;Oracle中的log buffer是解决redo写入的问题，而data buffer cache则解决data block的读写问题。对于Oracle来说，如果IO没有在SGA中命中，都会发生物理IO，Oracle并不关心底层存储的类型，可能是一套存储系统，可能是本地磁盘，可能是RAID 10，也可能是RAID 5，可能是文件系统，也可能是裸设备，或是ASM。总之，Oracle把底层的存储系统称为存储子系统。&lt;/p&gt;
&lt;p&gt;在存储系统中，cache几乎无处不在（在后面的论述中，我们统称为cache），文件系统有cache，存储有cache，RAID控制器上有cache，磁盘上也有cache。为了提高性能，Oracle的一个写操作，很有可能写在存储的cache上就返回了，如果这时存储系统发生问题，Oracle如何来保证数据一致性的问题。&lt;/p&gt;
&lt;p&gt;Oracle数据库最重要的特性是：Write ahead logging，在data block在写入前，必须保证首先写入redo log，在事务commit时，同时必须保证redo log被写入。Oracle为了保证数据的一致性，对于redo log采用了&lt;strong&gt;direct IO&lt;/strong&gt;，Direct IO会跳过了OS上文件系统的cache这一层。但是，OS管不了存储这一层，虽然跳过了文件系统的cache，但是依然可能写在存储的cache上。&lt;/p&gt;
&lt;p&gt;一般的存储都有cache，为了提高性能，写操作在cache上完成就返回给OS了，我们称这种写操作为write back，为了保证掉电时cache中的内容不会丢失，存储都有电池保护，这些电池可以供存储在掉电后工作一定时间，保证cache中的数据被刷入磁盘，不会丢失。不同于UPS，电池能够支撑的时间很短，一般都在30分钟以内，只要保证cache中的数据被写入就可以了。存储可以关闭写cache，这时所有的写操作必须写入到磁盘才返回，我们称这种写操作为write throuogh，当存储发现某些部件不正常时，存储会自动关闭写cache，这时写性能会下降。&lt;/p&gt;
&lt;p&gt;RAID卡上也有cache，一般是256M，同样是通过电池来保护的，不同于存储的是，这个电池并不保证数据可以被写入到磁盘上，而是为cache供电以保护数据不丢失，一般可以支撑几天的时间。还有些RAID卡上有flash cache，掉电后可以将cache中的内容写入到flash cache中，保证数据不丢失。如果你的数据库没有存储，而是放在普通PC机的本地硬盘之上的，一定要确认主机中的RAID卡是否有电池，很多硬件提供商默认是不配置电池的。当然，RAID卡上的cache同样可以选择关闭。&lt;/p&gt;
&lt;p&gt;磁盘上的cache，一般是16M-64M，很多存储厂商都明确表示，存储中磁盘的cache是禁用的，这也是可以理解的，为了保证数据可靠性，而存储本身又提供了非常大的cache，相比较而言，磁盘上的cache就不再那么重要。SCSI指令中有一个FUA(Force Unit Access)的参数，设置这个参数时，写操作必须在磁盘上完成才可以返回，相当于禁用了磁盘的写cache。虽然没有查证到资料，但是我个人认为一旦磁盘被接入到RAID控制器中，写cache就会被禁用，这也是为了数据可靠性的考虑，我相信存储厂商应该会考虑这个问题。&lt;/p&gt;
&lt;p&gt;至此，我们可以看到Oracle的一个物理IO是经历了一系列的cache之后，最终被写入到磁盘上。cache虽然可以提高性能，但是也要考虑掉电保护的问题。关于数据的一致性，是由Oracle数据库，操作系统和存储子系统共同来保证的。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409540953/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/08/db-storage.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/409540953/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/409540953/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/08/db-storage.html/feed</wfw:commentRss><slash:comments>1</slash:comments><description>Cache和Buffer是两个不同的概念，简单的说，Cache是加速“读”，而buffer是缓冲“写”，前者解决读的问题，保存从磁盘上读出的数据，后者是解决写的问题，保存即将要写入到磁盘上的数据。在很多情况下，这两个名词并没有严格区分，常常把读写混合类型称为buffer cache，本文后续的论述中，统一称为cache。
Oracle中的log buffer是解决redo写入的问题，而data buffer cache则解决data block的读写问题。对于Oracle来说，如果IO没有在SGA中命中，都会发生物理IO，Oracle并不关心底层存储的类型，可能是一套存储系统，可能是本地磁盘，可能是RAID 10，也可能是RAID 5，可能是文件系统，也可能是裸设备，或是ASM。总之，Oracle把底层的存储系统称为存储子系统。
在存储系统中，cache几乎无处不在（在后面的论述中，我们统称为cache），文件系统有cache，存储有cache，RAID控制器上有cache，磁盘上也有cache。为了提高性能，Oracle的一个写操作，很有可能写在存储的cache上就返回了，如果这时存储系统发生问题，Oracle如何来保证数据一致性的问题。
Oracle数据库最重要的特性是：Write ahead logging，在data block在写入前，必须保证首先写入redo log，在事务commit时，同时必须保证redo log被写入。Oracle为了保证数据的一致性，对于redo log采用了direct IO，Direct IO会跳过了OS上文件系统的cache这一层。但是，OS管不了存储这一层，虽然跳过了文件系统的cache，但是依然可能写在存储的cache上。
一般的存储都有cache，为了提高性能，写操作在cache上完成就返回给OS了，我们称这种写操作为write back，为了保证掉电时cache中的内容不会丢失，存储都有电池保护，这些电池可以供存储在掉电后工作一定时间，保证cache中的数据被刷入磁盘，不会丢失。不同于UPS，电池能够支撑的时间很短，一般都在30分钟以内，只要保证cache中的数据被写入就可以了。存储可以关闭写cache，这时所有的写操作必须写入到磁盘才返回，我们称这种写操作为write throuogh，当存储发现某些部件不正常时，存储会自动关闭写cache，这时写性能会下降。
RAID卡上也有cache，一般是256M，同样是通过电池来保护的，不同于存储的是，这个电池并不保证数据可以被写入到磁盘上，而是为cache供电以保护数据不丢失，一般可以支撑几天的时间。还有些RAID卡上有flash cache，掉电后可以将cache中的内容写入到flash cache中，保证数据不丢失。如果你的数据库没有存储，而是放在普通PC机的本地硬盘之上的，一定要确认主机中的RAID卡是否有电池，很多硬件提供商默认是不配置电池的。当然，RAID卡上的cache同样可以选择关闭。
磁盘上的cache，一般是16M-64M，很多存储厂商都明确表示，存储中磁盘的cache是禁用的，这也是可以理解的，为了保证数据可靠性，而存储本身又提供了非常大的cache，相比较而言，磁盘上的cache就不再那么重要。SCSI指令中有一个FUA(Force Unit Access)的参数，设置这个参数时，写操作必须在磁盘上完成才可以返回，相当于禁用了磁盘的写cache。虽然没有查证到资料，但是我个人认为一旦磁盘被接入到RAID控制器中，写cache就会被禁用，这也是为了数据可靠性的考虑，我相信存储厂商应该会考虑这个问题。
至此，我们可以看到Oracle的一个物理IO是经历了一系列的cache之后，最终被写入到磁盘上。cache虽然可以提高性能，但是也要考虑掉电保护的问题。关于数据的一致性，是由Oracle数据库，操作系统和存储子系统共同来保证的。
&amp;#8211;EOF&amp;#8211;&lt;img src=&quot;http://www1.feedsky.com/t1/409540953/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/08/db-storage.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/409540953/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/409540953/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>storage</category><category>cache</category><category>ORACLE</category><category>大话技术</category><pubDate>Sat, 28 Aug 2010 15:48:10 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/08/db-storage.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1700</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/08/db-storage.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409540953/5126880</fs:itemid></item><item><title>喝醉也是一种美</title><link>http://www.hellodba.net/2010/08/hejiu.html</link><content:encoded>&lt;p&gt;团队为旺旺送行，本以为我会很淡定，可是三瓶啤酒下肚，春哥一首《痛哭的人》，如同释放了一颗催泪弹，我没法控制自己。&lt;/p&gt;
&lt;p&gt;此时此刻，工作中的事情都已成为过眼云烟，只剩下五年的兄弟情谊，春哥K哥在旁边弹吉他，过去那些场景就在我脑海中回放。&lt;/p&gt;
&lt;p&gt;我承认，我没法坚强和理智，因为我还在乎。今晚喝醉，明早醒来，一样阳光灿烂。&lt;/p&gt;
&lt;p&gt;“相濡以沫，不如相忘于江湖”，这句话真好，祝旺旺一帆风顺！&lt;/p&gt;
&lt;p&gt;下次喝酒别带吉他了，太TM煽情了。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409540954/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/08/hejiu.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/409540954/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/409540954/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/08/hejiu.html/feed</wfw:commentRss><slash:comments>9</slash:comments><description>团队为旺旺送行，本以为我会很淡定，可是三瓶啤酒下肚，春哥一首《痛哭的人》，如同释放了一颗催泪弹，我没法控制自己。
此时此刻，工作中的事情都已成为过眼云烟，只剩下五年的兄弟情谊，春哥K哥在旁边弹吉他，过去那些场景就在我脑海中回放。
我承认，我没法坚强和理智，因为我还在乎。今晚喝醉，明早醒来，一样阳光灿烂。
“相濡以沫，不如相忘于江湖”，这句话真好，祝旺旺一帆风顺！
下次喝酒别带吉他了，太TM煽情了。
&amp;#8211;EOF&amp;#8211;&lt;img src=&quot;http://www1.feedsky.com/t1/409540954/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/08/hejiu.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/409540954/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/409540954/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>一地鸡毛</category><category>无病呻吟</category><pubDate>Thu, 12 Aug 2010 23:16:43 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/08/hejiu.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1691</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/08/hejiu.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409540954/5126880</fs:itemid></item><item><title>DBA的传说</title><link>http://www.hellodba.net/2010/08/alibaba-dba.html</link><content:encoded>&lt;p&gt;2005年&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;tt-flickr tt-flickr-Medium&quot; title=&quot;Alibaba DBA&quot; href=&quot;http://www.flickr.com/photos/hellodba/4881513115/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4094/4881513115_2aa53dc44b.jpg&quot; alt=&quot;Alibaba DBA&quot; width=&quot;500&quot; height=&quot;375&quot; /&gt;&lt;/a&gt; &lt;a class=&quot;tt-flickr tt-flickr-Medium&quot; title=&quot;Alibaba DBA&quot; href=&quot;http://www.flickr.com/photos/hellodba/4882121322/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4073/4882121322_07639b4195.jpg&quot; alt=&quot;Alibaba DBA&quot; width=&quot;500&quot; height=&quot;375&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;2010年&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;tt-flickr tt-flickr-Medium&quot; title=&quot;2010团队合影&quot; href=&quot;http://www.flickr.com/photos/hellodba/4882125450/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4078/4882125450_2fb13833bf.jpg&quot; alt=&quot;2010团队合影&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;2010团队合影&quot; href=&quot;http://www.flickr.com/photos/hellodba/4882125900/&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;tt-flickr tt-flickr-Medium&quot; title=&quot;2010团队合影&quot; href=&quot;http://www.flickr.com/photos/hellodba/4882125900/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4134/4882125900_93511e8097.jpg&quot; alt=&quot;2010团队合影&quot; width=&quot;500&quot; height=&quot;300&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;大师去了支付宝，道夫在阿里云，大辉去丁香园创业，文学转行做了老板，旺旺也即将去支付宝，还剩下我和donny两个老家伙。&lt;/p&gt;
&lt;p&gt;“相濡以沫，不如相忘于江湖”。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409540955/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/08/alibaba-dba.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/409540955/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/409540955/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/08/alibaba-dba.html/feed</wfw:commentRss><slash:comments>8</slash:comments><description>2005年
 
2010年
 

大师去了支付宝，道夫在阿里云，大辉去丁香园创业，文学转行做了老板，旺旺也即将去支付宝，还剩下我和donny两个老家伙。
“相濡以沫，不如相忘于江湖”。
&amp;#8211;EOF&amp;#8211;&lt;img src=&quot;http://www1.feedsky.com/t1/409540955/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/08/alibaba-dba.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/409540955/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/409540955/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>无病呻吟</category><category>IT江湖</category><pubDate>Wed, 11 Aug 2010 19:55:40 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/08/alibaba-dba.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1681</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/08/alibaba-dba.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409540955/5126880</fs:itemid></item><item><title>Oracle In-memory Undo运作原理</title><link>http://www.hellodba.net/2010/08/oracle-in-memory-undo.html</link><content:encoded>&lt;p&gt;Oracle中undo的作用主要有两个：第一是回滚事务，第二是产生一致性读。同时也衍生出了一些新的 功能，比如Flashback query。传统的undo是通过undo segment来管理的，我们看下面的示例：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/undo.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1644&quot; title=&quot;undo&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/undo.jpg&quot; alt=&quot;&quot; width=&quot;655&quot; height=&quot;443&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;事务开始，必须首先在data block中分配ITL，ITL中记录了事务ID(XID)，XID由三部分内容组成：XIDUSN(回滚段号)，XIDSLOT(回滚段槽 号)，XIDSQN(序列号)，在Undo segment header中有一个事务表，记录该回滚段上的事务信息，每个事务都会占据了一个回滚槽，XID对应一个UBA(undo block address)，表示该事务回滚信息的开始位置。 在上面的例子中，事务分别在T1,T2,T3时间执行了三个操作，更新了三个block中的数据，在每个data block中都存在一个ITL，指向undo segment header中的事务表。undo信息分别存放在三个undo block中，undo信息是一个链表结构，而undo segment header中的uba则指向了最后一个undo block，这也是回滚的起始位置。如果事务需要回滚，只需要在undo segment header中的事务表中找到事务回滚的起始位置，然后通过undo链表，就可以依次回滚整个事务。&lt;/p&gt;
&lt;p&gt;细心的DBA一定会发现，在每个data block的ITL中也有一个UBA，实际上这个UBA是指向了该block对应的undo信息的起始位置，这个UBA主要的作用是提供一致性读，因为一 致性读需要通过undo信息来构造一个CR block，通过这个UBA就可以直接定位到block的回滚信息的起始位置，而不再需要通过undo segment header中的事务表。&lt;/p&gt;
&lt;p&gt;在传统的undo管理模式中，Oracle对于undo和data block是一视同仁的，他们都需要首先读入到data buffer中进行修改，并都会产生redo信息，修改的过程大致是：产生undo的redo，更改undo block，产生data的redo，修改data block。总之redo必须要先于数据被记录下来。当数据库发生crash，可以通过redo日志，恢复data和undo block，然后再通过undo信息去回滚未提交的事务，保证数据的一致性，所以说instance recovery的过程是先前滚，再回滚的过程。&lt;/p&gt;
&lt;p&gt;传统的undo管理有弊端，第一是undo信息如果不在data buffer中，必须首先从外部文件中读入；第二是undo的所有变化也必须同时记录redo，在事务提交时被写入到redo log中。Oracle提出了In-Memory UNDO的新特性，将undo信息都存放在内存结构中，缓解传统undo管理中带来的开销。&lt;/p&gt;
&lt;p&gt;IMU在shared pool中分配一片内存空间（IMU pool），每个新的事务都会分配一个IMU buffer，它相当于一片事物私有的undo buffer，用来记录undo的信息。Data block中记录了IMU node的起始位置，通过IMU buffer中的信息就可以完成一致读，从而大大提升了效率。（这里要澄清一点，我在dump data block时，并没有发现指向IMU node的具体信息）。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/08/undo2.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1658&quot; title=&quot;undo2&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/08/undo2.jpg&quot; alt=&quot;&quot; width=&quot;689&quot; height=&quot;576&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;在IMU模式下，undo信息依然会被写入到redo中，理解这点很重要！因为Instance recovery需要undo的信息去回滚未提交的事物，使数据库处于一致状态，如果redo中没有undo变化的信息，那么一旦发生Instance crash，数据库将有可能处于一个不一致的状态。&lt;/p&gt;
&lt;p&gt;事务开始依旧会在data block中的分配ITL，并且它依然会指向undo segment header的事物表，但是undo block中的信息并不需要马上写入，这时undo信息是记录在IMU Buffer中的，这时也不会产生undo block的redo信息。在以下两种情况时，undo buffer中的信息会被写入到undo block中：1.IMU buffer空间不足；2.LGWR将redo信息被写入到redo log中时（比如commit），在v$sysstat中可以看到IMU flush和IMU commit，分别表示以上两种情况，如果你发现这两个值不断增加，代表系统开启了IMU特性。&lt;/p&gt;
&lt;p&gt;现在我们已经了解到，IMU中的undo信息依旧会被写入到redo log中，只不过在shared pool中分配了一个private undo buffer，一方面可以在内存中完成一致读的操作，另一方面，undo信息只在必要情况下批量写入到redo log中，保证数据库crash后可以恢复到一致状态。另外，Oracle总是会尽可能的保留undo buffer中的信息，以便可以在内存中完成一致读的操作，而且undo信息在写入undo block时，Oracle进行了合并处理，减少了undo block的消耗量和对应的redo产生量。&lt;/p&gt;
&lt;p&gt;从Oracle 10g开始，引入了private redo strands的概念，在shared pool中分配了一个private redo buffer的空间，每个事务产生的redo都放在这里（9i是放在PGA里面），每个buffer分配一个redo allocation latch，用来解决9i中redo allocation latch的争用问题。其实IMU和private redo strands这个特性是相关的，IMU相当于private undo buffer，当redo strand或者undo buffer空间不足时，会发生IMU flash事件，将redo信息（包括undo）写入到redo log中。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/08/private_redo.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1659&quot; title=&quot;private_redo&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/08/private_redo.jpg&quot; alt=&quot;&quot; width=&quot;541&quot; height=&quot;362&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;IMU实现复杂，在很多情况下Oracle会自动禁用IMU特性，比如RAC和Stream环境。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;
&lt;p&gt;关于IMU的资料很少，我也是一知半解。我所获取的信息来自于FreePatents上Oracle申请的一篇专利《Method and Mechanism for Implementing In-Memory Transaction Logging Records》，以及《Oracle performance Firefighting》中关于IMU的内容，Tanel Poder的《Performance and Scalability Improvements in Oracle 10g and 11g》，以及我自己的实验和思考。&lt;/p&gt;
&lt;p&gt;内容不一定正确，欢迎大家批评指正。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409540956/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/08/oracle-in-memory-undo.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/409540956/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/409540956/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/08/oracle-in-memory-undo.html/feed</wfw:commentRss><slash:comments>4</slash:comments><description>Oracle中undo的作用主要有两个：第一是回滚事务，第二是产生一致性读。同时也衍生出了一些新的 功能，比如Flashback query。传统的undo是通过undo segment来管理的，我们看下面的示例：

事务开始，必须首先在data block中分配ITL，ITL中记录了事务ID(XID)，XID由三部分内容组成：XIDUSN(回滚段号)，XIDSLOT(回滚段槽 号)，XIDSQN(序列号)，在Undo segment header中有一个事务表，记录该回滚段上的事务信息，每个事务都会占据了一个回滚槽，XID对应一个UBA(undo block address)，表示该事务回滚信息的开始位置。 在上面的例子中，事务分别在T1,T2,T3时间执行了三个操作，更新了三个block中的数据，在每个data block中都存在一个ITL，指向undo segment header中的事务表。undo信息分别存放在三个undo block中，undo信息是一个链表结构，而undo segment header中的uba则指向了最后一个undo block，这也是回滚的起始位置。如果事务需要回滚，只需要在undo segment header中的事务表中找到事务回滚的起始位置，然后通过undo链表，就可以依次回滚整个事务。
细心的DBA一定会发现，在每个data block的ITL中也有一个UBA，实际上这个UBA是指向了该block对应的undo信息的起始位置，这个UBA主要的作用是提供一致性读，因为一 致性读需要通过undo信息来构造一个CR block，通过这个UBA就可以直接定位到block的回滚信息的起始位置，而不再需要通过undo segment header中的事务表。
在传统的undo管理模式中，Oracle对于undo和data block是一视同仁的，他们都需要首先读入到data buffer中进行修改，并都会产生redo信息，修改的过程大致是：产生undo的redo，更改undo block，产生data的redo，修改data block。总之redo必须要先于数据被记录下来。当数据库发生crash，可以通过redo日志，恢复data和undo block，然后再通过undo信息去回滚未提交的事务，保证数据的一致性，所以说instance recovery的过程是先前滚，再回滚的过程。
传统的undo管理有弊端，第一是undo信息如果不在data buffer中，必须首先从外部文件中读入；第二是undo的所有变化也必须同时记录redo，在事务提交时被写入到redo log中。Oracle提出了In-Memory UNDO的新特性，将undo信息都存放在内存结构中，缓解传统undo管理中带来的开销。
IMU在shared pool中分配一片内存空间（IMU pool），每个新的事务都会分配一个IMU buffer，它相当于一片事物私有的undo buffer，用来记录undo的信息。Data block中记录了IMU node的起始位置，通过IMU buffer中的信息就可以完成一致读，从而大大提升了效率。（这里要澄清一点，我在dump data block时，并没有发现指向IMU node的具体信息）。

在IMU模式下，undo信息依然会被写入到redo中，理解这点很重要！因为Instance recovery需要undo的信息去回滚未提交的事物，使数据库处于一致状态，如果redo中没有undo变化的信息，那么一旦发生Instance crash，数据库将有可能处于一个不一致的状态。
事务开始依旧会在data block中的分配ITL，并且它依然会指向undo segment header的事物表，但是undo block中的信息并不需要马上写入，这时undo信息是记录在IMU Buffer中的，这时也不会产生undo block的redo信息。在以下两种情况时，undo buffer中的信息会被写入到undo block中：1.IMU buffer空间不足；2.LGWR将redo信息被写入到redo [...]&lt;img src=&quot;http://www1.feedsky.com/t1/409540956/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/08/oracle-in-memory-undo.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/409540956/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/409540956/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>ORACLE</category><category>IMU</category><category>大话技术</category><pubDate>Mon, 02 Aug 2010 21:03:51 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/08/oracle-in-memory-undo.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1643</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/08/oracle-in-memory-undo.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409540956/5126880</fs:itemid></item><item><title>东极岛</title><link>http://www.hellodba.net/2010/07/dongjidao.html</link><content:encoded>&lt;p&gt;周末随老婆公司自驾游，东极岛，顾名思义，是中国有人居住的最东端的岛屿，从舟山沈家门出海，大约40多公里，坐船大约需要三个小时。&lt;/p&gt;
&lt;p&gt;当天风浪很大，我晕船，吐得一塌糊涂，在岛上住在渔民家里，顿顿都是海鲜，不是鱼就是贝壳。岛上蚊子巨多，我们戏称是来献血的。岛上没什么象样的海滩，找了个能游泳的地方，水还算清澈，就是有些冷。回去的路上，继续吐了一路，下船后只想吃顿KFC，比海鲜好吃多了，我想我还是比较适应在陆地上生活。&lt;/p&gt;
&lt;p&gt;只带了一个30mm的定焦头，也没怎么拍，凑合着看吧。&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;tt-flickr tt-flickr-Medium&quot; title=&quot;东极岛&quot; href=&quot;http://www.flickr.com/photos/hellodba/4837719704/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4104/4837719704_d68b2799d4.jpg&quot; alt=&quot;东极岛&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;东极岛&quot; href=&quot;http://www.flickr.com/photos/hellodba/4837721690/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4103/4837721690_300fe4499f.jpg&quot; alt=&quot;东极岛&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;东极岛&quot; href=&quot;http://www.flickr.com/photos/hellodba/4837111253/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4151/4837111253_21fe3e9ace.jpg&quot; alt=&quot;东极岛&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;东极岛&quot; href=&quot;http://www.flickr.com/photos/hellodba/4837726130/&quot;&gt;&lt;img class=&quot;alignnone&quot; src=&quot;http://farm5.static.flickr.com/4126/4837726130_3c1c32f0bc.jpg&quot; alt=&quot;东极岛&quot; width=&quot;500&quot; height=&quot;333&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409540957/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/07/dongjidao.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/409540957/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/409540957/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/07/dongjidao.html/feed</wfw:commentRss><slash:comments>4</slash:comments><description>周末随老婆公司自驾游，东极岛，顾名思义，是中国有人居住的最东端的岛屿，从舟山沈家门出海，大约40多公里，坐船大约需要三个小时。
当天风浪很大，我晕船，吐得一塌糊涂，在岛上住在渔民家里，顿顿都是海鲜，不是鱼就是贝壳。岛上蚊子巨多，我们戏称是来献血的。岛上没什么象样的海滩，找了个能游泳的地方，水还算清澈，就是有些冷。回去的路上，继续吐了一路，下船后只想吃顿KFC，比海鲜好吃多了，我想我还是比较适应在陆地上生活。
只带了一个30mm的定焦头，也没怎么拍，凑合着看吧。
   
&amp;#8211;EOF&amp;#8211;&lt;img src=&quot;http://www1.feedsky.com/t1/409540957/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/07/dongjidao.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/409540957/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/409540957/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>一地鸡毛</category><category>边走边拍</category><pubDate>Wed, 28 Jul 2010 21:27:19 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/07/dongjidao.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1652</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/07/dongjidao.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409540957/5126880</fs:itemid></item><item><title>可扩展的分布式数据库架构</title><link>http://www.hellodba.net/2010/07/database_scalability.html</link><content:encoded>&lt;p&gt;&lt;strong&gt;本文发表在《程序员》杂志2010年第6期&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;引 言&lt;/strong&gt;&lt;br /&gt;
数据库的可用性和扩展性一直是数据库厂商和用户最关注的问题。过去我们采用高端的设备，比如使用小型机和大型存储来保证数据库的可用 性。而扩展性主要采用向上扩展(Scale  up)的方式，通过增加CPU，内存，磁盘等方式提高处理能力。这种集中式数据库的架构，使得数据库成为了整个系统的瓶颈，已经越来越不适应海量数据对计 算能力的巨大需求。近些年来，分布式系统成为了一种趋势，我们希望用廉价的设备堆叠出具备高可用性和高扩展性的计算集群，从而摆脱对大型设备的依赖。数据 库作为系统架构中的重要组成部分，如何做到即提供高可用性，又具备向外扩展(Scale out)的能力，数据库厂商和用户都做了很多的探索。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Oracle  RAC&lt;/strong&gt;&lt;br /&gt;
几乎每个数据库产品都有集群解决方案，Oracle  RAC是业界最流行的产品。其架构的最大特点是共享存储架构（Shared-disk），整个RAC集群是建立在一个共享的存储设备之上的，节点之间采用 高速网络互连。Oracle  RAC提供了非常好的高可用特性，比如负载均衡和应用透明切换(TAF)，其最大优势在于对应用完全透明，应用无需修改便可以切换到RAC集群。但 是，RAC的扩展能力有限，首先因为整个集群都依赖于底层的共享存储，所以共享存储的IO能力和可用性决定了整个集群的可以提供的能力，其依然无法摆脱对 大型存储设备的依赖。Oracle显然也意识到了这个问题，在Oracle的MAA(Maximum Availability  Architecture)架构中，采用ASM来整合多个存储设备的能力，使得RAC底层的共享存储也具备线性扩展的能力，整个集群不再依赖于大型存储的 处理能力和可用性。&lt;/p&gt;
&lt;p&gt;RAC的另外一个问题是，随着节点数的不断增加，节点间通信的成本也会随之增加，当到达某个限度时，增加节点可能不会 再带来性能上的提高，甚至可能造成性能下降。这个问题的主要原因是Oracle  RAC对应用透明，应用可以连接集群中的任意节点进行处理，当不同节点上的应用争用资源时，RAC节点间的通信开销会严重影响集群的处理能力。所以使用 Oracle RAC有两个建议：1.节点间通信使用高速互联网络；2.尽可能将不同的应用分布在不同的节点上。基于这个原因，Oracle  RAC通常在DSS环境中可以做到很好的扩展性，因为DSS环境很容易将不同的任务分布在不同的计算节点上，而对于OLTP应用，Oracle  RAC更多情况下是用来提高可用性，而不是为了提高扩展性。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MySQL Cluster&lt;/strong&gt;&lt;br /&gt;
MySQL  cluster和Oracle  RAC完全不同，它采用Shared-nothing架构。整个集群由管理节点(ndb_mgmd)，处理节点(mysqld)和存储节点(ndbd)组 成，不存在一个共享的存储设备。MySQL  cluster主要利用了NDB存储引擎来实现，NDB存储引擎是一个内存式存储引擎，要求数据必须全部加载到内存之中。数据被自动分布在集群中的不同存 储节点上，每个存储节点只保存完整数据的一个分片(fragment)。同时，用户可以设置同一份数据保存在多个不同的存储节点上，以保证单点故障不会造 成数据丢失。&lt;/p&gt;
&lt;p&gt;MySQL  cluster的优点在于其是一个分布式的数据库集群，处理节点和存储节点都可以线性增加，整个集群没有单点故障，可用性和扩展性都可以做到很高，更适合 OLTP应用。但是它的问题在于：1.NDB存储引擎必须要求数据全部加载到内存之中，限制比较大，但是目前NDB新版本对此做了改进，允许只在内存中加 载索引数据，数据可以保存在磁盘上。2.目前的MySQL  cluster的性能还不理想，因为数据是按照主键hash分布到不同的存储节点上，如果应用不是通过主键去获取数据的话，必须在所有的存储节点上扫描， 返回结果到处理节点上去处理。而且，写操作需要同时写多份数据到不同的存储节点上，对节点间的网络要求很高。&lt;/p&gt;
&lt;p&gt;虽然MySQL  cluster目前性能还不理想，但是share nothing的架构一定是未来的趋势，Oracle接手MySQL之后，也在大力发展MySQL  cluster，我对MySQL cluster的前景抱有很大的期待。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;分布式数据库架构&lt;br /&gt;
&lt;/strong&gt;目前，除了数据库厂商的 集群产品以外，解决数据库扩展能力的方法主要有两个：数据分片和读写分离。数据分片(Sharding)的原理就是将数据做水平切分，类似于hash分区 的原理，通过应用架构解决访问路由和数据合并的问题。Sharding架构的优势在于，集群扩展能力很强，几乎可以做到线性扩展，而且整个集群的可用性也 很高，部分节点故障，不会影响其他节点提供服务。Sharding原理简单，容易实现，是一种非常好的解决数据库扩展性的方案。但是Sharding对应 用场景的要求很高，因为一旦使用数据分片架构，如果需要跨不同的节点做join，或者统计类型的操作，将会变得非常困难，应该尽量避免。所以说 Sharding架构会损失部分关系型数据库的特性，比如join，从而使数据库退化为Key-Value  store类型的存储。所以，并不是所有的应用都适合做Sharding，它可能会造成应用架构复杂或者限制系统的功能，这也是它的缺陷所在。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/df92qgsw_188dn93m8fx_b.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1637&quot; title=&quot;df92qgsw_188dn93m8fx_b&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/df92qgsw_188dn93m8fx_b.jpg&quot; alt=&quot;&quot; width=&quot;321&quot; height=&quot;444&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Sharding架构图&lt;/p&gt;
&lt;p&gt;读写分离架构利用了数据库的复制技术，将读和 写分布在不同的处理节点上，从而达到提高可用性和扩展性的目的。最通常的做法是利用MySQL Replication技术，Master  DB承担写操作，将数据变化复制到多台Slave DB上，并承担读的操作。这种架构适合read-intensive类型的应用，通过增加Slave  DB的数量，读的性能可以线性增长。为了避免Master DB的单点故障，集群一般都会采用两台Master  DB做双机热备，所以整个集群的读和写的可用性都非常高。除了MySQL，Oracle从11g开始提供Active  Standby的功能，也具备了实现读写分离架构的基础。读写分离架构的缺陷在于，不管是Master还是Slave，每个节点都必须保存完整的数据，如 果在数据量很大的情况下，集群的扩展能力还是受限于单个节点的存储能力，而且对于Write-intensive类型的应用，读写分离架构并不适合。&lt;/p&gt;
&lt;div&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/df92qgsw_178hptqj5cx_b.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1639&quot; title=&quot;df92qgsw_178hptqj5cx_b&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/df92qgsw_178hptqj5cx_b.jpg&quot; alt=&quot;&quot; width=&quot;298&quot; height=&quot;231&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;读写分离架构图&lt;/p&gt;
&lt;p&gt;读写分离架构应用非常广泛，很多网站都采用cache+DB的读写分离架构，通 过cache层来承载大量的读访问。Memcached是一种广泛使用的Key-Value  cache，它不具备持久化存储的功能，所以它通常和数据库一起组成读写分离的架构，由数据库承载数据持久化存储的功能，而Memcached则用来承载 大量的并发访问。通常的做法是：应用的读请求会首先访问Memcached，如果命中则返回，如果没有命中，则会去数据库中读取，并将数据加载到 Memcached中。关于新增，修改和删除操作，一般采用lazy  load的策略，即新增时只写入数据库，并不会马上更新Memcached，而是等到再次读取时才会加载到Memcached中，修改和删除操作也是更新 数据库，然后将Memcached中的数据标记为失效，等待下次读取时再加载。Memcached支持数据分区，利用hash算法将数据分布到不同的服务 器，组成一个分布式的cache集群。&lt;/p&gt;
&lt;div&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/df92qgsw_184vm2fzngq_b.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1640&quot; title=&quot;df92qgsw_184vm2fzngq_b&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/df92qgsw_184vm2fzngq_b.jpg&quot; alt=&quot;&quot; width=&quot;315&quot; height=&quot;270&quot; /&gt;&lt;/a&gt;&lt;/div&gt;
&lt;p&gt;MySQL+Memcached读写分离架构&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;数据库与CAP理论&lt;/strong&gt;&lt;br /&gt;
根据 CAP理论，一致性(C)，可用性(A)，分区容错性(P)，三者不可兼得，必须有所取舍。而传统数据库保证了强一致性(ACID模型)和高可用性，所以 要想实现一个分布式数据库集群非常困难，这也解释了为什么数据库的扩展能力十分有限。而近年来不断发展壮大的NoSQL运动，就是通过牺牲强一致性，采用 BASE模型，用最终一致性的思想来设计分布式系统，从而使得系统可以达到很高的可用性和扩展性。&lt;/p&gt;
&lt;p&gt;但是，对于CAP理论也有一些不同的声 音，数据库大师Michael Stonebraker就撰文《Errors in Database Systems, Eventual  Consistency, and the CAP  Theorem》，表示为了P而牺牲C是不可取的。事实上，数据库系统最大的优势就对一致性的保证，如果我们放弃了一致性，也许NoSQL比数据库更有优 势。那么，有没有可能实现一套分布式数据库集群，即保证可用性和一致性，又可以提供很好的扩展能力呢？&lt;/p&gt;
&lt;p&gt;目前，已经有很多分布式数据库的产 品，但是绝大部分是面向DSS类型的应用，因为相比较OLTP应用，DSS应用更容易做到分布式扩展，比如基于PostgreSQL发展的 Greenplum，就很好的解决了可用性和扩展性的问题，并且提供了很强大的并行计算能力。对于OLTP应用，业务特点决定其要求：高可用性，一致性， 响应时间短，支持事务和join等等。Michael  Stonebraker提到了一种新的数据库产品VoltDB，它的定义是Next-Generation SQL Database for  Fast-Scaling OLTP Applications。虽然产品还没有问世，但是从技术资料上来看，它有几个特点：&lt;br /&gt;
1.采用Share  nothing架构，将物理服务器划分为以CPU core为单位的Virtual  node，采用Sharding技术，将数据自动分布到不同的Virtual node，最大限度的利用机器的计算资源；&lt;br /&gt;
2.采用内存数据访问技 术，类似于内存数据库(In-memory database)，区别于传统的数据库(Disk-based  database)，消除了传统数据库内存管理的开销，而且响应速度非常快；&lt;br /&gt;
3.每个Virtual  node上的操作是自治的，利用队列技术将并发访问变为串行访问，消除了传统数据库串行控制的开销(比如Latch和Lock)；&lt;br /&gt;
4.数据同步写 多个副本，不存在单点故障，而且消除了传统数据库需要记录redo log的开销。&lt;/p&gt;
&lt;p&gt;VoltDB不仅支持传统数据库的ACID模型和 SQL接口，而且提供类似NoSQL产品的高可用性和很强的扩展能力，可谓鱼肉熊掌兼得。CAP理论并不是神话，相信未来类似的数据库产品会不断涌现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;数 据库和NoSQL&lt;/strong&gt;&lt;br /&gt;
当越来越多的NoSQL产品涌现出来，它们具备很多关系型数据库所不具备的特性，在可用性和扩展性方面都可以做到很好。 那么，未来传统的关系型数据库还有优势吗？NoSQL会取代数据库吗？我个人认为关系型数据库至少在相当长的一段时间内，依然是主流，而且还有很大的发展 空间。&lt;/p&gt;
&lt;p&gt;第一，NoSQL的应用场景非常局限，某个类型的NoSQL仅仅针对特定类型的应用场景而设计。而关系型数据库则要通用的多，使用 NoSQL必须搞清楚自己的应用场景是否适合，所以说NoSQL对于很多人来说是“汝之蜜糖，彼之砒霜”。&lt;br /&gt;
第二，利用关系型数据库配合应用架构， 比如Sharding和读写分离技术，同样可以搭建出具备高可用和扩展性的分布式数据库集群。&lt;br /&gt;
第三，关系型数据库厂商依然很强大，全世界有大量的 用户，需求必然会推动新的产品问世。&lt;br /&gt;
第四，硬件的发展日新月异，比如闪存的技术的不断成熟，未来闪存可以作为磁盘与内存之间的cache，或者完 全替代磁盘。而内存价格越来越低，容量越来越大，In-memory  cache或database的应用越来越广泛，可以给应用带来数量级的性能提升。数据库面临的IO问题将被极大改善，数据库也将随着这些新技术而焕发第 二春。&lt;/p&gt;
&lt;p&gt;我并不担心关系型数据库的未来，但我们也不能忽视NoSQL的巨大力量。未来，各种产品和技术一定是百花齐放，关系型数据库依然有 很强的生命力，各种NoSQL产品也会层出不穷，所以完全不用担心谁将会替代谁，我们要做的就是找到最佳的解决方案。有人将NoSQL解释成为Not  only SQL，我想也是这个原因吧。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;结论&lt;/strong&gt;&lt;br /&gt;
前面探讨了关于数据库可用性和扩展性方面的问题，我们看到每种产品和 架构都是有缺陷的，其实架构就是有所取舍的过程，目标是用最小的代价去解决问题。所以找到适合自己的产品和架构，这才是最重要的。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409540958/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/07/database_scalability.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/409540958/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/409540958/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/07/database_scalability.html/feed</wfw:commentRss><slash:comments>6</slash:comments><description>本文发表在《程序员》杂志2010年第6期
引 言
数据库的可用性和扩展性一直是数据库厂商和用户最关注的问题。过去我们采用高端的设备，比如使用小型机和大型存储来保证数据库的可用 性。而扩展性主要采用向上扩展(Scale  up)的方式，通过增加CPU，内存，磁盘等方式提高处理能力。这种集中式数据库的架构，使得数据库成为了整个系统的瓶颈，已经越来越不适应海量数据对计 算能力的巨大需求。近些年来，分布式系统成为了一种趋势，我们希望用廉价的设备堆叠出具备高可用性和高扩展性的计算集群，从而摆脱对大型设备的依赖。数据 库作为系统架构中的重要组成部分，如何做到即提供高可用性，又具备向外扩展(Scale out)的能力，数据库厂商和用户都做了很多的探索。
Oracle  RAC
几乎每个数据库产品都有集群解决方案，Oracle  RAC是业界最流行的产品。其架构的最大特点是共享存储架构（Shared-disk），整个RAC集群是建立在一个共享的存储设备之上的，节点之间采用 高速网络互连。Oracle  RAC提供了非常好的高可用特性，比如负载均衡和应用透明切换(TAF)，其最大优势在于对应用完全透明，应用无需修改便可以切换到RAC集群。但 是，RAC的扩展能力有限，首先因为整个集群都依赖于底层的共享存储，所以共享存储的IO能力和可用性决定了整个集群的可以提供的能力，其依然无法摆脱对 大型存储设备的依赖。Oracle显然也意识到了这个问题，在Oracle的MAA(Maximum Availability  Architecture)架构中，采用ASM来整合多个存储设备的能力，使得RAC底层的共享存储也具备线性扩展的能力，整个集群不再依赖于大型存储的 处理能力和可用性。
RAC的另外一个问题是，随着节点数的不断增加，节点间通信的成本也会随之增加，当到达某个限度时，增加节点可能不会 再带来性能上的提高，甚至可能造成性能下降。这个问题的主要原因是Oracle  RAC对应用透明，应用可以连接集群中的任意节点进行处理，当不同节点上的应用争用资源时，RAC节点间的通信开销会严重影响集群的处理能力。所以使用 Oracle RAC有两个建议：1.节点间通信使用高速互联网络；2.尽可能将不同的应用分布在不同的节点上。基于这个原因，Oracle  RAC通常在DSS环境中可以做到很好的扩展性，因为DSS环境很容易将不同的任务分布在不同的计算节点上，而对于OLTP应用，Oracle  RAC更多情况下是用来提高可用性，而不是为了提高扩展性。
MySQL Cluster
MySQL  cluster和Oracle  RAC完全不同，它采用Shared-nothing架构。整个集群由管理节点(ndb_mgmd)，处理节点(mysqld)和存储节点(ndbd)组 成，不存在一个共享的存储设备。MySQL  cluster主要利用了NDB存储引擎来实现，NDB存储引擎是一个内存式存储引擎，要求数据必须全部加载到内存之中。数据被自动分布在集群中的不同存 储节点上，每个存储节点只保存完整数据的一个分片(fragment)。同时，用户可以设置同一份数据保存在多个不同的存储节点上，以保证单点故障不会造 成数据丢失。
MySQL  cluster的优点在于其是一个分布式的数据库集群，处理节点和存储节点都可以线性增加，整个集群没有单点故障，可用性和扩展性都可以做到很高，更适合 OLTP应用。但是它的问题在于：1.NDB存储引擎必须要求数据全部加载到内存之中，限制比较大，但是目前NDB新版本对此做了改进，允许只在内存中加 载索引数据，数据可以保存在磁盘上。2.目前的MySQL  cluster的性能还不理想，因为数据是按照主键hash分布到不同的存储节点上，如果应用不是通过主键去获取数据的话，必须在所有的存储节点上扫描， 返回结果到处理节点上去处理。而且，写操作需要同时写多份数据到不同的存储节点上，对节点间的网络要求很高。
虽然MySQL  cluster目前性能还不理想，但是share nothing的架构一定是未来的趋势，Oracle接手MySQL之后，也在大力发展MySQL  cluster，我对MySQL cluster的前景抱有很大的期待。
分布式数据库架构
目前，除了数据库厂商的 集群产品以外，解决数据库扩展能力的方法主要有两个：数据分片和读写分离。数据分片(Sharding)的原理就是将数据做水平切分，类似于hash分区 的原理，通过应用架构解决访问路由和数据合并的问题。Sharding架构的优势在于，集群扩展能力很强，几乎可以做到线性扩展，而且整个集群的可用性也 [...]&lt;img src=&quot;http://www1.feedsky.com/t1/409540958/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/07/database_scalability.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/409540958/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/409540958/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>大话技术</category><pubDate>Thu, 15 Jul 2010 20:05:09 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/07/database_scalability.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1633</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/07/database_scalability.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409540958/5126880</fs:itemid></item><item><title>Library cache内部机制详解</title><link>http://www.hellodba.net/2010/07/oracle-library-cache.html</link><content:encoded>&lt;p&gt;Library cache是Shared pool的一部分，它几乎是Oracle内存结构中最复杂的一部分，主要存放shared curosr（SQL）和PLSQL对象（function，procedure，trigger）的信息，以及这些对象所依赖的table，index，view等对象的信息。&lt;/p&gt;
&lt;p&gt;Library cache需要解决三个问题：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.快速定位的问题&lt;/strong&gt;：Library cache中对象众多，Oracle如何管理这些对象，以便服务进程可以迅速找到他们需要的信息。比如某个服务进程需要迅速定位某个SQL是否存在于Library cache中。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.关系依赖的问题&lt;/strong&gt;：Library cache中的对象存在复杂的依赖关系，当某个objec失效时，可以迅速将依赖其的对象也置为失效状态。比如某个表发生了结构变化，依赖其的SQL语句需要重新解析。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.并发控制的问题&lt;/strong&gt;：Library cache中必须有一个并发控制的机构，比如锁机制，来管理大量共享对象的并发访问和修改的问题，比如某个SQL在重新编译的同时，其所依赖的对象不能被修改。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Library cache结构：&lt;br /&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Oracle利用hash table结构来解决library cache中快速定位的问题，hash table就是很多hash bucket组成的数组：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/library_cache.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1600&quot; title=&quot;library_cache&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/library_cache.jpg&quot; alt=&quot;&quot; width=&quot;653&quot; height=&quot;693&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;原理与buffer cache中定位block的方式相同，将对象信息（比如SQL）hash定位到某个hash bucket中，然后顺序扫描bucket中的 List，实现快速定位对象的目的。&lt;/p&gt;
&lt;p&gt;Library cache handle是对象的一个指针，其中的namespace属性表示其指向的对象的类型：比如CRSR(Cursor)，TABL(Table)，INDX(Index) ，PROD(Procedure)，TRIG(Trigger)等等。&lt;/p&gt;
&lt;p&gt;LCO(Library cache object)是handel指向的对象，包含了以下几个部分的内容：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;1.dependency table：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;指向本对象所依赖的对象，比如：select * from emp这个cursor的对象，依赖emp这个表，这里指向了emp这个表的handle。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;2.child table：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;指向本对象的子对象，比如某个游标的子游标。子游标是指SQL文本相同，但是SQL的实际含义不同的情况，比如执行的用户不同，执行计划不同，执行的环境不同等等，我们一般称之为SQL的不同版本。一个SQL至少包含一个父游标和一个子游标。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;3.authorization table：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;对象的授权信息。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;4.type&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Library cache object的type，包括：shared cursor,index,table,cluster,view,synonym,sequence,procedure,function,package,table body,package body,trigger等等。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;5.data blocks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;data block是一个指针，指向了data heap，即存放真实数据的地方，主要包括：diana tree, p-code, source code, shared cursor context area等等，如下图：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/library_cache2.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1605&quot; title=&quot;library_cache2&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/library_cache2.jpg&quot; alt=&quot;&quot; width=&quot;652&quot; height=&quot;450&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Library cache对象依赖关系：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;对象依赖关系是利用LCO中的dependency table来完成的，我们设想以下的情况，用来说明对象间的依赖关系：&lt;/p&gt;
&lt;p&gt;两个共享游标：&lt;/p&gt;
&lt;p&gt;SQL1: select * from emp;&lt;/p&gt;
&lt;p&gt;SQL2: select * from emp和select a.name from emp a,dept b where a.dept_id=b.id  and b.name=:1;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/library_cache3.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1615&quot; title=&quot;library_cache3&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/library_cache3.jpg&quot; alt=&quot;&quot; width=&quot;345&quot; height=&quot;583&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;SQL1产生了两个子游标，也就是SQL文本相同的两个不同版本，他们同时依赖emp表。SQL2只有一个版本，因为每个游标最少有一个子游标，所以它只有一个子游标，并且同时依赖dept表和emp表。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Library cache中的并发控制&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;Oracle利用Library cache lock和Library cache pin来实现并发控制，Library cache lock是在handle上获取的，而Library cache pin则是在data heap上获取。访问对象时，首先必须获取handle上的lock，然后将访问的数据pin在内存中。lock的作用是控制进程间的并发访问，而pin的作用是保证数据一致性，防止数据在访问时被交换出去。&lt;/p&gt;
&lt;p&gt;Library cache lock有三种模式：null，share，exclusive，Library cache pin有两种模式：share，exclusive。下面详细解释在修改和访问对象时，lock和pin的作用：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;修改对象&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;编译SQL或PLSQL对象，获取该对象（cursor，procedure）handle上exclusive类型的lock，并且持有data  heap上exclusive类型的pin，防止其他人读取和修改。同时，在该对象所依赖的对象（table）上，必须持有一个share类型的lock和pin，防止在修改的过程中，被其他进程所修改。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;访问对象&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;访问SQL或PLSQL对象，获取该对象（cursor，procedure）handle上NULL类型的lock，并且持有data  heap上share类型的pin，同时，在其依赖的对象（table）上持有share类型的lock和pin。如果一个procedure依赖另外一个function，那么在被依赖的function上，也需要持有share类型的lock和pin。&lt;/p&gt;
&lt;p&gt;NULL类型的lock比较特殊，它只存在于cursor和procedure等只读对象上，它并不起到任何并发控制的作用，它更象是一个trigger，当对象失效时，通知所有访问这个cursor的进程。比如：select * from emp这个SQL，依赖emp表，当emp表发生变化时，cursor上的NULL lock被打破，所有有访问这个cursor的进程都会知道该对象已经失效。&lt;/p&gt;
&lt;p&gt;当持有对象的library cache pin时，会在row cache中对相应的对象加锁，就是row cache  lock，阻止可能导致数据字典信息混乱的DDL发生。&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/library_cache4.jpg&quot;&gt;&lt;img class=&quot;alignnone size-full wp-image-1623&quot; title=&quot;library_cache4&quot; src=&quot;http://www.hellodba.net/wp-content/uploads/2010/07/library_cache4.jpg&quot; alt=&quot;&quot; width=&quot;589&quot; height=&quot;470&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;lock和pin的实现类似于enqueue，在每个handle上都有lock和pin的holder list和waiter list，用来保存持有该资源和等待该资源的队列。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;阻塞分析&lt;/strong&gt;：&lt;/p&gt;
&lt;p&gt;现实情况中，我们有一个数据库中存在被应用大量频繁访问的procedure，当依赖的表发生变更时，导致该procedure失效，这时会出现大量的library cache lock和library cache pin的等待，堵塞应用访问，造成了重大故障。出现这个问题的原因是：当procedure失效后，所有访问该对象的进程都尝试去编译，大量进程尝试获取exclusive类型的lock和pin，出现了大量的等待。后续的Oracle版本作出了改进，当出现这种情况时，只允许第一个进程尝试去编译该对象，编译通过后，所有的进程就可以并发访问，避免了大量进程同时尝试编译的情况出现。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Library cache中的Latch：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Library cache中相关的latch包括：shared pool latch，library cahce latch，library cache lock latch，library cache pin latch。&lt;/p&gt;
&lt;p&gt;Share pool latch的主要作用是分配或释放空间时使用，从Oracle9i开始，sharedpool被分成了很多个subpool，由多个shared pool latch保护，Oracle开始支持更大的shared pool。&lt;/p&gt;
&lt;p&gt;Library cache latch的主要作用是在hash bucket中定位handle时使用，library cache lock latch和library cache pin latch分别是获取lock和pin时，需要取得的latch。&lt;/p&gt;
&lt;p&gt;shared pool大小不合理，大量的硬解析以及SQL版本过多都可能导致shared pool latch和library cache latch的争用。&lt;/p&gt;
&lt;p&gt;从Oracle10g开始，Oracle正在逐步用mutex取代library cache中的latch，cursor：pin S和cursor：pin X相当于share和exclusive类型的library cache pin，cursor：pin S wait on X则表示share方式正在等待exclusive锁定。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;
&lt;div id=&quot;_mcePaste&quot; style=&quot;position: absolute; left: -10000px; top: 718px; width: 1px; height: 1px; overflow: hidden;&quot;&gt;shared cursor (SQL cursor or PL/SQL anonymous block), index,&lt;br /&gt;
table, cluster, view, synonym, sequence, procedure, function, package, table body, package body, and trigger&lt;/div&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409540959/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/07/oracle-library-cache.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/409540959/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/409540959/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/07/oracle-library-cache.html/feed</wfw:commentRss><slash:comments>33</slash:comments><description>Library cache是Shared pool的一部分，它几乎是Oracle内存结构中最复杂的一部分，主要存放shared curosr（SQL）和PLSQL对象（function，procedure，trigger）的信息，以及这些对象所依赖的table，index，view等对象的信息。
Library cache需要解决三个问题：
1.快速定位的问题：Library cache中对象众多，Oracle如何管理这些对象，以便服务进程可以迅速找到他们需要的信息。比如某个服务进程需要迅速定位某个SQL是否存在于Library cache中。
2.关系依赖的问题：Library cache中的对象存在复杂的依赖关系，当某个objec失效时，可以迅速将依赖其的对象也置为失效状态。比如某个表发生了结构变化，依赖其的SQL语句需要重新解析。
3.并发控制的问题：Library cache中必须有一个并发控制的机构，比如锁机制，来管理大量共享对象的并发访问和修改的问题，比如某个SQL在重新编译的同时，其所依赖的对象不能被修改。
Library cache结构：

Oracle利用hash table结构来解决library cache中快速定位的问题，hash table就是很多hash bucket组成的数组：

原理与buffer cache中定位block的方式相同，将对象信息（比如SQL）hash定位到某个hash bucket中，然后顺序扫描bucket中的 List，实现快速定位对象的目的。
Library cache handle是对象的一个指针，其中的namespace属性表示其指向的对象的类型：比如CRSR(Cursor)，TABL(Table)，INDX(Index) ，PROD(Procedure)，TRIG(Trigger)等等。
LCO(Library cache object)是handel指向的对象，包含了以下几个部分的内容：
1.dependency table：
指向本对象所依赖的对象，比如：select * from emp这个cursor的对象，依赖emp这个表，这里指向了emp这个表的handle。
2.child table：
指向本对象的子对象，比如某个游标的子游标。子游标是指SQL文本相同，但是SQL的实际含义不同的情况，比如执行的用户不同，执行计划不同，执行的环境不同等等，我们一般称之为SQL的不同版本。一个SQL至少包含一个父游标和一个子游标。
3.authorization table：
对象的授权信息。
4.type
Library cache object的type，包括：shared cursor,index,table,cluster,view,synonym,sequence,procedure,function,package,table body,package body,trigger等等。
5.data blocks
data block是一个指针，指向了data heap，即存放真实数据的地方，主要包括：diana tree, p-code, source code, shared cursor context area等等，如下图：

Library cache对象依赖关系：
对象依赖关系是利用LCO中的dependency table来完成的，我们设想以下的情况，用来说明对象间的依赖关系：
两个共享游标：
SQL1: select * from emp;
SQL2: select * from emp和select a.name [...]&lt;img src=&quot;http://www1.feedsky.com/t1/409540959/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/07/oracle-library-cache.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/409540959/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/409540959/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>pin</category><category>ORACLE</category><category>mutex</category><category>大话技术</category><category>lock</category><category>latch</category><pubDate>Sun, 04 Jul 2010 16:32:57 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/07/oracle-library-cache.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1598</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/07/oracle-library-cache.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409540959/5126880</fs:itemid></item><item><title>Oracle Mutex实现机制</title><link>http://www.hellodba.net/2010/06/oracle-mutex.html</link><content:encoded>&lt;p&gt;我们都知道Latch是Oracle用来在内存中做串行控制的机构，从10g R2开始，Oracle引入了一个新的技术-Mutex。Mutex并不是Oracle的发明，而是系统提供的一个底层调用，Oracle只是利用它实现串行控制的功能，并替换部分Latch。&lt;/p&gt;
&lt;p&gt;Mutex中有两个变量：分别是Holider identifer和Reference count，Holider identifer记录持有mutex的SID，而Reference count是一个计数，记录了当前正在以share方式访问mutex的数量，每当session以share方式持有mutex时，计数会加1，而释放时会减1。如果Reference count大于零，则表示该内存结构正在被Oracle pin住。&lt;/p&gt;
&lt;p&gt;我们看一段伪代码，演示mutex的申请过程：&lt;/p&gt;
&lt;pre&gt;Function Mutex_get(mutex_name)
{
  if &lt;strong&gt;mutex.holder:=SID&lt;/strong&gt;
    case mode:
    'exclusive':
      if mutex.ref_count=0
        return TRUE
      else
        mutex.holder.clear;
        reture FALSE
      end if
    'share':
      mutex.ref_count++
      mutex.holder.clear
      return TRUE
    end case
  else
    reture FALSE
  end if
}
&lt;/pre&gt;
&lt;p&gt;Mutex是如何实现串行控制的，实际上它是利用了操作系统的一个原子操作CAS(compare-and-swap)实现的。我们看到函数的开始处：&lt;strong&gt;mutex.holder:=SID&lt;/strong&gt;，将SID赋值给mutex的Holider Identifer，这里就是一个原子的CAS操作，首先比较mutex.holder是否为空，如果不为空则赋值session的SID。CAS操作由OS来保证其原子性，在同一时刻这个操所是串行的。如果这个赋值操作失败，整个申请过程失败。赋值成功后，如果是share方式，则mutex.ref_count加1，并清空mutex.holder，如果是exclusive方式，需要判断mutex.ref_count是否为零（是否被pin住），如果大于0，则失败，并清空mutex.holder，如果等于0，则成功，这时不清空mutex.holder，保持当前session对mutex的exclusive占用，直到释放为止。&lt;/p&gt;
&lt;p&gt;Mutex相比latch带来了以下的好处：&lt;/p&gt;
&lt;p&gt;1.更少的资源消耗，mutex与latch不同，它不是独立存在的，而是在每个内存结构中，并随着内存结构创建和释放，mutex同时也被创建和释放。mutex暂用的空间比latch小很多，创建和释放消耗更少的资源。&lt;/p&gt;
&lt;p&gt;2.有效降低竞争，因为mutex是每个内存结构中的一部分，这样意味着mutex的数量可以有很多，而不同于latch，一个latch需要管理很多个内存结构，当你访问同一latch管理的不同内存结构时，也会发生竞争，而mutex则不会。另外，因为latch的数量有限，很多时候latch本身的竞争会很厉害，之前，我们只能增加latch数量或者减少latch持有的时间，而现在，mutex是一个更好的选择。&lt;/p&gt;
&lt;p&gt;3.更快的pin，当block被访问时，它必须被pin在buffer cache中，当一个cursor执行时，它也必须被pin在library cache中，如果大量并发频繁执行同一个cursor，library cache pin会耗费大量的CPU资源。而mutex使用reference count来解决并发访问的问题，只要它大于零，就表示它已经被pin在了内存中，不能被交换出去。而且mutex.ref_count++这个操所是非常快的，只占用非常少的资源。&lt;/p&gt;
&lt;p&gt;Mutex申请的过程和latch类似，同样需要spin和sleep，不同的是Oracle硬编码了mutex spin的次数为255次（Latch spin的次数默认为2000，由隐含参数_spin_count控制）。latch sleep会随着等待次数的逐步增加，每次sleep的时间也会逐步增加。而mutex sleep则比较特别，它有三个选项，分别是yield CPU，sleep或者block other process，允许开发人员来决定采用哪种选项。&lt;/p&gt;
&lt;p&gt;由于在某些RISC的操作系统中（HP-UNIX），由于系统不支持CAS操作，Oracle通过创建一个latch pool来模拟了CAS操作，被称为KGX latch，如果你发现系统中存在这种latch竞争，说明操作系统不支持CAS操作，可以通过_kks_use_mutex_pin关闭mutex。&lt;/p&gt;
&lt;p&gt;mutex主要使用在library cache中，用来取代原来的library cache pin和library cache lock，关于library cache中锁的实现机制，我会在另外一篇文章中说明。&lt;/p&gt;
&lt;p&gt;&amp;#8211;EOF&amp;#8211;&lt;/p&gt;
&lt;p&gt;注：有关CAS，可以参考&lt;a href=&quot;http://en.wikipedia.org/wiki/Compare-and-swap&quot;&gt;wiki&lt;/a&gt;上的说明。&lt;/p&gt;&lt;img src=&quot;http://www1.feedsky.com/t1/409540960/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/06/oracle-mutex.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/409540960/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/409540960/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/06/oracle-mutex.html/feed</wfw:commentRss><slash:comments>8</slash:comments><description>我们都知道Latch是Oracle用来在内存中做串行控制的机构，从10g R2开始，Oracle引入了一个新的技术-Mutex。Mutex并不是Oracle的发明，而是系统提供的一个底层调用，Oracle只是利用它实现串行控制的功能，并替换部分Latch。
Mutex中有两个变量：分别是Holider identifer和Reference count，Holider identifer记录持有mutex的SID，而Reference count是一个计数，记录了当前正在以share方式访问mutex的数量，每当session以share方式持有mutex时，计数会加1，而释放时会减1。如果Reference count大于零，则表示该内存结构正在被Oracle pin住。
我们看一段伪代码，演示mutex的申请过程：
Function Mutex_get(mutex_name)
{
  if mutex.holder:=SID
    case mode:
    'exclusive':
      if mutex.ref_count=0
        return TRUE
      else
        mutex.holder.clear;
     [...]&lt;img src=&quot;http://www1.feedsky.com/t1/409540960/hellodba/feedsky/s.gif?r=http://www.hellodba.net/2010/06/oracle-mutex.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/409540960/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/409540960/art01.gif&quot; onerror=&quot;this.style.display='none'&quot; /&gt;&lt;/a&gt;&lt;/p&gt;</description><category>ORACLE</category><category>mutex</category><category>大话技术</category><pubDate>Thu, 17 Jun 2010 18:48:13 +0800</pubDate><author>jacky</author><comments>http://www.hellodba.net/2010/06/oracle-mutex.html#comments</comments><guid isPermaLink="false">http://www.hellodba.net/?p=1587</guid><dc:creator>jacky</dc:creator><fs:srclink>http://www.hellodba.net/2010/06/oracle-mutex.html</fs:srclink><fs:srcfeed>http://www.hellodba.net/?feed=rss2</fs:srcfeed><fs:itemid>feedsky/hellodba/~7018878/409540960/5126880</fs:itemid></item></channel></rss>