2008-08-25 Mon

17:06 Time-The Beijing Olympics Photo Gallery (376 Bytes) » Free2way@Net

时代杂志的奥运会相片精选,记录了不少精彩的瞬间:

 

06:46 OCM exam guide - Prepair (4858 Bytes) » Chanel [K]

今天开始在OU参加为期四天的Oracle 10g OCM考试的培训,这个培训是第一次在OU举办,并不是对OCM中牵涉到Oracle数据库技术进行培训而是专门针对如何应对OCM考试的培训。

OCM考试全称为Oracle Certified Master(Oracle认证大师),是在OCA(Oracle认证专员Oracle Certified Associate)、OCP(Oracle认证专家Oracle Certified Professional)之后更高一级的Oracle技术认证,也是Oracle技术认证最高的一个级别。

考试是两天的时间,全部为实际操作的考试,第一天是创建数据库和安装Grid Control,第二天是创建RAC以及部署Data Guard,其中穿插着几乎所有Oracle数据库管理需要用到的常用知识。

其实,技术上来说OCM的考试并不很难,考试涉及的内容也是很喜闻乐见的技术架构。但是问题就在于时间,一个数据库管理员用dbca这样的图形化界面在一个小时里面创建完一个数据库这基本上没有难度,但是要求你不能使用图形界面只能用命令行方式呢?你能记得所有create database的语法吗?你能记得所有storage参数的语法吗?你能记得设定ASSM属性那个四个单词的前后顺序吗?

也许有人会说,我不需要记得啊,我有Oracle Online Documentation可以查询哦,是的,没错,OCM考试允许你查询Oracle的联机帮助文档(仅仅限于联机文档而不允许使用internet去做搜索),但是你能在几分钟内定位到你想要找的内容呢?又一共有多少个知识点你需要去查文档呢?而两个小时的考试时间又允许你去查多少次联机文档呢?我个人认为我对联机文档已经颇为熟悉了,但是今天上午的经验让我必须承认,如果我不继续加以练习,我绝对无法在规定时间内创建出完全符合考试要求的数据库。而如果第一天上午考试结束的时候你没有创建出需要的数据库,那么这次OCM考试你就失败了,因为后面考试的内容是要使用到这个数据库的。

最后,只要是考试就会有压力,当时间一点一滴流逝的时候,你能确保自己在最后的半小时里面还能像刚开始考试时候那样冷静吗?本来一次就能输入正确的SQL语句,会不会就要多输错几个单词,多按几次Delete键,多看到几次ORA报错信息才能完成输入呢?

好吧,这一系列文章的目的并不是给大家施加压力,而是准备告诉大家如何应对OCM考试,这几乎已经无关乎技术,而更多的是技巧了。

1. 保持平常心和信心,这很重要,当然也要意识到信心是通过考试前多次的自我实验而逐渐累积出来的。

2. 请一定在坐到考试桌前之后,尽快检查你面前的机器,会是两台RHEL4的Linux服务器,Gnome的图形界面(喜欢用KDE的兄弟们请去熟悉一下Gnome的操作),有鼠标有键盘,检查你的键盘输入是否顺畅,检查你的鼠标移动是否顺畅,检查机器的电源插座是否插牢,检查Oracle 10gR2的软件是否已经安装,检查$ORACLE_HOME等环境参数是否已经设置好,检查联机文档是否可以正常读取。按照常理来说,这些都不应该出问题,但是万一你运气好碰到有问题的机器,一旦考试开始计时,那损失的就只能是你自己了。哦,为什么是两台机器呢?因为一台是用来创建数据库,而另外一台是用来安装Grid Control的OMS。

下面一篇文章开始正式介绍,如何快速使用命令行方式创建一个数据库,再次强调,这无关乎技术,不是告诉你create database的语法该怎么写。


04:15 对话 UNIX: 简单的按键操作 (2 Bytes) » oracle unix&linux技术
02:39 直方图视图user_tab_histograms中的endpoint_value (4639 Bytes) » ORATEA

