2008-08-25 Mon
对于那些上严重倾斜性的列来说,直方图是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之后,结果就唯一,一串数字而已。
><
今天同事在查看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)|
—————————————————————-
问题解决了。
><
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
注:此文首发于 《程序员》杂志 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 是能够跨数据库,甚至跨越物理机器的。(见对比表格)

(转载别忘了此图。注明全文来自 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
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
作者:d.c.b.a, 订阅AnySQL, Oracle数据库恢复及服务, Sybase恢复, 磁盘及RAID恢复
一提到系统监控就会联想到Cacti这个优秀的开源软件, 或用Nagios. 不管什么样的监控软件平台, 监控可做的事大约有四个方面.
一定的报警机制. 对于特定的事件, 需要用特定的方式(手机, 邮件, 淘宝旺旺等)通知相关人员, 通知的事件大小由监制的机制来决定, 如果是7x24的, 那一般只有交易量下降多少比例时才会报警, 如果不是7x24的, 那么有任何错误发生时都需要报警.
一定的图表显示. 图表是最好的表现数据趋势的方式, 对于交易量或主机负荷之类的少数重要数据, 用图的方式显示. 缺点是一个屏幕内能提供的信息量比较少, 对于详细诊断问题所在起不了多少帮助.
很多的详细信息. 用网页方式显示某些方面详细的数据, 如将所有的消息滞留的情况记录下来, 用来查找发生的问题. 更多的如应用中关键的API调用次数, 显示一个当前值和历史平均值, 也可以确定某个点是不是有问题. 非常适合于详细问题的快速确定.
一定的自动响应机制. 管理出身的会很关注这一点, 是很好的设想, 但不容易实现, 最简单地说表空问不足这个问题吧, 让程序自动加文件? 还是做一个空间预测, 提前加好空间, 个人偏向于后者.
现在监时做的一些监控就是建立在自已开发的WebChart基础上的, 表格和图形并存的方式. 更适合于白天工作时段的监控, 好好保存一定历史信息, 还可用于事后问题查找.
相关文章 | Related Artiles
我要留言(当前0)
2008-08-21 Thu
Facebook 其实对待技术的态度其实挺开放的。今天阅读了这篇 Scale Out, 工程师 Jason Sobel 介绍了在对付跨地域 MySQL 复制网络延迟的问题。
Cache 一致性问题解决思路
大量的 MySQL + Memcached 服务器,布署简示:
California (主 Write/Read)............. Virginia (Read Only)
主数据中心在 California ,远程中心在 Virginia 。这两个中心网络延迟就有 70ms,MySQL 数据复制延迟有的时候会达到 20ms. 如果要让只读的信息从 Virginia 端发起,Memcached 的 Cache 数据一致性就是个问题。
- 1 用户发起更新操作,更名 "Jason" 到 "Monkey" ;
- 2 主数据库写入 "Monkey",删除主、从两端 Memcached 中的名字值;
- 3 在 Virginia 有人查看该用户 Profile ;
- 4 在 Memcached 中没发现用户名字,从 Virginia Slave 数据库读取,因为网络延迟,结果读到了 "Jason";
- 5 更新 Virginia Memcached 中的该用户名字为 "Jason";
- 6 复制追上了,更新名字为 ""Monkey";
- 7 又有人读取 Profile 了;
- 8 在 Memcached 中找到了键值,返回 "Jason" (实际上造成业务冲突了)
解决办法挺有意思,在 SQL 解析层嵌入了针对 Memcached 的操作。
- 1 用户发起更新操作,更名 "Jason" 到 "Monkey" ;
- 2 主数据库写入 "Monkey",删除主端 Memcached 中的名字值,但Virginia 端 Memcached 不删;(这地方在 SQL 解析上作了一点手脚,把更新的操作"示意"给远程);
- 3 在 Virginia 有人查看该用户 Profile ;
- 4 在 Memcached 中找到键值,返回值 "Jason";
- 5 复制追上更新 Slave 数据库用户名字为 "Monkey",删除 Virginia Memcached 中的键值;
- 6 在 Virginia 有人查看该用户 Profile ;
- 7 Memcache 中没找到键值,所以从 Slave 中读取,然后得到正确的 "Monkey" 。
这里面的一个简单的原则是: 更新后的数据,用户第一次读取要从数据库读,顺便扔一份到 Cache 里,而不是在写入的时候直接更新 Memcached 。避免写事务过大。
而写操作的原则是:一次写入,到处分发。
第二个问题是关于"Page Routing"的 ,也很有参考价值。感兴趣的自己读一下吧。
--EOF--
另推荐一下: 分布式系统中的一致性和可用性,该文是上次在支付宝 QClub 活动的总结之二。