对于那些上严重倾斜性的列来说,直方图是CBO正确选择执行计划的重要基础。
我们一般查询直方图都是查询user_tab_histograms,all_tab_histograms或者dba_tab_histograms。
以user_tab_histograms来说明下视图各个字段的含义

SQL> desc user_tab_histograms
名称                                      是否为空? 类型
—————————————– ——– ————–

TABLE_NAME                                         VARCHAR2(30)      
COLUMN_NAME                                        VARCHAR2(4000)
ENDPOINT_NUMBER                                    NUMBER
ENDPOINT_VALUE                                     NUMBER
ENDPOINT_ACTUAL_VALUE                              VARCHAR2(1000)

TABLE_NAME  ————— 表名          
COLUMN_NAME ————— 字段名
ENDPOINT_NUMBER ———– 结束点序号
ENDPOINT_VALUE  ———– 结束点值
ENDPOINT_ACTUAL_VALUE—— 结束点真实值(一般为空)

以前使用直方图的时候没有过多的关注ENDPOINT_VALUE字段,一直以后这个字段存储的结束点的实际值。
可今天发现不是这样的。

SQL> create table sunwg (id number,grade varchar2(1));

表已创建。

SQL> insert into sunwg values(1,’a');

已创建 1 行。

SQL> insert into sunwg values(2,’b');

已创建 1 行。

SQL> commit;

提交完成。

SQL> begin
  2  dbms_stats.gather_table_stats(
  3  ownname => ‘SUNWG’,
  4  tabname => ‘SUNWG’,
  5  method_opt => ‘FOR TABLE FOR ALL COLUMNS SIZE AUTO’);
  6  end;
  7  /

PL/SQL 过程已成功完成。
SQL> select column_name,endpoint_number,endpoint_value
  2  from user_tab_histograms
  3  where table_name = ‘SUNWG’
  4  order by 1,2;

COLUMN_NAM ENDPOINT_NUMBER ENDPOINT_VALUE
———- ————— ————–
GRADE                    0     5.0365E+35
GRADE                    1     5.0885E+35
ID                       0              1
ID                       1              2

从这个测试结果能看出来,对于列ID存储的是实际值,而对于列GRADE则不是。
后来查询了user_tab_histograms的底层表才知道ENDPOINT_VALUE存储的原来是实际值的hash值。

create table histgrm$                                     /* histogram table */
( obj#            number not null,                          /* object number */
  col#            number not null,                          /* column number */
  row#            number,                       /* row number (in row cache) */
  bucket          number not null,                          /* bucket number */
  endpoint        number not null,                  /* endpoint hashed value */
  intcol#         number not null,                 /* internal column number */
  epvalue         varchar2(1000),              /* endpoint value information */
  spare1          number,
  spare2          number)
cluster c_obj#_intcol#(obj#, intcol#)
/

endpoint        number not null,                  /* endpoint hashed value */
这样就清楚了,5.0365E+35是’a'的hash值。
oracle这样可能是为了增强通用性吧,否则需要建一系列的endpoint,字符型的endpoint,数据型的endpoint,日期型的endpoint等。
而使用了hash之后,结果就唯一,一串数字而已。
><

02:21 ORA-01039 (6026 Bytes) » ORATEA

今天同事在查看sql的执行计划的时候出现ORA-01039的错误。原因主要是在视图所在的基表上没有select的权限。

oerr ora 1039
01039, 00000, “insufficient privileges on underlying objects of the view”
 *Cause: Attempting to explain plan on other people’s view without
         the necessary privileges on the underlying objects of the view.
 *Action: Get necessary privileges or do not perform the offending operation.
 
这个时候只要把基表的权限付给相应的用户就可以了。

GRANT SELECT ON xxx TO xxx;

下面模拟下出错的过程和解决的办法:

一 sunwg用户下:

sunwg> desc sunwg
 名称                                      是否为空? 类型
 —————————————– ——– ————————

 OWNER                                              VARCHAR2(30)
 OBJECT_NAME                                        VARCHAR2(128)
 SUBOBJECT_NAME                                     VARCHAR2(30)
 OBJECT_ID                                          NUMBER
 DATA_OBJECT_ID                                     NUMBER
 OBJECT_TYPE                                        VARCHAR2(19)
 CREATED                                            DATE
 LAST_DDL_TIME                                      DATE
 TIMESTAMP                                          VARCHAR2(19)
 STATUS                                             VARCHAR2(7)
 TEMPORARY                                          VARCHAR2(1)
 GENERATED                                          VARCHAR2(1)
 SECONDARY                                          VARCHAR2(1)

sunwg> create view sunwg_v as select * from sunwg;

视图已创建。

sunwg> grant select on sunwg_v to test;

授权成功。
二 test用户下:

test> desc sunwg.sunwg
ERROR:
ORA-04043: 对象 sunwg.sunwg 不存在
test> desc sunwg.sunwg_v
 名称                                      是否为空? 类型
 —————————————– ——– ——————-

 OWNER                                              VARCHAR2(30)
 OBJECT_NAME                                        VARCHAR2(128)
 SUBOBJECT_NAME                                     VARCHAR2(30)
 OBJECT_ID                                          NUMBER
 DATA_OBJECT_ID                                     NUMBER
 OBJECT_TYPE                                        VARCHAR2(19)
 CREATED                                            DATE
 LAST_DDL_TIME                                      DATE
 TIMESTAMP                                          VARCHAR2(19)
 STATUS                                             VARCHAR2(7)
 TEMPORARY                                          VARCHAR2(1)
 GENERATED                                          VARCHAR2(1)
 SECONDARY                                          VARCHAR2(1)

test> set autot traceonly exp
test> select * from sunwg.sunwg_v;

执行计划
———————————————————-
ERROR:
ORA-01039: 视图基本对象的权限不足
SP2-0612: 生成 AUTOTRACE EXPLAIN 报告时出错

三 在sunwg下授权给test

sunwg> grant select on sunwg to test;

授权成功。

四 重新在test下查看sql的执行计划

test> select * from sunwg.sunwg_v;

执行计划
———————————————————-
Plan hash value: 856969577

—————————————————————-
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)|
—————————————————————-
|   0 | SELECT STATEMENT  |       | 10000 |   820K|    33   (4)|
|   1 |  TABLE ACCESS FULL| SUNWG | 10000 |   820K|    33   (4)|
—————————————————————-

问题解决了。
><

01:00 对话 UNIX: 简单的按键操作 (354 Bytes) » developerWorks 中国 : 技术文章 , 教程 AIX
用户与计算机交互的方式在不断发生变化。启动后提供纯命令行界面的操作系统已逐渐演化为图形化前端。然而,脱离构成操作系统的构建块有时并非是迈向正确方向的必要步骤。幸运的是,IBM AIX 操作系统一直把握着重点:计算机操作系统的稳定性、功能和稳健性。
00:45 11g新特性——基于函数的统计信息 (12155 Bytes) » ORATEA

11g在统计信息上的进步还是比较大的,增加了一种新的统计信息——基于函数的统计信息。
通过基于函数的统计信息就可以完美的解决了10g中的在列上存在函数时候的结果集估算上的问题。
想知道基于函数的统计信息有多大的用途,那么先让我们来看看10g中的cbo在处理存在函数的列时候有多笨蛋。

10g

SQL> drop table sunwg ;

表已删除。

SQL> create table sunwg as select * from dba_objects where rownum<10001;

表已创建。

SQL> begin
  2          dbms_stats.gather_table_stats (
  3                  ownname         => ‘SUNWG’,
  4                  tabname         => ‘SUNWG’,
  5                  estimate_percent=> 100,
  6                  method_opt      => ‘FOR TABLE FOR ALL COLUMNS SIZE AUTO’,
  7                  cascade         => true
  8  );
  9  end;
 10  /

PL/SQL 过程已成功完成。

SQL> set autot traceonly exp
SQL> select * from sunwg where substr(object_name,1,1) = ‘S’;

执行计划
———————————————————-
Plan hash value: 856969577

—————————————————————-
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)|
—————————————————————-
|   0 | SELECT STATEMENT  |       |   100 |  8400 |    33   (4)|
|*  1 |  TABLE ACCESS FULL| SUNWG |   100 |  8400 |    33   (4)|
—————————————————————-

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

   1 - filter(SUBSTR(”OBJECT_NAME”,1,1)=’S')

CBO估计最后的结果集100,那么看下实际上结果集应该是多少。

SQL> set autot OFF

SQL> select count(*) from sunwg where substr(object_name,1,1) = ‘S’;

        761

100和761比起来,差距还是很大的。
实际上这个时候CBO计算结果集的方式就是 row_num * 1% = 10000 * 1% = 100
上面的1%是在等值查询的时候,如果是不等查询,比如说是substr(object_name,1,1) > ‘S’,则公式变为row_num * 5%。

SQL> set autot traceonly exp
SQL> select * from sunwg where substr(object_name,1,1) > ‘S’;

执行计划
———————————————————-
Plan hash value: 856969577

—————————————————————-
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)|
—————————————————————-
|   0 | SELECT STATEMENT  |       |   500 | 42000 |    33   (4)|
|*  1 |  TABLE ACCESS FULL| SUNWG |   500 | 42000 |    33   (4)|
—————————————————————-

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

   1 - filter(SUBSTR(”OBJECT_NAME”,1,1)>’S')
  
那么实际呢?

SQL> set autot off
SQL> select count(*) from sunwg where substr(object_name,1,1) > ’s’;

         2337
        
由此可以看出,在10g中如果列上存在函数,CBO的估算存在着严重的问题。这些问题进而导致CBO选择不恰当的执行计划。
最终的结果就是,用户抱怨程序执行缓慢。

下面我们看看11g中有什么新的变化。

11g

sunwg>create table sunwg as select * from dba_objects where rownum<10001;

Table created.

sunwg>begin
  2    dbms_stats.gather_table_stats (
  3             ownname         => ‘SUNWG’,
  4             tabname         => ‘SUNWG’,
  5             estimate_percent=> 100,
  6             method_opt      => ‘FOR TABLE FOR ALL COLUMNS FOR COLUMNS (SUBSTR(OBJECT_NAME,1,1))’);
  7   end;
  8  /

PL/SQL procedure successfully completed.

上面对表收集统计信息的时候和在10g的时候有所不同,增加对了函数的统计信息的收集——FOR COLUMNS (SUBSTR(OBJECT_NAME,1,1))。
先来看下收集了基于函数的统计信息后的效果。

sunwg>set autot traceonly exp

sunwg>select * from sunwg where substr(object_name,1,1) = ‘S’;

Execution Plan
———————————————————-
Plan hash value: 856969577

—————————————————————-
| Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)|
—————————————————————-
|   0 | SELECT STATEMENT  |       |   737 | 67804 |    19   (0)|
|*  1 |  TABLE ACCESS FULL| SUNWG |   737 | 67804 |    19   (0)|
—————————————————————-

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

   1 - filter(”SUNWG”.”SYS_STU5NQYW0T0Y__CUOUS30XU1JP”=’S')

看看实际的结果集大小:

sunwg@SWORD>set autot OFF

sunwg@SWORD>select count(*) from sunwg where substr(object_name,1,1) = ‘S’;

  COUNT(*)
———-
       737
      
看来CBO这次估算的结果还是很正确的。     

细心的可能注意到一个问题,在上面的执行计划的筛选中出现了”SUNWG”.”SYS_STU5NQYW0T0Y__CUOUS30XU1JP”=’S'。
那么这个”SUNWG”.”SYS_STU5NQYW0T0Y__CUOUS30XU1JP”是什么对象呢,凭感觉应该是和substr(object_name,1,1)有关系的。

在11g中增加了一个新的视图USER_STAT_EXTENSIONS,用来存储那些扩展的统计信息。

sunwg@SWORD>select TABLE_NAME,EXTENSION_NAME,EXTENSION from user_stat_extensions;

TABLE_NAME                     EXTENSION_NAME                 EXTENSION
—————————— —————————— ——————————–
SUNWG                          SYS_STU5NQYW0T0Y__CUOUS30XU1JP (SUBSTR(”OBJECT_NAME”,1,1))

那么这个扩展的统计信息存储在哪里了,我们找找看吧。

sunwg@SWORD>select table_name,column_name,NUM_DISTINCT,DENSITY from user_tab_cols where table_name = ‘SUNWG’ order by 1;

TABLE_NAME                     COLUMN_NAME                    NUM_DISTINCT    DENSITY
—————————— —————————— ———— ———-
SUNWG                          SYS_STU5NQYW0T0Y__CUOUS30XU1JP           25     .00005
SUNWG                          EDITION_NAME                              1  .00018315
SUNWG                          NAMESPACE                                 7     .00005
SUNWG                          SECONDARY                                 1     .00005
SUNWG                          GENERATED                                 2     .00005
SUNWG                          TEMPORARY                                 2     .00005
SUNWG                          STATUS                                    1     .00005
SUNWG                          TIMESTAMP                               334  .00438216
SUNWG                          LAST_DDL_TIME                           361  .00423152
SUNWG                          CREATED                                 320  .00440554
SUNWG                          OBJECT_TYPE                              20     .00005
SUNWG                          DATA_OBJECT_ID                         1931 .000963212
SUNWG                          OBJECT_ID                             10000      .0001
SUNWG                          SUBOBJECT_NAME                           28 .004310345
SUNWG                          OBJECT_NAME                            8067  .00013912
SUNWG                          OWNER                                     6     .00005

一下子就找到了,这个基于函数的统计信息是和表中的列存储在一起的。
从上面的统计信息可以看出来,SUBSTR(”OBJECT_NAME”,1,1)有25个不同值,并且DENSITY值等于.00005。
CBO正是通过这个统计信息来计算出substr(object_name,1,1) = ‘S’的结果集合是737。
至于具体怎么计算得到的,我这就不写了。这涉及到直方图的一些知识了,有兴趣的可以参考我写的:
cbo心得(选择率,基数,直方图) - http://www.oratea.cn/2008/03/25/39.html
><

  2008-08-24 Sun

19:05 开源数据库 Sharding 技术 (9738 Bytes) » DBA notes

注:此文首发于 《程序员》杂志 2008 年 7 月刊。

从 Shard 到 Sharding

"Shard" 这个词英文的意思是"碎片",而作为数据库相关的技术用语,似乎最早见于大型多人在线角色扮演游戏(MMORPG)中。"Sharding" 姑且称之为"分片"。

Sharding 不是一门新技术,而是一个相对简朴的软件理念。如您所知,MySQL 5 之后才有了数据表分区功能,那么在此之前,很多 MySQL 的潜在用户都对 MySQL 的扩展性有所顾虑,而是否具备分区功能就成了衡量一个数据库可扩展性与否的一个关键指标(当然不是唯一指标)。数据库扩展性是一个永恒的话题,MySQL 的推广者经常会被问到:如在单一数据库上处理应用数据捉襟见肘而需要进行分区化之类的处理,是如何办到的呢? 答案是:Sharding。

Sharding 不是一个某个特定数据库软件附属的功能,而是在具体技术细节之上的抽象处理,是水平扩展(Scale Out,亦或横向扩展、向外扩展)的解决方案,其主要目的是为突破单节点数据库服务器的 I/O 能力限制,解决数据库扩展性问题。

事关数据库扩展性

说起数据库扩展性,这是个非常大的话题。目前的商业数据都有自己的扩展性解决方案,在过去相对来说比较成熟,但是随着互联网的高速发展,不可避免的会带来一些计算模式上的演变,这样很多主流商业系统也难免暴露出一些不足之处。比如 Oracle 的 RAC 是采用共享存储机制,对于 I/O 密集型的应用,瓶颈很容易落在存储上,这样的机制决定后续扩容只能是 Scale Up(向上扩展) 类型,对于硬件成本、开发人员的要求、维护成本都相对比较高。

Sharding 基本上是针对开源数据库的扩展性解决方案,很少有听说商业数据库进行 Sharding 的。目前业界的趋势基本上是拥抱 Scale Out,逐渐从 Scale Up 中解放出来。

Sharding 的应用场景

任何技术都是在合适的场合下能发挥应有的作用。 Sharding 也一样。联机游戏、IM、BSP 都是比较适合 Sharding 的应用场景。其共性是抽象出来的数据对象之间的关联数据很小。比如IM ,每个用户如果抽象成一个数据对象,完全可以独立存储在任何一个地方,数据对象是 Share Nothing 的;再比如 Blog 服务提供商的站点内容,基本为用户生成内容(UGC),完全可以把不同的用户隔离到不同的存储集合,而对用户来说是透明的。

这个 "Share Nothing" 是从数据库集群中借用的概念,举例来说,有些类型的数据粒度之间就不是 "Share Nothing" 的,比如类似交易记录的历史表信息,如果一条记录中既包含卖家信息与买家信息,如果随着时间推移,买、卖家会分别与其它用户继续进行交易,这样不可避免的两个买卖家的信息会分布到不同的 Sharding DB 上,而这时如果针对买卖家查询,就会跨越更多的 Sharding ,开销就会比较大。

Sharding 并不是数据库扩展方案的银弹,也有其不适合的场景,比如处理事务型的应用就会非常复杂。对于跨不同DB的事务,很难保证完整性,得不偿失。所以,采用什么样的 Sharding 形式,不是生搬硬套的。

Sharding与数据库分区(Partition)的区别

有的时候,Sharding 也被近似等同于水平分区(Horizontal Partitioning),网上很多地方也用 水平分区来指代 Sharding,但我个人认为二者之间实际上还是有区别的。的确,Sharding 的思想是从分区的思想而来,但数据库分区基本上是数据对象级别的处理,比如表和索引的分区,每个子数据集上能够有不同的物理存储属性,还是单个数据库范围内的操作,而 Sharding 是能够跨数据库,甚至跨越物理机器的。(见对比表格)

Sharding.png
(转载别忘了此图。注明全文来自 http://www.dbanotes.net)

Sharding 策略

数据 Sharding 的策略与分区表的方式有很多类似的地方,有基于表、ID 范围、数据产生的时间或是SOA 下理念下的基于服务等众多方式可选择。而与传统的表分区方式不同的是,Sharding 策略和业务结合的更为紧密,成功的 Sharding 必须对自己的业务足够熟悉,进行众多可行性分析的基础上进行,"业务逻辑驱动"。

Sharding 实现案例分析:Digg 网站

作为风头正劲的 Web 2.0 网站之一的 Digg.com,虽然用户群庞大,但网站数据库数据并非海量,去年同期主数据大约只有 30GB 的样子,现在应该更大一些,但应该不会出现数量级上增长,数据库软件采用 MySQL 5.x。Digg.com的 IO 压力非常大,而且是读集中的应用(98%的 IO 是读请求)。因为提供的是新闻类服务,这类数据有其自身特点,最近时间段的数据往往是读压力最大的部分。

根据业务特点,Digg.com 根据时间范围对主要的业务数据做 Sharding,把不到 10% 的"热"数据有效隔离开来,同时对这部分数据用以更好的硬件,提供更好的用户体验。而另外 90% 的数据因用户很少访问,所以尽管访问速度稍慢一点,对用户来说,影响也很小。通过 Sharding,Digg 达到了预期效果。

现有的 Sharding 软件简介

现在 Sharding 相关的软件实现其实不少,基于数据库层、DAO 层、不同语言下也都不乏案例。限于篇幅,作一下简要的介绍。

MySQL Proxy + HSCALE

一套比较有潜力的方案。其中 MySQL Proxy (http://forge.mysql.com/wiki/MySQL_Proxy) 是用 Lua 脚本实现的,介于客户端与服务器端之间,扮演 Proxy 的角色,提供查询分析、失败接管、查询过滤、调整等功能。目前的 0.6 版本还做不到读、写分离。HSCALE 则是针对 MySQL Proxy 插件,也是用 Lua 实现的,对 Sharding 过程简化了许多。需要指出的是,MySQL Proxy 与 HSCALE 各自会带来一定的开销,但这个开销与集中式数据处理方式单条查询的开销还是要小的。

Hibernate Shards

这是 Google 技术团队贡献的项目(http://www.hibernate.org/414.html),该项目是在对 Google 财务系统数据 Sharding 过程中诞生的。因为是在框架层实现的,所以有其独特的特性:标准的 Hibernate 编程模型,会用 Hibernate 就能搞定,技术成本较低;相对弹性的 Sharding 策略以及支持虚拟 Shard 等。

Spock Proxy

这也是在实际需求中产生的一个开源项目。Spock(http://www.spock.com/)是一个人员查找的 Web 2.0 网站。通过对自己的单一 DB 进行有效 Sharding化 而产生了Spock Proxy(http://spockproxy.sourceforge.net/ ) 项目,Spock Proxy 算得上 MySQL Proxy 的一个分支,提供基于范围的 Sharding 机制。Spock 是基于 Rails 的,所以Spock Proxy 也是基于 Rails 构建,关注 RoR 的朋友不应错过这个项目。

HiveDB

上面介绍了 RoR 的实现,HiveDB (http://www.hivedb.org/)则是基于Java 的实现,另外,稍有不同的是,这个项目背后有商业公司支持。

PL/Proxy

前面几个都是针对 MySQL 的 Sharding 方案,PL/Proxy 则是针对 PostgreSQL 的,设计思想类似 Teradata 的 Hash 机制,数据存储对客户端是透明的,客户请求发送到 PL/Proxy 后,由这里分布式存储过程调用,统一分发。 PL/Proxy 的设计初衷就是在这一层充当"数据总线"的职责,所以,当数据吞吐量支撑不住的时候,只需要增加更多的 PL/Proxy 服务器即可。大名鼎鼎的 Skype 用的就是 PL/Proxy 的解决方案。

Pyshards

http://code.google.com/p/pyshards/wiki/Pyshards 这是个基于 Python的解决方案。该工具的设计目标还有个 Re-balancing 在里面,这倒是个比较激进的想法。目前只支持 MySQL 数据库。

结束语

Sharding 是一项仍处于高速发展中的"老"技术,随着 Web 2.0 的发展,Sahrding逐渐从比较"虚"的概念变成比较"实"的运用思路,开放源代码软件大潮也给 Sharding 注入新的活力,相信会有越来越多的项目采用 Sharding 技术,也会有更多成熟的 Sharding 方案和数据库附加软件涌现。

你的站点 Sharding 了么?

--EOF--

另,本周末我讲参加这个活动:体验基于OpenSolaris的Web/企业应用,做一个题为《设计可扩展的面向互联网应用的MySQL数据库》的简单分享。欢迎杭州朋友光临指导。

  2008-08-23 Sat

21:15 Linux中如何让进程在后台运行 (5324 Bytes) » NinGoo.net

Author:NinGoo posted on NinGoo.net

在Linux中,如果要让进程在后台运行,一般情况下,我们在命令后面加上&即可,实际上,这样是将命令放入到一个作业队列中了:

$ ./test.sh &
[1] 17208

$ jobs -l
[1]+ 17208 Running                 ./test.sh &

对于已经在前台执行的命令,也可以重新放到后台执行,首先按ctrl+z暂停已经运行的进程,然后使用bg命令将停止的作业放到后台运行:

$ ./test.sh
[1]+  Stopped                 ./test.sh

$ bg %1
[1]+ ./test.sh &

$ jobs -l
[1]+ 22794 Running                 ./test.sh &

但是如上方到后台执行的进程,其父进程还是当前终端shell的进程,而一旦父进程退出,则会发送hangup信号给所有子进程,子进程收到hangup以后也会退出。如果我们要在退出shell的时候继续运行进程,则需要使用nohup忽略hangup信号,或者setsid将将父进程设为init进程(进程号为1)

$ echo $$
21734

$ nohup ./test.sh &
[1] 29016

$ ps -ef | grep test
515      29710 21734  0 11:47 pts/12   00:00:00 /bin/sh ./test.sh
515      29713 21734  0 11:47 pts/12   00:00:00 grep test
$ setsid ./test.sh &
[1] 409

$ ps -ef | grep test
515        410     1  0 11:49 ?        00:00:00 /bin/sh ./test.sh
515        413 21734  0 11:49 pts/12   00:00:00 grep test

上面的试验演示了使用nohup/setsid加上&使进程在后台运行,同时不受当前shell退出的影响。那么对于已经在后台运行的进程,该怎么办呢?可以使用disown命令:

$ ./test.sh &
[1] 2539

$ jobs -l
[1]+  2539 Running                 ./test.sh &

$ disown -h %1

$ ps -ef | grep test
515        410     1  0 11:49 ?        00:00:00 /bin/sh ./test.sh
515       2542 21734  0 11:52 pts/12   00:00:00 grep test

另外还有一种方法,即使将进程在一个subshell中执行,其实这和setsid异曲同工。方法很简单,将命令用括号() 括起来即可:

$ (./test.sh &)

$ ps -ef | grep test
515        410     1  0 11:49 ?        00:00:00 /bin/sh ./test.sh
515      12483 21734  0 11:59 pts/12   00:00:00 grep test

注:本文试验环境为Red Hat Enterprise Linux AS release 4 (Nahant Update 5),shell为/bin/bash,不同的OS和shell可能命令有些不一样。例如AIX的ksh,没有disown,但是可以使用nohup -p PID来获得disown同样的效果。

还有一种更加强大的方式是使用screen,首先创建一个断开模式的虚拟终端,然后用-r选项重新连接这个虚拟终端,在其中执行的任何命令,都能达到nohup的效果,这在有多个命令需要在后台连续执行的时候比较方便:

$ screen -dmS screen_test

$ screen -list
There is a screen on:
        27963.screen_test       (Detached)
1 Socket in /tmp/uscreens/S-jiangfeng.

$ screen -r screen_test

Related Articles

PermLink: http://www.ningoo.net/html/2008/how_to_run_processes_on_background_in_linux.html

Add Comments(0) | Follow NinGoo@Twitter | Google Reader


  2008-08-22 Fri

19:19 奋斗 » 玉面飞龙的BLOG
09:06 需要什么样的监控? » AnySQL.net

  2008-08-21 Thu

07:51 开启异步IO的相关风险 » OracleBlog.cn
00:07 TCP 连接断连问题剖析 » developerWorks 中国 : 技术文章 , 教程 AIX

  2008-08-20 Wed

22:31 Learning ODI - Sybase to Oracle » Chanel [K]
07:01 推荐一个多协议IM工具Pidgin » Ricky's Test Blog
02:12 Korn Shell 脚本入门 » developerWorks 中国 : 技术文章 , 教程 AIX
02:11 带宽与I/O(转) » ORATEA
00:31 mysql压力测试工具:mysqlslap » Taobao DBA Team

2008-08-19 Tue

08:28 再说刘翔退赛 » 存储部落
 123
 123