xzh2000的博客 本人提供杭州地区Oracle现场技术支持服务,包括性能调整、DataGuard、RAC等。
23 07, 2008
如何计算long字段的长度
作者 xzh2000 16:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

有一个应用,在访问clob时抛出异常如下:

FATAL ERROR IN TWO-TASK SERVER: error = 12152
*** 2008-07-17 18:28:43.912
ksedmp: internal or fatal error
ORA-12571: TNS:packet writer failure

RDBMS:9206,查metalink,证实为一个未公开的bug,为了挠过该bug,将clob类型的字段改成long类型,结果访问还是有问题,当长度超过一定的长度时,proc程序就只能读取前4000个字符,因为应用已经发布,修改代码已经来不急。查看了一下long字段的内容,发现文字内容很少的,大部分都是html的格式代码,只需要找出长度超过4000的记录,去掉该部分html代码应用就可以恢复正常;但怎么在long字段中找到超过4000字符记录呢?

 查看全文

10 07, 2008
Stream在11gR1的新特征
作者 xzh2000 17:29 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

相对于10gR2而言,11gR1中stream的新功能更是令人期待,比如:同步捕获(synchronous capture)功能,已经脱离日志挖掘的范畴;stream性能顾问(stream performance advisor)可以识别stream拓扑中的瓶颈、分离与合并stream的目标站点(对于复杂的stream环境可以提高其可用性及可维护性),跟踪LCRs的状态等、支持透明数据加密等、比较与同步共享的数据库对象(当复制环境中名称相关的表数据不一致时,可以用dbms_comparison包来同步)。。。

 查看全文

17 04, 2008
Parallel Query Wait Events
作者 xzh2000 09:55 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

SCOPE & APPLICATION
-------------------

This is intended as a reference for anyone involved in database tuning.

At the moment we consider the following PX wait events as idle:
- "PX Idle Wait"
- "PX Deq: Execution Msg"
- "PX Deq: Table Q Normal"
- "PX Deq Credit: send blkd"
- "PX Deq: Execute Reply"
- "PX Deq Credit: need buffer"
- "PX Deq: Signal ACK"
- "PX Deque wait"

 查看全文
16 04, 2008
Recovery is repairing media corrupt block
作者 xzh2000 20:03 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在dataguard环境中,经常发现standby库的pxxx进程的trace文件中有这样的信息,查了metalink,官方的解释:并不是bug或者错误,而是因为在primary database执行了不可恢复的操作导致的,解决的办法特简单,在primary database上执行以下操作:

 查看全文

26 03, 2008
ASM INSTANCE & Shared Pool (ORA-4031)
作者 xzh2000 14:17 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

The setting for the SHARED_POOL_SIZE parameter determines the amount of memory required to manage the instance. The setting for this parameter is also used to determine the amount of space that is allocated for extent storage. The default value for this parameter is suitable for most ASM environments.

 查看全文

25 03, 2008
数字数据存储格式[摘]
作者 xzh2000 20:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Oracle 以变长格式存储数字数据。所有数字数据均以科学计数法存储[scientific notation],使用 1 字节存储指数[exponent],最多 20 字节存储尾数[mantissa]。最终存储的数字数据受限于 38 位精度限制。且 Oracle 不会存储数字首端及末端的 0。举例来说,数字 412 在存储时的格式可以理解为 4.12 x 102,Oracle 使用 1 字节存储指数(2),使用 2 字节存储尾数的三位有效数字(4,1,2)。存储负数时,符号也需要占用存储空间。

 查看全文

07 11, 2007
你喜欢用number做数据类型吗?
作者 xzh2000 17:14 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

经常见到有人在系统设计时用GUID或MD5产生的32位字符串做主键,即使一些按日期产生的业务编码如2001010100001这样的字符串,都用varchar2来存储,总觉得不是很好,如果数据量不大的话,也无可厚非,但如果运用于存储海量的数据,那将会造成存储成本的巨增,请看下面的测试:

 查看全文

06 09, 2007
SQL优化:理解SQL的意图
作者 xzh2000 16:12 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

如果你的系统中,通过statspack report或awr report,发现这样的SQL执行比较频繁,而且test表的记录数比较多,test表中附合status = '1'的记录数也非常多,占test表记录数90%的比例吧,从statspack report或awr report可以发现该SQL的逻辑读会相当大,假定该表没有任何索引,那DBA该如何着手进行SQL的优化呢?
SELECT seller_id
FROM (SELECT * FROM (SELECT seller_id, max(gmt_create) FROM test WHERE status = 1 GROUP BY seller_id)
ORDER BY gmt_create DESC)
WHERE rownum <= 10;

 查看全文

05 09, 2007
11g新特性:Automatic SQL Tuning Advisor
作者 xzh2000 15:46 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在11g中,优化器有两种模式:普通模式与调化模式。优化器在普通模式下,当SQL被执行时,查询优化器将生成SQL的执行计划,如果SQL的可选路径很多,优化器必须是限制时间内,选择一个合适的执行计划;当优化器在调优模式下,优化器需要执行额外的分析去判断优化器在普通模式下产生的执行计划是否有可能被改进,此时优化器输出的不是一个执行计划,而是一系列的动作,根据调优的原理、产生一个更优化的执行计划,优化器需发花费一定的时间去调优单个的sql,自动调优的优化器每次查询都是硬解析。

 查看全文

04 09, 2007
11g新特性:SQL Performance Analyzer(SPA)
作者 xzh2000 17:31 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

系统变更会影响SQL的执行计划,比如数据库升级,优化参数调整,表结构变更,索引维护(创建,删除,重建),统计信息收集等,Oracle为了预防系统变更所引起的不良后果,特推出SPA,SPA做为RAT(Real Application Test)的一部分,可以消除一些不知预知的错误,Oracle提供dbms_sqlpa包来实现系统变更前后的性能分析,SPA主要应用在以上方面:

 查看全文

03 09, 2007
11g新特性:database replay workload capture的限制
作者 xzh2000 13:07 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在11g中,Real Application Testing(RAT)是一个独立的收费选项,所以当我们需要订购此项服务时,我们该了解该服务有那些限制,否则付了钱,发现有许多地方存在或多或少的冲突,有些冲突的消除可能要花费更大的成本,所以在上项目前,可行性技术研究是必不可少的,如果想使用RAT,需要关注现有的数据库系统是否涉及到如下技术:

 查看全文

31 08, 2007
11g新特性:SQL Management Base(SMB)
作者 xzh2000 15:36 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在Oracle 11g,SMB是SPM的控制端,SMB是数据字典的一部分,SMB存储在sysaux表空间,SMB存储SQL语句日志,Plan Histories,以及SQL Profiles等,SMB允许每周清除一次未使用的SQL Plan & Log,SMB已经配置了自动存储空间管理。

 查看全文

30 08, 2007
11g新特性:SQL Plan Management(SPM)
作者 xzh2000 13:34 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在11g,oracle提供dbms_spm包来管理SQL Plan,SPM是一个预防机制,它记录并评估sql的执行计划,将已知的高效的sql执行计划建立为SQL Plan Baselines,SQL Plan Baseline的功能是保持SQL的性能而不必关注系统的改变。

 查看全文

29 08, 2007
11g新特性:Pending Statistics
作者 xzh2000 16:30 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

从11g开始,表与索引的统计信息收集完毕后,可以选择收集的统信息立即发布,也可以选择使新收集的统计信息处于pending状态,待确定处于pending状态的统计信息是安全的,再使处于pending状态的统计信息发布,这样就会避免一些因为收集统计信息立即发布而导致SQL执行计划走错的灾难。

 查看全文

28 08, 2007
11g新特性:Extended Statistics Collect
作者 xzh2000 12:14 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在11g中,dbms_stats package提供了组合列的统计信息的收集,如果在where条件中使用了组合列进行查询,则优化器将会得到更准确的统计信息,进而输出执行计划时,可以输出更接近与真实数据的统计结果,11g的Extended Statistics包含了组合列与表达式统计信息的收集,表过式统计信息收集主要是针对函数索引字段,下面就组合列统计信息的收集做一下测试:

 查看全文

27 08, 2007
11g新特性:Auto Optimizer Statistics Collection
作者 xzh2000 15:41 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在oracle 10g中,优化统计信息的收集是通过scheduler job来自动完成的,dba可以通过dbms_scheduler package的enable procedure与disable procedure来启动与关闭,在oracle 11g中,oracle提供了全新的package dbms_auto_task_admin来完成统计信息的收集工作,测试脚本如下所示:

 查看全文

24 08, 2007
11g新特性:常驻连接池DRCP之三
作者 xzh2000 17:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

五 如何在DB中配置DRCP?
在11g中,系统默认包含了一个连接池:SYS_DEFAULT_CONNECTION_POOL,这个池默认被创建,但默认该池是不启动的,如果要启动默认的连接池,必须显式地执行启动DRCP的命令,oracle提供dbms_connection_pool package来执行这个工作,如果连接池被显式地启动,必须显式地被停掉,当实例宕掉时,如果DRCP是活动的,则实例启动时,DRCP也将自动实动。
启动DRCP需要以下步骤:
A 用sysdba权限连接到sqlplus
B 执行exec dbms_connection_pool.start_pool();
C 查看DRCP的状态

 查看全文

23 08, 2007
11g新特性:常驻连接池DRCP之二
作者 xzh2000 15:53 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

三Dedicated Servers,Shared Servers与DRCP的内存需求
一般情况下,由于每个会话需要消耗400k的内存,每个进程需要消耗4m的内存,现在我们以DRCP的pool size是100,shared server的shared server进程是100为例,假如有5000个客户端连接到这些环境,则这些主机的内存分配如下:
A Dedicated Server
Memory used = 5000 X (400 KB + 4 MB) = 22 GB
B Shared Server
Memory used = 5000 X 400 KB + 100 X 4 MB = 2.5 GB
Out of the 2.5 GB, 2 GB is allocated from the SGA.
C Database Resident Connection Pooling
Memory used = 100 X (400 KB + 4 MB) + (5000 X 35KB)= 615 MB

 查看全文

22 08, 2007
11g新特性:常驻连接池DRCP之一
作者 xzh2000 15:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在oracle中,进程的频繁创建是一个比较消耗资源的开消,在11g之前,oracle提供专用器进程与共享服务器进程供用户选择适合自己的进程机制,在11g中,oracle又推出DRCP(database resident connection pool),类似于sqlrelay那种轻量级中间件的进程机制为客户服务,DRCP适用于web application(比如php/apache),可以提供成千上万的连接,使用DRCP可以共享主机资源。

 查看全文

21 08, 2007
11g新特性:database replay
作者 xzh2000 16:56 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在11g中,很多功能oracle都引导用户通过OEM来操作,但喜欢用API的dba,照样可以写脚本来完成自己的工作,下面给大家介绍一下database replay的配置方法,database replay可以捕捉整个数据库的负载,并且传递到需要进行测试数据库上,然后重演负载以测试系统调优后的效果,当然也可以为升级硬件进行压力测试。

 查看全文

20 08, 2007
11g新特性:全表扫描的变化
作者 xzh2000 14:20 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在oracle 11g以前的版本中,如果对大表进行全表扫描,通过v$session_wait可以看到wait event是:db file scattered read;在11g中,如果对大表进行全表扫描,通过v$session_wait可以看到wait event是:direct path read;也就是说,在11g中,大表全表扫描是将数据块直接读入会话的pga区域。

 查看全文

17 08, 2007
11g新特性:实时sql监控增强
作者 xzh2000 12:27 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在11g以前的版本,SQL的运行情况可以通过监控v$session_longops来了解,当某个操作执行时间超过6秒,就会被v$session_longops感知,通常可以监控到比如全表扫描,全索引扫描,哈希联接,并行查询等;在11g中,当sql并行运行时,马上会被real-time monitor到,当sql单进程运行时,如果运行时间超过5秒,它也会被监控到。

 查看全文

16 08, 2007
11g新特性:awr报表增强
作者 xzh2000 11:34 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

11g在awr report方面,还是增加了一些吸引眼球的地方,比如增加了对OS等主机配置的报告,对于dba来讲,在接手一个新环境时,或做现场服务时,该报表将会简少一些额外的工作,比如报表中已经可以显示主机名,操作系统,CPU个数,物理内存等,最让人关注的还是增加了主机负载的一些情况,具体变化请看下文:

 查看全文

15 08, 2007
11g新特性:增强的add column
作者 xzh2000 11:01 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在11g以前的版本中,如果表上存在未提交的事务,则对表进行DDL操作将失败,在11g中,这个限制已经被取消啦,执行ADD COLUMN操作时,并不会受未提交事务的影响,另外,ADD COLUMN还有一个增强,就是在一个非常大的表上执行ADD COLUMN xxx DATATYPE DEFAULT yyy NOT NULL时,它不会再去将默认值更新到表中已经存在的记录,这样改进的好处是非常大的,DBA对表结构的变更将更加容易,而且不会产生大量的library cache lock/pin等,更不会阻塞事务,它是怎么做到的呢?

 查看全文

14 08, 2007
11g stream新特性列表
作者 xzh2000 15:38 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

从最初学习9iR2的stream,以及10gR1,10gR2的stream,到现在的11gR1,可以说oracle在stream上面压了很大的成钱,stream也越来越得到用户的接受,在11gR1中,stream比之前的版本也有较大的改进,比如同步捕获,合并的捕获与应用进程等,以下就简单地列下新增的功能点,感兴趣的可以自己看文档。。。

 查看全文

10 08, 2007
11g新特性:DDL锁超时
作者 xzh2000 16:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在11g中,oracle提供了一个新的可动态调整的参数ddl_lock_timeout,该参数允许存在未提交的事务的表上,执行DDL操作,如果事务在ddl_lock_timeout允许的时间内提交,则DDL操作将会成功,否则就会报ORA-00054错误,如果对该表执行ADD COLUMN操作,则会直接提交表上发生的未提交的事务,所以用11g时,有些东西还是要注意的,当然也不排除这是11g的一个bug哦。。。

 查看全文

09 08, 2007
如何减少db file sequential read等待事件
作者 xzh2000 09:14 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

从理论上讲,db file sequential read是没有办法避免的,即是高端存储,对于同样次数的db file sequential read,主要是响应时间上有较大的下降,所以解决db file sequential read等待,需要从以下两个方面来想办法:

 查看全文

08 08, 2007
11g新特性:stream同步捕获
作者 xzh2000 15:28 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在测试9iR2,10gR1,10gR2的stream时,非常希望能够有种同步capture的机制,该同步capture机制与log-based real-time capture机制是不同的,它应该是一种内部触发的机制,比如当有活动事务时,DB引擎判断该表配置有stream的同步capture标志,就可以直接把dml打包成LCRs并压入队列...

 查看全文

26 12, 2006
ORA-00600 [17113]异常解淅
作者 xzh2000 10:59 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

收到al*.log报ORA-00600: [17113], [0x000000000]错误,查看*.trc文件后,发现有个开发人员通过pl/sql developer查询生产库引起的,开发人员没有查询生产库的权限,后来才知开发人员通过开发库中指向生产库的db link执行了一个查询,结果就触发了一个ORA-600错误。。。

 查看全文

07 12, 2006
如何更快地批量数据处理?
作者 xzh2000 16:42 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在批量处理数据时,比如从上亿条记录的表中删除上1000万条数据,不仅要考虑对undo的影响,还要考虑对redo,对磁盘i/o,锁、阻塞等的影响,在某种意思上讲,同样的任务,执行的sql次越少,总的消耗的时间就越少。。。

 查看全文
01 12, 2006
用sql比较两个库是否一致
作者 xzh2000 15:43 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

比较两个数据库,可以用工具,比如toad等,也可以自己写存储过程来实现,偶介绍一个用sql来核对表结构是否一致,以此类推,大家可以写出对比索引是否一致,对比约束是否一致的sql,该sql的缺点就是只能查出差异,却不知是那个表引起的:

 查看全文

30 11, 2006
OPT_PARAM Hint in 10g R2
作者 xzh2000 17:19 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

"OPT_PARAM" is a new optimizer hint introduced in 10g Release 2. This hint behaves the same way as setting a parameter (e.g, using alter session) except that the effect is for the statement only.where parameter_name is the name of a parameter and parameter_value is its value. If the parameter contains a numeric value, the parameter value has to be specified without quotes.

The syntax is:opt_param(<parameter_name> [,] <parameter_value>).
For example:/*+ opt_param('hash_join_enabled','false') */

 查看全文

16 11, 2006
10g关闭对象统计信息收集
作者 xzh2000 13:55 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

10g中通过scheduler自动收集对象(表与索引)的统计信息,有两种办法可以关闭对象统计信息的收集,虽然不建议关闭对象统计信息的分析,如果一定要关闭对象统计信息的收集,有两种办法可以参考,具体办法如下:

 查看全文

15 11, 2006
ORACLE字符集的包含关系
作者 xzh2000 10:38 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Metalinke Doc: 119164.1

 查看全文

14 11, 2006
10gR2中如何修改bind var capture interval
作者 xzh2000 13:56 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10gR2中,可以捕获到SQL绑变变量的值,为了效率,每15分钟捕获一次,偶以前有篇文章介绍过SQL绑定变量的捕获,这里就不再介绍如何查看捕获的绑定变量啦,下面给大家简单地介绍一下如何修改bind variable capture interval:

 查看全文

13 11, 2006
10gR2中关于tablespace usage的数据字典视图
作者 xzh2000 14:36 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

在10g以前的版本中,如果查表空间的使用情况,需要对某些数据字典视图进行聚合,统计出表空间(含临时表空间)的使用情况,偶博客中有个改进的统计表空间使用的脚本;在10g中,统计表空间的使用情况就比较简单了,ORACLE已经给我们提供了可以直接查看表空间使用情况的数据字典视图:

 查看全文

12 11, 2006
产生top sql的原因
作者 xzh2000 18:57 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

这是一个网友的面试题,问到top sql一般是什么情况下产生的,不同的公司,dba参与项目的阶段不同,所以答案也就有所区别,一般来讲,top sql产生的阶段有:系统设计阶段(表结构设计),编码实现阶段(SQL编写),SQL审核优化阶段等,这样涉及到的人的因素就有:系统设计人员+开发人员+DBA,任何一个环节出了问题,就有可能出现top sql,所以一个项目,出了性能问题,并不一定是DBA的责任,但优秀的DBA,可以消除潜在的风险。

 查看全文

07 11, 2006
关于v$session_wait_history
作者 xzh2000 12:15 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

V$SESSION_WAIT_HISTORY displays the last 10 wait events for each active session,这是10gR2中reference对该动态性能视的介绍,从该动态性能视图中追溯活动会话最后10个等待事件,如果我们想追溯活动会话更多的等待事件,那该如何实现呢?

 查看全文

06 11, 2006
如何计算index的compress?
作者 xzh2000 15:04 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在创建组合索引时,通常会把选择性好的列作为前导列,但在创建带compress选项的组合索引时,恰恰相反,最好把选择性最差的列作前导列,这样创建出来的索引,更能节省存储空间,但compress选项如何取值呢?请看下面的测试:

 查看全文

01 11, 2006
Oracle 11g new Features
作者 xzh2000 16:11 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

At Oracle Openworld 2006, Oracle announced some exciting new features of Oracle 11g, and they promise 482 specific new Oracle11g features:

 查看全文

25 10, 2006
10gR2启动时报错处理
作者 xzh2000 12:39 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

Errors in file /opt/oracle/admin/dbtest/udump/dbtest_ora_14166.trc:
ORA-00604: error occurred at recursive SQL level 1
ORA-12663: Services required by client not available on the server
ORA-36961: Oracle OLAP is not available.
ORA-06512: at "SYS.OLAPIHISTORYRETENTION", line 1
ORA-06512: at line 15
Wed Oct 25 12:34:50 2006
Completed: ALTER DATABASE OPEN

 查看全文

24 10, 2006
10gR2中awrsqrpt.sql介绍
作者 xzh2000 14:51 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在RDBMS/admin/awrsqrpt.sql中,这个脚本可以方便地取出某个sql在某两个快照间隔内,它总的消耗的cpu时间,执行次数,逻辑读,物理读,sql的执行计划以及sql的full sql text等,不过偶不太喜欢这个脚本。。。

 查看全文

23 10, 2006
回顾v$*stat dynamic views
作者 xzh2000 18:09 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

很久不做实验,发现对常用的dynamic view已经比较陌生啦,做故障处理时,感觉茫无头绪,一方面应该是压力较大所致,另一方面应该是思维太局限于经验所致,而不是根据系统表现的蛛丝马迹进行深入分析,所以有些不重现的或很短暂的故障,通常都如神龙见首不见尾。。。

 查看全文

20 10, 2006
10gR2的awrddrpt.sql介绍
作者 xzh2000 15:32 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

如果想对比两个awr报表的差异,可用RDBMS/admin/awrddrpt.sql脚本,这个脚本的交互部分需要输入要进行对比的两个awr报表的begin snap_id与end snap_id,然后就是要输入对比结果报表的名称;在对系统做调整或优化前,可以创建一个awr的base line,系统调整或优化后,再创建一个awr的base line,这样awr在清除过期awr快照时,就不会清除这些快照。

 查看全文

20 10, 2006
10gR2中awrinfo.sql介绍
作者 xzh2000 14:18 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在RDBMS/admin目录下,awrinfo.sql是统计awr metadata的脚本,比如对awr snapshot每天/每周(快照收集间隔:60min)使用存储空间的趋势进行前期评估等,包括awr segment使用空间比较严重的报表等。用awrinfo.sql可以清楚地得知以下信息:

 查看全文

18 10, 2006
ORA-00020处理思路及防范
作者 xzh2000 10:38 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

昨晚收到短信报警,有两台DB报ORA-00020错误,如果你不太清楚ORA-20代表了什么,在linux/unix平台下,可以用oerr ora 20来查看它比较详细的错误代码;在生产环境中,processes参数一般都设置的比实际的processes多一些,所以DB一旦报ORA-20错误,基本上可以确定是程序出了问题,那该如何着手解决呢?

 查看全文

17 10, 2006
开发库与测试库schema同步的思路及相关过程
作者 xzh2000 17:38 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

如果要维护多套开发与测试的数据库环境,如果schema变动很频繁,那dba的工作量也就非常可观,稍一不慎,就会给开发以及测试有不好的影响,所以同步开发与测试环境的是必不可少的,d.c.b.a曾经开发过一个比较并同步schema的工具,但需要手工执行去同步,偶这次介绍的是通过job+procedure来完成的。

 查看全文

16 10, 2006
10gR2的awr与statspack在enqueue显示上对比
作者 xzh2000 13:41 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在statspack report中,在enqueue 部分,显示的队列enqueue是两个大写字符,即是euqueue的缩写,有时分析euqueue时,还要查手册;在awr report中,在enqueue 部分,不仅显示了缩写,还符带显示了euqueue的描述信息,使dba能够更容易看懂eneuque在等待什么,awr的用户体验比statspack好了很多。。。

 查看全文

15 10, 2006
10gR2优化器对表关联做的优化
作者 xzh2000 10:44 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

在以前的一篇文章中,介绍过额外的关联对SQL的影响是很大的,所以在sql审核的工作中,对于表关联的关注是相当多的,如果冗余能够优化掉表关联,偶都尽量在表设计上做些冗余处理;在10gR2中,发现优化器可以优化掉一些不必要的关联。。。

 查看全文

11 10, 2006
索引的"前导字段 IS NULL"也可以使用索引的
作者 xzh2000 14:07 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

在单列索引中,IS NULL是不会使用索引的,但并不是所有IS NULL都不使用索引,比如组合索引,所以对与一些不确定的东西,我们更应该要以测试的心态来确认它,而不是否定或都不去使用它,通过这个案例,相信可以加深对组合索引的认识;还有值得注意的地方是,有些走索引很正常的sql,如果不小心加了一个is null的条件,很有可能导致索引走错,下例就是很好的例子,没有加starts is null之前,走user_id上的索引,加了is null之后,却走到starts上的索引,所以如果能用hints稳定执行计划,最好加上,免得走错。

 查看全文

10 10, 2006
调整MBRC提高索引创建的速度
作者 xzh2000 14:29 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

调整db_file_multiblock_read_count可以极大提高创建索引的速度,经过测试,在EMC cx700的存储上,将MBRC从16调整到128时,在索引创建时,全表扫描的速度从每秒2400个块左右增加到每秒4500个块左右。。。

 查看全文

09 10, 2006
将freespace.sql做了点改进
作者 xzh2000 15:05 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

通常查看表空间使用情况,查dba_data_files与dba_free_space即可,若查看temp表空间使用情况,可用dba_temp_files与v$temp_space_header字典,用v$temp_space_header的缺点就是并不能准确反映temp表空间的使用情况,改用v$sort_usgae则可以准确地实时反映temp表空间的使用情况:

 查看全文

08 10, 2006
哈希分区表使用时注意事项
作者 xzh2000 17:42 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在使用hash partition表,决定assm表空间的uniform size与分区表的分区个数是非常需要注意的事情,如果初始设置不当,在比较极端的环境中将会对应用造成很严重的后果,那我们做决定时,需要注意那些问题呢?

 查看全文

29 09, 2006
如何查看正在运行的过程?
作者 xzh2000 14:33 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

通过很多字典可以查看那些过程是否在正在运行中,比如v$access,dba_ddl_locks,v$db_object_cache等,当然通过v$session+v$sql/sqlarea等也是可以做到的,下面给大家介绍一下如何通过v$db_object_cache查看正在运行的过程?

 查看全文

26 09, 2006
BULK In-BIND与RECORD
作者 xzh2000 10:49 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

在PL/SQL中,BULK In-BIND与RECORD,%ROWTYPE是不能在一块使用的,也就是说,BULK In-BIND只能与简单类型的数组一块使用,这样导致如果有多个字段需要用BULK In-BIND来处理的话,代码就比较复杂:

 查看全文

22 09, 2006
ORA-600 [729]的错误处理
作者 xzh2000 18:32 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

通过database link为远程的表与序列创建了同义词,大约一个小时报DB报ORA-600错误,期间使用这两个同义词大约200次,查metalink得知,该错误是database link引起的,Patch号:4451759,如果不想打补丁,还有三个办法消除报错:

 查看全文

20 09, 2006
rhel4中lvm2的lv绑定到raw devices支持rac吗?
作者 xzh2000 12:19 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

itpub上有个比较有趣的关于lvm2划出lv绑定到raw devices的贴子,由于没有相关的环境,没有办法测试这些东西,查了一下10gR2 RAC concept文档,并没有明确说明logical volume for raw devices不支持RAC,可以做RAC的存储介质如下:

 查看全文

19 09, 2006
mlog$_xxx表hwm过高导致性能问题的解决办法
作者 xzh2000 19:49 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在fuyuncat的个人站点上,有篇关于mlog$表的HWM过高导致性能问题的一个解决方案,在用物化视图进行快速刷新来同步数据的数据库中,这个问题是非常容易遇到的,特别在数据复制源端数据更新非常频繁的情况下。。。

 查看全文

19 09, 2006
ORA-01460的重现与解决
作者 xzh2000 18:18 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

今天开发工程师说收到应用报ORA-01460错误,然后提交了报错的sql语句,该sql中用到了str2varlist函数,str2varlist有一个输入参数,该形参数据类型是varchar2,具体的创建语法请叁考链接,从sql看,语法没有问题,确定问题在实参上,如何重现该错误呢?示例代码如下:

 查看全文

18 09, 2006
10gR2的wrh$_分区表快速膨胀怎么办?
作者 xzh2000 10:58 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

winngingnick在itpub上问wrh$_表膨胀太快怎么办?事情的缘由是由于系统断电之后,wrh$_active_session_history表膨胀的太快,2周已经膨胀到2000万条记录,在metalink发sr也没有得到解决,根据这些线索,那我们该如何处理这类问题呢?

 查看全文

14 09, 2006
如何评估sql执行所需要的sort space的大小
作者 xzh2000 12:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

如何评估sql执行需要的sort空间呢?如果表与索引最近都做了分析,是可以通过explain plan for 来评估sql执行所需要的temp空间的,explain plan for 不仅可以评估dml操作需要的temp表空间,还可以监控ddl操作所需要的temp表空间,比如创建索引等。。。

 查看全文

13 09, 2006
如何监控mv的刷新进度
作者 xzh2000 12:41 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

foreverlee在itpub上提出这个问题,如果我们执行的是DDL,那么操作就很难监控,但如是执行的是mv的完全刷新,只要它的刷新时间超过6秒,在mlog$_xxx所在的DB中的v$session_longops动态性能视图就会有记录。。。

 查看全文

12 09, 2006
如何监控temp表空间使用
作者 xzh2000 18:12 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在创建索引或做大的排序操作时,监控v$sort_usage动态性能视图是必需的,否则如果temp表空间空间不足将会导致排序操作失败;在数据库的日常维护中,也需要对temp表空间的使用情况进行监控,有利于对系统中的异常排序有所防范。。。

 查看全文
11 09, 2006
外部存储设备抢占sda设备号的解决办法[转]
作者 xzh2000 12:07 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

linux系统加载存储时,时常会出现本地的设备好sda被存储抢占,而本地变成sdb、sdc等。这种现象是因为连接外部存储的适配器的优先级比本地的scsi/fc的适配器的优先级高造成的。出现这种情况os启动时会有swap报错,给系统管理带来一些麻烦,但这个问题可以通过更改os的内核实现改变驱动顺序,在rhel3上有这个问题,rhel4上已经不用考虑了,具本实现如下所示:

 查看全文
10 09, 2006
数据库维护常用的一些规范
作者 xzh2000 19:37 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

对于一个人来讲,习惯就是规范,对于一个团队来讲,需要规范来培养习惯,好的规范有利于形成良好的习惯,好的习惯可以避免人为失误所造成的宕机,所以做为dba,要把一些可能出问题的地方整理成规范,约束自己的行为。。。

 查看全文

09 09, 2006
红帽RHEL 5 beta1下载
作者 xzh2000 00:01 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

红帽RHEL 5 beta1 :
http://linux.chinaunix.net/news/2006-09-08/2686.shtml

 查看全文

08 09, 2006
浅谈有利于开发工程师编码的数据库结构设计
作者 xzh2000 14:46 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

通常在做数据库结构设计时,系统设计人员通常会考虑数据库的性能是否到预定标准及业务需求能否实现,涉及到具体的实现方法却往往考虑的很少,因为大家都认为系统设计都出来了,那业务实现还不是小菜一碟吗?

 查看全文

07 09, 2006
用C语言写的网络蜘蛛[转]
作者 xzh2000 14:29 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

原贴如下:

http://bbs.chinaunix.net/viewthread.php?tid=821361&extra=page%3D1


04 09, 2006
10gR2之前版本兼容矩阵
作者 xzh2000 16:53 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

如果要从10gR2之前的版本升级到10gR2,有些低版本可直接升级到10gR2,有些则需要先升级到某一版本,然后再升级到10gR2,具体情况,可对照以下列表:

 查看全文

31 08, 2006
rhel2.1/3.2/4.3各版本下9iR2/10g如何激活aio?
作者 xzh2000 16:22 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在9iR2以后oracle才支持aio的,但默认它们是不支持aio,如果要打开对aio的支持,需要重新链接一下可执行文件,9iR2与10g中打开aio选项的方式也是不同,所以需要注意,还有就是初始化参数中,对于data file使用raw devices或file system,那参数的设置也稍微有些差异。

 查看全文

25 08, 2006
standby裸设备重复链接错误解决
作者 xzh2000 17:28 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

如果用了raw devices,通常都要为raw devices创建一个软链接,这样在维护起来比较方便,就象文件系统一般,但容易出问题的地方在于两个软链接都连到同一个设备或者链到一个不存在的设备等,standby的mrp进程就会down下来,如果两个软链接都链到同一个在用的裸设备上,standby的实例可能会shutdown的。

 查看全文

24 08, 2006
函数为什么不允许dml操作
作者 xzh2000 15:09 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

前天开发工程师要求产生一个有规则的唯一编码,编码的格式是yyyymmddx#5,即最后五位每天都是从1开始计数,他们自己的实现方式是直接对表求max(id),如果前8位是当前日期,则编码后六位加1,否则产生编码的规则是:前8位是当前日期,后六位从1开始计数。。。

 查看全文

20 08, 2006
standby并行恢复提高恢复速度
作者 xzh2000 16:49 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

standby的归档目录做的是raid5,每个归档日志大小是100m,OS是rhel4.3,RDBMS是9206,用time dd if=/arc/archive/1_xxxx.dbf of=/dev/zero bs=1024k count=100测试,存储的速度还是相当快的,但恢复归档的速度是每10分钟左右一个100m的归档,在业务繁忙时间,standby的归档累积相当多。。。

 查看全文

19 08, 2006
如何生成随机的唯一编码?
作者 xzh2000 16:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

通常来讲,oracle中生成随机唯一编码的方法就是调用sys_guid()函数产生16进制的16个字符的字符串,如果用varchar2来存储guid格式的字符串,那就需要32个字节,如果我们的编码表的数据量很大,比如网站的会员信息表,其它的业务流水表会非常多地引用会员信息表的主键,这个对存储成本要求是非常高的,很多表的索引都比表占用的空间还要多。。。

 查看全文

16 08, 2006
索引逆向扫描优化sql一例
作者 xzh2000 14:27 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

select id, email, status
from test a
where a.id = #Id#
and a.gmt_created = (select max(b.gmt_created)
from test b
where b.id = #Id#);

这个sql对于开发工程师来说,是比较常见的,意思是求最近的一个记录,该索引创建成(id,gmt_created)组合索引,但这样写有两个问题,一是对于索引来讲,需要扫描两次,一次子查询中的聚合扫描,一次范围扫描,第二个问题比较严重,有可能两条记录的gmt_created是一样的,结果集可能是多条,那程序可能就会出错。。。

--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 92 | 1 |
| 1 | TABLE ACCESS BY INDEX ROWID | TEST | 1 | 92 | 1 |
|* 2 | INDEX RANGE SCAN | IDX_TEST_ID | 1 | | 1 |
| 3 | SORT AGGREGATE | | 1 | 27 | |
| 4 | FIRST ROW | | 1 | 27 | 1 |
|* 5 | INDEX RANGE SCAN (MIN/MAX)| IDX_TEST_ID |1 |
--------------------------------------------------------------------------

 查看全文

15 08, 2006
rhel4使用hangcheck-timer
作者 xzh2000 12:32 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
rhel3与rhel4中hangcheck-timer安装不在同一位置.。

 查看全文

14 08, 2006
用rman做restore太好玩了
作者 xzh2000 16:07 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
以前从来没有注意过这个问题,上周要为一个比较大的DB做standby,备份用rman,共用了40多个小时,恢复时用rman进行,恢复过程中有个raw devices链接错了,而且datafile目录oracle用户没有写权限,所以就中断了恢复,当时大约已经恢复了800g,第二次执行restore时,又接着上次的断点开始恢复,真是太好了,否则就偶老人家该吐血了。。。
13 08, 2006
lvm2与Found duplicate PV
作者 xzh2000 10:11 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
最近在rhel4.3上用lvm2来管理emc cx700存储,创建pv,创建vg,创建lv等都已经完成,但在用vgs,pvs,lvs以及其它的比如vgdisplay,pvdisplay,lvdisplay时,都会输出一大串Found duplicate PV 信息,然后才是当前命令执行结果的输出,在google上搜了很久,才知道需要在/etc/lvm/lvm.conf中自定义过滤串。

 查看全文

12 08, 2006
Bug4364202-Failed ONLINE index rebuild
作者 xzh2000 14:42 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

当我们rebuild index online失败后,smon进程会清除sys_journal_xxx(xxx是object_id)以及其它的不一致的东西,在smon清除它们之前,是不能再进行rebuild index online的,如果要清除它们,需要执行dbms_repare包的online_index_clean过程来处理...

 查看全文

11 08, 2006
最近在看的书《剑谍》
作者 xzh2000 20:03 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

看过《仙剑神曲》的筒子大概都记住了牛语者,而《剑谍》就是牛语者继《仙剑神曲》之后的大作,相比起《诛仙》与《七界传说》,牛语者也算是很不错的啦,文笔流畅,构思奇特,不象《诛仙》与《七界传说》,也许多地面让读者觉得摸不着头脑,还有就是《剑谍》的更新速度也比《诉仙》与《七界传说》勤。。。

 查看全文

10 08, 2006
Linux 2.6 deprecation of raw devices
作者 xzh2000 11:32 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

DEPRECATION OF RAW DEVICES IN LINUX 2.6 KERNELS
-----------------------------------------------

Starting with the 2.6 Linux kernel, raw devices are being phased
out in favor of O_DIRECT access directly to the block devices.

With Oracle RDBMS 10.2.0.2 and higher, block devices can be accessed via
any of the following methods, and utilized by RDBMS:

- Directly to the block device
- Via ASMLib mapped devices
- OCFS2 devices (Note: OCFS2 is still Pending Certification)
- LVM2 mapped devices if single-instance

 查看全文

09 08, 2006
[存储设备]什么是NAS?
作者 xzh2000 21:07 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

对于一个企业来说,网络数据的安全性是极为重要的,企业各类应用系统、电子商务运行积累的数据作为宝贵的财产,一定要找个安全合适的方式妥善保管。一旦重要的数据被破坏或丢失,就会对企业日常生产造成重大的影响,甚至是难以弥补的损失。

 查看全文

08 08, 2006
LINUX字符、块设备的区别
作者 xzh2000 21:55 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

1. Character devices are read and written directly without buffering.

2. Block devices can only be written to and read from in multiples of the block size, typically 512 or 1024 bytes. Block devices are accessed via the buffer cache and may be randomly accessed, that is to say, any block can be read or written no matter where it is on the device. Block devices can be accessed via their device special file but more commonly they are accessed via the file system. Only a block device can support a mounted file system.

3. Network devices are accessed via the BSD socket interface and the networking subsytems described in the Networking chapter.

The Raw devices are character devices (major number 162).

 查看全文
07 08, 2006
ads3与ads4网卡识别的差异
作者 xzh2000 18:52 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

这两天在同一台机器上先后安装了ads3与ads4,由于该机器有2块内置网卡,两块外置网卡,发现ads3上默认先识别内置网卡,在ads4上默认先识别外置网卡,由于一开始不太清楚这种情况,所以在配置网络时浪费了一些时间。。。


07 08, 2006
statspack报告中Rollback per trans过高怎么办
作者 xzh2000 18:22 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

olivenan网友在itpub上提问,statspack报表中的Rollback per transaction %达到93.97%,对系统是否有影响,偶以前也曾经也遇到过这个问题,现将这个问题做个解答,希望对这个问题比较困惑的同学有所帮所,实际情况就是:statsapck报表中的rollback perl transaction%比例过高对系统没有什么不利影响。。。

 查看全文
03 08, 2006
EMC powerpath 与 Oracle ASMLib 需要注意事项
作者 xzh2000 10:37 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

这两天在配置EMC cx700的过程中,遇到重重困难,虽然暂时解决了一部分问题,但还有很长的路要走,发现metalink在解决oracle相关问题时(比如EMC powerpath的问题),仅仅依赖metalink上现存的资料还是不够的,只有发tar(现在应该称SR)才能更快地解决问题。

 查看全文

01 08, 2006
ads3.4+powerpath4.3.3+lvm的奇怪问题
作者 xzh2000 11:28 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

昨天在dell pe6650上安装好ads3.4(2.4.27)与emcCX700,然后在ads3.4上安装并配置好powerpath4.3.3,用powermt display dev=all可以看到所有的LUN都已经认出来啦,遗憾的是powerpath盘把我本地盘符从/dev/sda,/dev/sdb顶成/dev/sdcc,重新启动dell pe6650机器时swap好久才能enable上。。。

 查看全文

21 07, 2006
对showsql.sql脚本的改进
作者 xzh2000 11:30 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

很久没有更新博客了,主要是最近被博客上的垃圾评论整得心烦,眼不见心不烦,今天对showsql.sql脚本做了点更新,相信大家用起来更顺手,所以就发出来给大家做参考,本次改进减少了一个sql的调用,输出的结果就更准确了...

 查看全文

14 06, 2006
关于ORA-3136的处理办法
作者 xzh2000 09:54 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

昨天一个朋友给我讲他的DB一直报ora-3136,带来的后果就是客户不能登陆,发现他安装了10g 10.2.0.1 for linux,没有用连接池,连接数也不是很多,process是200,并没有报连接溢出错误,但进程数一直在200以上,查metalink:

 查看全文

04 06, 2006
分区表如何创建分区主键?
作者 xzh2000 15:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在一些应用中,数据有时效性,过段时间这些数据就要被清除掉,每天几百万甚至上千万的数据被删除,将会产生大量的归档,数据删除期间,对DISK I/O的需求很大,为了解决这种情况,用分区表是比较有效的办法。。。

 查看全文

27 05, 2006
dba需要参与数据库设计吗
作者 xzh2000 00:27 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

有人在itpub上提了这个问题,估计相当多的开发dba以及新入行的dba都会有这个疑问,认为表结构以及索引等全由dba来做比较合适,毕竟开发人员对这些并不是很在行,但这对dba的要求就会相当高,要求dba必须对相关的业务系统非常深入,有一定的开发经验,否则dba需要付与非常可观的交流成本。。。

 查看全文

24 05, 2006
如何监控长时间运行的查询
作者 xzh2000 23:23 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

查询v$session_longops动态性能视图可以查看运行时间大于6秒的查询,如果想让运行时间大于6秒的查询被数据库引擎收集,必须满足以下条件:

1 参数timed_statistics或sql_trace为true
2 涉及的对象(表或索引)必须被分析(analyze或dbms_stats)

 查看全文

16 05, 2006
如何同步开发与生产库结构
作者 xzh2000 16:23 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

如果表结构变动较小或管理的数据库不是很多,同步表结构应该是比较轻松的工作,每个开发库修改了,生产库跟着改一下也就再步啦,如果管理的数据库很多,而且变动很频繁,那维护起来的成本就比较高,那我们该如何同步呢?

 查看全文

16 05, 2006
rman备份ora-19573错误
作者 xzh2000 09:42 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

oerr ora 19573
19573, 00000, "cannot obtain %s enqueue for datafile %s"
// *Cause: The file access enqueue could not be obtained for a file
// specified in a backup, copy or restore operation.
// If the enqueue type shown is 'shared', then the file is the
// input file for a backup or copy. If the type is 'exclusive', then
// the file is the output file for a datafile copy or restore which
// is attempting to overwrite the currently active version of that
// file - in this case, the file must be offline or the database must
// be closed. If the type is 'read-only', then you are attempting
// to back up or copy this file while the database is in NOARCHIVELOG
// mode.
// *Action: Wait until the conflicting operation is complete, then retry
// the copy or backup. If the database is in NOARCHIVELOG mode, then
// all files being backed up must be closed cleanly.

 查看全文

08 05, 2006
如何识别索引是否被使用
作者 xzh2000 21:20 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

识别索引是否被使用最准确的方法是使用索引监控,但该方法对系统的性能消耗是相当严重的,特别在访问量较大的系统,可能会导致系统挂掉,但在开发数据库上,还是不错的选择,相关内容见偶另一篇(http://xzh2000.itpub.net/post/96/12850)。

 查看全文

07 05, 2006
ORA-09817错误的处理办法
作者 xzh2000 11:07 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
如果您在alert_*.log发现有ORA-09817错误,基本上可以确定是磁盘空间已经被用光,相关的目录是bdump,udump等...
05 05, 2006
10gR2激活real-time apply
作者 xzh2000 18:54 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

如果dataguard需要激活real-time apply,它需要满足一些必须的条件,首先备库必须有standby redo log,其次dataguard要处于最大保护模式,再就是必须用LGWR来传送REDO信息到备库,可以通过下面的语法进行real-time apply:

 查看全文

05 05, 2006
alter index ... rebuild online的机制
作者 xzh2000 09:26 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

当我们对索引进行rebuild时,如果不加online选项,oracle则直接读取原索引的数据;当我们添加online选项时,oracle是直接扫描表中的数据,那如何维护索引段数据的一致性呢?就是从引开始创建到索引创建完成这段时间的数据改变...

 查看全文

05 05, 2006
临时表对性能有什么影响
作者 xzh2000 08:54 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

由于临时表不请求锁,不生成redo对于数据改变,所在对于临时数据处理是非常有益的;但它会产生undo for data以及redo for undo,临时表使用临时段,在创建临时表时并不自动创建临时段,只有在first insert或ctas时会创建临时段...

 查看全文

02 05, 2006
如何消除undo表空间爆满
作者 xzh2000 22:21 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

在大家dba的职业生涯中,相信undo表空间暴满的情况基本上大家都会遇到,那又如何处理这种情况呢,最常用的方法就是创建新的undo表空间,然后修改undo_tablespace参数切换undo表空间到新创建的undo表空间...

 查看全文

30 04, 2006
序列的nextval属性使用
作者 xzh2000 16:32 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

今天发现一个insert中有两个字段需要相同的值,开发工程师就在sql写了values(seq_test_id.nextval,seq_test_id.nextval,...),当时直觉是错的,担心第二个seq_test.id.nextval产生的ID与第一个不同。。。

 查看全文

30 04, 2006
ORA-01003: no statement parsed解决办法
作者 xzh2000 15:37 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

当修改了表结构之后,再执行引用该表的sql时,应用报01003错误,这时需要重启一下jboss或者weblogic就可以啦。。。所以在生产库上修改表结构也要慎重啦。。。

 查看全文
30 04, 2006
dba要具有的工作习惯之三
作者 xzh2000 14:17 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

习惯:不要轻易地改变约定的东东

 查看全文
30 04, 2006
dba要具有的工作习惯之二
作者 xzh2000 14:11 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

习惯:处理大的工作要保留详细的脚本

 查看全文

30 04, 2006
dba要具有的工作习惯之一
作者 xzh2000 12:58 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

习惯:凡事必先写清楚操作步骤及脚本

 查看全文
30 04, 2006
关于"粗心的DBA太多了"
作者 xzh2000 11:59 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

ccjg2k: 这两天突然发现很多很多求助的帖子都是关于误删数据的。如果连这些最低级的操作都会犯的话,我建议还是别当DBA了,不然以后的麻烦多了,可能会吃不了兜着走了。

 查看全文
30 04, 2006
关于"我们以后能做到吗?"
作者 xzh2000 10:29 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

RQW_: 前二天去一个客户那边,他们的系统是RAC+DATAGUARD的,ORACLE的版本是10G的标准版。在10G的标准版上安装RAC没有问题,这是大家都知道的,关键是他们的DATAGUARD,他们的ORACLE版本是标准版的,他们为了实现他们自己的DATAGUARD,是用许多的SHELL脚本来完成的,工作方式和ORACLE提供的DATAGUARD也不一样,他们是把主库上产生的日志文件自动传输到备用库上,然后进行自动的恢复回去,感觉上原理也不复杂,但看了他们的SHELL脚本,不得不佩服做个事的人,感觉上水平实在太高了,对ORACLE和OS的理解太深了。最后,客户跟我说,做这个系统的人是一个德国的DBA,这个人做数据库方面的足足有30年了,现在有五十多岁了,唉,我们以后能做到这一步吗?数据库刚出来不久,人家就开始做了,现在还在第一线这么执着的做下去。

 查看全文
29 04, 2006
关于如何消除内存排序
作者 xzh2000 16:09 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

相对于逻辑读(buffer_gets)较大的语句而言,内存排序的影响就比较小,如果排序的行比较多,那对CPU的消耗也是非常可观的,所以优化的第一要义就是减少SQL的逻辑读与物理读,如果逻辑读与物理读者比较小,这时就可以考虑消除内存排序...

 查看全文

29 04, 2006
关于lob字段的retention与pctversion参数
作者 xzh2000 12:42 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

lob字段默认是pctversion等到于10,意思是表lob字段所在的表空间需要预留10%的空间给lob的前映象使用,当表空间比较小时,用pctversion应该不会有大的问题,当表空间超过100g时,就需要预留10g,可能存在浪费空间的问题,比如每小时更新lob记录的频率增长不多,还要减去(当lob的内容小于4000字节时,lob的前映象保存在undo表空间)这部分,但如果该表空间增长到300g,就有30g的空间预留下来备用,导致较多的空间被浪费.所以,当您的LOB字段所在的表空间已经很大时,要注意pctversion参数要适当的调小,否则空间的浪费是相当的严重...

 查看全文

26 04, 2006
List control file structures with usage limits
作者 xzh2000 20:34 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

rem ---------------------------------------------------
rem Filename: ctlimits.sql
rem Purpose: List control file structures with usage limits
rem Date: 21-Sep-2000
rem Author: Frank Naude, Oracle FAQ
rem ---------------------------------------------------

set pages 50000
col PCT_USED format 990.09

-- Controlfile creation parameters:
-- Type DATAFILE is for MAXDATAFILES
-- Type REDO LOG is for MAXLOGFILES
-- Type LOG HISTORY is for MAXLOGHISTORY
-- Type REDO THREAD is for MAXINSTANCES
-- No entry for MAXLOGMEMBERS (?)

 查看全文
26 04, 2006
10gR2 rac如何clone新节点
作者 xzh2000 20:07 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

RAC cloning

You can now use OUI to clone RAC nodes and clusterware. The R2 Oracle Universal Installer comes with a perl script, $ORACLE_HOME/clone/bin/clone.pl, which automates the cloning process. A companion script, prepare_clone.pl, prepares the source ORACLE_HOME for cloning by archiving and compressing it; you copy the files over yourself, unarchive, and run clone.pl.

 查看全文

25 04, 2006
aix5.3 ML03两个贴心的改进
作者 xzh2000 09:47 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
1 一般用户可以不用授权就可以用topas
2 不用nfso设置参数就可以直接mount nfs目录啦
23 04, 2006
如何禁止dml table lock?
作者 xzh2000 23:13 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

查DSI405有2种方法可以disable dml table lock:

1 设置dml_locks=0
2 执行alter table xxx disable table lock


23 04, 2006
DSI(405)介绍的调优方法学
作者 xzh2000 20:54 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
1. State the problem.
2. Find the problem stack.
3. Drill down and find the worst bottleneck.
4. Fix it.
5. Test against the baseline.
6. Repeat until you hit your goal.

22 04, 2006
oracle入门书籍导读[转]
作者 xzh2000 23:40 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

很多网友询问如何选择入门书籍,学Oracle有什么好书,这里给出一些常见书籍的介绍。首先声明,本文只涉及国外作品,因为国内的作品好的极少,大多是拼凑之作。

 查看全文
13 04, 2006
Linux内核稳定版2.6.16.5正式发布[fw:cu]
作者 xzh2000 21:14 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Linux 内核稳定版Linux 2.6.16.5正式发布

发表者: 赵珂 2006年04月13日 #136
http://blog.joylinux.org/zhaoke/cn/136.html
原文: Patch: Linux 2.6.16.5
http://lkml.org/lkml/2006/4/12/169

我们(内核稳定版开发小组)宣布2.6.16.5内核正式发布.

 查看全文

13 04, 2006
在存储过程中执行shell命令[fw:asktom]
作者 xzh2000 21:04 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

I can think of a couple of different ways....

o In Oracle8i, release 8.1, we could use java to run a system command with an "&" after it (assuming unix) or perhaps "start xxx.cmd" if using NT.

o In Oracle8.0 and up, we can write an external procedure in C that runs host commands with system() and the "&". (see attached for an external procedure example)

o In Oracle7.0 and up, we can use dbms_pipes to talk to a daemon running outside the database. Here is a simple example that uses sqlplus to be the daemon:

A quick and dirty way to do this is with a csh script and sqlplus as such (cut and pasted from another email)

Ok, so can you do this without C? Yes. Here is a PL/SQL subroutine you can install in your schema:

 查看全文

13 04, 2006
get_hash_value的不稳定性
作者 xzh2000 20:02 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

SQL>select dbms_utility.get_hash_value('我的家',1000000000, 1073741824) from dual;

DBMS_UTILITY.GET_HASH_VALUE('我的家',1000000000,1073741824)
-----------------------------------------------------------
1830833598
1993107607
2026776409

 查看全文

10 04, 2006
偶也开始抓狂啦,呜呜呜
作者 xzh2000 11:29 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

有一个表,已经创建了13个索引,除了主键外,其它的索引都是有六个字段已经上的组合索引,现在开发工程师告诉我需求变化了,按新的需求,要再创建5个组合索引,呜呜,不知那位有过这种情况,创建超过15个以上的索引,而且这个表的insert,update,delete都比较频繁...真担心这个表会崩溃...


08 04, 2006
10g awr与statspack区别
作者 xzh2000 00:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Oracle Database 10 genhances the data collection mechanism with the introduction of the Automatic Workload Repository and Active Session History, which replace the previous performance data gathering tools such as Statspack and utlbstat/utlestat. The major differences between the current repositories from previous such tools include the following:

 查看全文

08 04, 2006
10g中mmon与mmnl的区别
作者 xzh2000 00:17 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

The MMON (Manageability Monitor) process is responsible for various
manageability tasks such as taking snapshots of various statistical information at prescribed time intervals and issuing alerts when metric values exceed defined thresholds. The MMON process can spawn multiple slave processes to perform these tasks.
The MMNL (the Manageability Monitor—Lightweight) process is responsible for computing various metrics and taking snapshots of active sessions at every second.We’ll discuss this further in the section “Active Session History.”

 查看全文

07 04, 2006
10gR2 SQL Profile Enhancements
作者 xzh2000 21:01 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
SQL Profile Enhancements
This feature allows SQL Profile to match SQL text after literal values have been normalized into bind variables.SQL Profile has been enhanced to allow applications to use literal values rather than bind variables.
05 04, 2006
10gR2中Distributed Large Objects (LOB) Support
作者 xzh2000 19:55 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Distributed LOBs support provides easy-to-use and efficient support for accessing unstructured data in a distributed environment. The data interface for LOBs can now INSERT, UPDATE, and SELECT LOBs across dblinks.The benefit of this new support is the ability to access remote LOBs.
31 03, 2006
10gR2 rman的新特性
作者 xzh2000 21:53 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

1 可加密的备份集
2 闪回数据库增强(可跨过open resetlogs)
3 Restore Points
4 Guaranteed Restore Points
5 Incremental Roll Forward of Database Copy
6 Easy Conversion of Physical Standby Database to a Reporting Database
7 Database Transport Across Same Endian Platforms
8 Transportable Tablespaces from Backup
9 Unused Block Compression
10 Temporary Datafiles Are Re-Created on RMAN Recovery
11 Support for Backup Vaulting in Media Managers
12 Backup and Recovery Enhancements in Enterprise Manager


31 03, 2006
10gR2 rman backup as Compressed backupset
作者 xzh2000 14:46 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10gR2中,可以允许dba对备份集进行压缩,即可以压缩到磁盘,也可以压缩到磁带,在测试中,可以将2g容量的数据文件,压缩后的备份集只有50m左右,可以极大地节省空间...

使用命令:

rman>backup as compressed backupset full database;


31 03, 2006
10gR2 rman对Unused Block Compression
作者 xzh2000 13:42 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

在10gR2中,rman最显著的一个特征就是对未分配的块进行压缩,但它必须满足一些必要的条件,在满足该条件下做了测试,效果非常理想,创建一个2g的数据文件,备份集只增加了8m,而且数据文件总的容量在2g,备份集才588m.

备份的脚本:

rman>backup full database format = 'd:test.bak';

必须满足的条件如下:

 查看全文
29 03, 2006
如何测试web分页sql的性能
作者 xzh2000 23:05 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

如何真实地测试web分页sql的性能呢?一方面就是求助于测试部门编写测试用例,但在某些实现方案的选型时,求助测试部门就比较麻烦,本例给出了非常简单的测试方案,并改进了runstats_pgk,添加了一个新的过程rs_run过程,当然也不必用runstats_pgk,只需要配置一下statspack即可...

 查看全文

14 03, 2006
用forall+db link的一个bug
作者 xzh2000 16:00 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

在用forall通过db link更新另一个库的记录时,这个会报ora-01483错误的,后来测试用for ...loop的方式是可以的,查metalink也没有找到很明确的bug信息...


13 03, 2006
对showsql.sql的再次改进
作者 xzh2000 19:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

上次改进了显示sql时,显示更多的信息,比如sql总的执行次数,单次的物理读与逻辑读,这次改进主要是显示sql在v$sql_plan中的执行计划,还添加了kill当前会话的脚本...

 查看全文

28 02, 2006
10gR2的event及其分类
作者 xzh2000 22:28 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

SQL> select distinct wait_class from v$event_name;

WAIT_CLASS
--------------
Concurrency
System I/O
User I/O
Administrative
Other
Configuration
Scheduler
Cluster
Application
Idle
Network
Commit

 查看全文

28 02, 2006
10gR2索引创建新特性
作者 xzh2000 22:09 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

在10gR2中,索引创建后,索引的统计信息就已经存在啦,这样就可以避免10gR2以前版本中索引创建后与索引分析完成之前这段时间内系统崩溃的风险...

 查看全文

23 02, 2006
这种情况如何创建索引?
作者 xzh2000 23:14 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

在较关键的系统中,在晚上流量较小时,用online的方式索引,无论是单列索引还是组合索引,在索引创建完毕与分析完毕之间,这段时间极可能搞跨整个系统,如果创建后的索引比较大,你会如何来处理这个事情?前提是没有停机维护时间...

 查看全文

16 02, 2006
发布查看v$sql_plan的脚本
作者 xzh2000 19:50 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

该脚本主要从$ORACLE_HOME/rdbms/admin/sprepsql.sql 中取出,简化了一些不太感兴趣的东西,更简洁...

 查看全文

12 02, 2006
metalink完蛋了?
作者 xzh2000 20:54 | Permalink 静态链接网址 | Comments 最新回复 (6) | Trackback 引用 (0) | 技术交流
慢得不敢相信是oracle公司的站点?
11 02, 2006
绑定变量的一个陷井
作者 xzh2000 23:10 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

有一个SQL,当用explain plan for 进行查看它的执行计划时,走的是索引扫描(通过主键),当代入实际值时,显示的全表扫描,后来发现SQL的传入的实参的类型搞错了...

 查看全文

11 02, 2006
用分析函数求出同名的记录
作者 xzh2000 23:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

利用分析函数只求出重复的记录

create table test_0210(id number,name varchar2(32),age number);

SQL> select * from test_0210;
ID NAME AGE
---------- -------------------------------- ----------
1 abc 32
2 def 33
3 def 45
要求的结果:
ID NAME AGE
---------- -------------------------------- ----------
2 def 33
3 def 45

 查看全文

11 02, 2006
10g中如何构造柱状图?
作者 xzh2000 02:19 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

在10gR1开始,oracle就允许用户自己构造柱状图,由于柱状图分等高与等宽两种,所以由width_bucket构造等宽柱状图,由ntile构造等高的柱状图,测试方法如下所示:

 查看全文

09 02, 2006
关于10gR2的commit_write
作者 xzh2000 12:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

commit_write会减少log file sync的值,执行shotdown abort,没有数据丢失

SQL> alter system set commit_write='immediate,nowait' scope=both;

System altered.

Elapsed: 00:00:00.02
SQL> @list_waits

EVENT TOTAL_WAITS
-------------------------------------------------------------- -----------
log file sync 1
db file sequential read 72
db file scattered read 2

Elapsed: 00:00:00.19
SQL> delete from para_all where rownum = 1;

1 row deleted.

Elapsed: 00:00:00.05
SQL> commit;

Commit complete.

Elapsed: 00:00:00.01
SQL> @list_waits

EVENT TOTAL_WAITS
-------------------------------------------------------------- -----------
log file sync 1
db file sequential read 74
db file scattered read 3

Elapsed: 00:00:00.04
SQL> alter system set commit_write='immediate,wait' scope=both;

System altered.

Elapsed: 00:00:00.02
SQL> delete from para_all where rownum = 1;

1 row deleted.

Elapsed: 00:00:00.00
SQL> commit;

Commit complete.

Elapsed: 00:00:00.01
SQL> @list_waits

EVENT TOTAL_WAITS
-------------------------------------------------------------- -----------
log file sync 3
db file sequential read 74
db file scattered read 3

Elapsed: 00:00:00.04
SQL> delete from para_all where rownum = 1;

1 row deleted.

Elapsed: 00:00:00.01
SQL> commit;

Commit complete.

Elapsed: 00:00:00.00
SQL> @list_waits

EVENT TOTAL_WAITS
------------------------------------------------------------- -----------
log file sync 4
db file sequential read 74
db file scattered read 3

Elapsed: 00:00:00.04

 查看全文
09 02, 2006
10gR2的automatic checkpoint tuning
作者 xzh2000 12:27 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

前2天看文档讲,当设置了FAST_START_MTTR_TARGET参数,将激法mttr advisor来tuning checkpoint,如果想激法automatic checkpoint tuning,就不需要设置以下参数:

fast_start_mttr_target
fast_start_io_target
log_checkpoint_interval
log_checkpoint_timeout

 查看全文
09 02, 2006
对showsql.sql脚本的改进
作者 xzh2000 11:02 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

原脚本如下所示:

---------------- showsql.sql --------------------------
column status format a10
set feedback off
set serveroutput on

select username, sid, serial#, process, status
from v$session
where username is not null
/

column username format a20
column sql_text format a55 word_wrapped

set serveroutput on size 1000000
declare
x number;
begin
for x in
( select username||'('||sid||','||serial#||
') ospid = ' || process ||
' program = ' || program username,
to_char(LOGON_TIME,' Day HH24:MI') logon_time,
to_char(sysdate,' Day HH24:MI') current_time,
sql_address, LAST_CALL_ET
from v$session
where status = 'ACTIVE'
and rawtohex(sql_address) <> '00'
and username is not null order by last_call_et )
loop
for y in ( select max(decode(piece,0,sql_text,null)) ||
max(decode(piece,1,sql_text,null)) ||
max(decode(piece,2,sql_text,null)) ||
max(decode(piece,3,sql_text,null))
sql_text
from v$sqltext_with_newlines
where address = x.sql_address
and piece < 4)
loop
if ( y.sql_text not like '%listener.get_cmd%' and
y.sql_text not like '%RAWTOHEX(SQL_ADDRESS)%')
then
dbms_output.put_line( '--------------------' );
dbms_output.put_line( x.username );
dbms_output.put_line( x.logon_time || ' ' ||
x.current_time||
' last et = ' ||
x.LAST_CALL_ET);
dbms_output.put_line(
substr( y.sql_text, 1, 250 ) );
end if;
end loop;
end loop;
end;

 查看全文
08 02, 2006
10gR2中绑定变量的捕获
作者 xzh2000 12:46 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10g以前的版本,是不能捕获bind var的实参的,但在10gR2是可以捕获bind var的实际参数值.为了降低系统的压力,bind data capture与Modification Monitoring一样,都采用15min钟取样一次...

 查看全文

08 02, 2006
10gR2中废弃的隐藏参数
作者 xzh2000 11:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在9ir2中,共有隐藏参数597个,在10gR2中隐藏参数共有1127个,其中9ir2共有38个隐藏参数不再使用,新增隐藏参数568个,以下就是废弃隐藏参数列表:

 查看全文

07 02, 2006
10gR2中几个新函数
作者 xzh2000 22:23 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

SQL> select nvl2(null,'1','2'),nvl2('abc','1','2'),nullif('abc','abc') from dual;

N N NUL
- - ---
2 1

 查看全文

07 02, 2006
10gR2中创建表空间的变化
作者 xzh2000 21:57 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

在10g以前的版本,创建的表空间如果不指定segment space management auto,则创建的表空间将不是assm类型的...在10g中,assm是默认的表空间间类型...

 查看全文

12 01, 2006
如何去掉列的默认值?
作者 xzh2000 11:58 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

在我写的字典管理软件中,当需要取消某个number类型字段的默认值时,default null后就与原始的不同啦,查了一下手册,好象也没有nodefault这样的功能...

 查看全文

11 01, 2006
视图字段信息在那个字典中
作者 xzh2000 14:29 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

以前从没考虑过视图的字段信息在那里,通常用desc就可以看到了,这段时间在写一个管理字典的工具,由于这个问题导致收集的字段数不对,后来查了一下,发现是因为视图的字段信息在user_tab_columns中所致.


10 01, 2006
判断可否resize数据文件的脚本
作者 xzh2000 10:06 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
转metaling: 查看全文
29 12, 2005
面向 DBA 的 Linux Shell 脚本简介[转]
作者 xzh2000 11:11 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

大约 7 年前,Oracle 发布了 Linux 上的第一个商业数据库。从那时起,Oracle、Red Hat 和 Novell/SUSE 就不断地合作更改 Linux 内核,从而提高数据库和应用程序的性能。正因为这样,用于 Linux 的 Oracle 数据库 10g 才包含了与操作系统紧密相关的许多增强功能。DBA 比以往任何时候更需要了解和使用此平台来在其监视下对系统进行最佳管理。

 查看全文

27 12, 2005
pl/sql中模拟数组...
作者 xzh2000 10:22 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
declare
type rec_name is record
(lastname varchar2(32),
firstname varchar2(32));
type var_array is table of rec_name;
v_rec rec_name;
v_arr var_array := var_array();
begin
v_arr.extend;
v_rec.lastname := 'abc';
v_rec.firstname := 'def';
v_arr(1) := v_rec;
dbms_output.put_line(v_arr(1).lastname);
end;
27 12, 2005
淘宝网聘dba一名.
作者 xzh2000 10:15 | Permalink 静态链接网址 | Comments 最新回复 (13) | Trackback 引用 (0) | 技术交流
职位:数据仓库工程师
需求人数:1
工作地点:杭州
职责描述:数据仓库DBA以及ETL开发
职位要求:
1.精通ORACLE,熟悉安装,升级,备份,恢复,RMAN,STANDBY,RAC等.
2.数据库调整优化,sql调优.
3.精通linux,AIX操作系统.
4.具备EMC管理经验.
5.熟悉数据仓库概念,具备ETL开发经验.
6.具备团队精神,细心.

有意者请发邮件:yekai@taobao.com

20 12, 2005
Borland Delphi2006新功能
作者 xzh2000 12:05 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

Borland Delphi 2006 和C++ Builder 2006
2005-11-11 09:22:27 delphi精髓2005 出处:borland

Borland Delphi 2006 和C++ Builder 2006新增关键功能,
以加速微软 Windows 和 .NET 应用的交付
为针对微软 Windows 和 .NET 的 Borland 多语言开发环境
Borland Developer Studio提供加强的开发环境

 查看全文
06 12, 2005
10gR1中ora-00201,ora-01103错误的解决办法
作者 xzh2000 10:52 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

今天刚到公司,有个网友发了ip与密码过来让我帮你启动数据库,进去后发现数据库安装的比较乱,启动数据库时报00201的错误,很久不摸这些安装方面的东西啦,有点生,忙完了一些例行工作,然后就静下心来测试,很快就启动数据库啦.

 查看全文

26 10, 2005
2种设计思路,喜欢那一种
作者 xzh2000 11:33 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

某表中有较多的状态(标志)字段,假如业务发生变化时,可能就要添加新的状态字段,不仅要对表结构进行修改,还要对程序进行修改,或许相关的索引也要修改,具体示例如下.另一种情况是只创建一个状态字段,所有的状态位都用2进制进行按位与.

这两种方法谁更好呢?它们都需要对状态字段进行文档化管理,不过第二种情况下,需要对状态字段进行严格的2进制编码,程序上也需要相应的改动,但好处就是不需要修改表结构与索引结构,dba维护时比较方便.

从示例来看,第一种情况虽然dba需要维护的工作量较大,但程序可读性较好,而且性能也比第二种情况好,其实性能方面不是绝对的,因为第一种情况中很多标志字段有很多是空值,所以索引较小,当然性能也好一些,如果状态字段都禁止非空,那性能的优劣就很难说的.

 查看全文
21 10, 2005
9206有bitor这个函数吗?
作者 xzh2000 14:46 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

今天在一台9206 for aix上做了测试,发现bitand/bitor都是有的,但在9206 for linux上竟然只有bitand,没有bitor,真是奇怪,希望大家测试一下是否在其它的版本上也有这个问题?

 查看全文

13 10, 2005
10gR2中ckpt的新特征.
作者 xzh2000 11:08 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

 查看全文

10 10, 2005
10gR2 RAC设置归档的改进
作者 xzh2000 14:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10g以及的数据库版本,将非归档的RAC数据库改成归档的RAC数据库,需要将cluster_database先设置为false,然后按单实例的设置归档方法就可以啦.

 查看全文

05 10, 2005
10gR2transportAWRData
作者 xzh2000 23:21 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Transport AWR Data

Let's say you are tying to resolve some performance issues in the production databases. As you saw elsewhere in this article, the AWR data is vital for the analysis. However, analyzing AWR data during a normal production run may not be desirable or even feasible. Rather, you may want to load the data in some central location for comparative analysis. How can you do that?

 查看全文
05 10, 2005
10gR2中check for tracing
作者 xzh2000 23:18 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Check for Tracing Enabled

If a session is not doing what it is supposed to do, or is doing it slowly, the first step for most DBAs is to check the wait events. To build a profile, you may also want to trace the session over an extended period, which produces a trace file in the user_dump_dest directory. Now, imagine that you have been using end-to-end tracing on several sessions for some time but now you have no idea which sessions have tracing turned on. How do you find out?

 查看全文
04 10, 2005
10gR2中temp表空间的tempfile可以自动重建
作者 xzh2000 22:09 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

文档中说用rman恢复数据库后,数据库会自动重建temp文件,这个还不够细,偶down下数据库后,删除temp文件,然后再重启实例,发现temp文件已经recreate,真是不错。

 查看全文

04 10, 2005
10gR2中rman的一个新功能
作者 xzh2000 22:02 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Dynamic RMAN Views for Past and Current Jobs

Like numerous other DBAs, I fell in love with RMAN soon after it was introduced in Oracle8. Nevertheless, I never felt that I understood its activities as thoroughly as I should. In Oracle Database 10g Release 2, the new dynamic views provided for RMAN jobs make it extremely easy to peek into these activities—current as well as past.

 查看全文
04 10, 2005
10gR2中将推出的新备份工具obtool
作者 xzh2000 21:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Many DBAs, of course, still like to use the command line and write scripts. OSB provides a command line tool called obtool. You can invoke the command line version of the tool by typing: obtool which brings up the OSB prompt ob>. You can type "help" here to see the commands available.

 查看全文
02 10, 2005
如何改变awr快照的收集级别?
作者 xzh2000 17:22 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在我另一篇博客中,曾经提到过一个问题:如何改变awr中snapshot的收集级别?在statpack中,快照的收集级别有1/5/6/7/10共五种,而且可以通地statspack的过程来改变它的收集级别,在awr中,如何来改变它们呢?

 查看全文

02 10, 2005
10gR2中dbms_file_transfer
作者 xzh2000 14:18 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
DBMS_FILE_TRANSFER Package in Oracle Database 10g,Oracle 10g has introduced the DBMS_FILE_TRANSFER package which provides an API for copying binary files between database servers. Common Usage Notes COPY_FILE GET_FILE PUT_FILE Common Usage Notes,All of the the currently supported procedures have some common usage notes listed below: The user must have read privilege on the source directory object and write privilege on the destination directory object. The procedure converts directory object names to uppercase unless they are surrounded by double quotes. Files to be copied must be multiples of 512 bytes in size. Files to be copied must be equal to or less than 2 terabytes in size. File transfers are not transactional. Files are copied as binary, so no character conversions are performed. File copies can be monitored using the V$SESSION_LONGOPS view. 查看全文
02 10, 2005
10gR2中segment advisor(segment_advisor.sql)
作者 xzh2000 14:05 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
-- ----------------------------------------------------------------------
-- File Name : http://www.oracle-base.com/dba/10g/segment_advisor.sql
-- Author : DR Timothy S Hall
-- Description : Displays segment advice for the specified segment.
-- Requirements : Access to the DBMS_ADVISOR package.
-- Call Syntax : Object-type = "tablespace":
-- @segment_advisor.sql tablespace (tablespace-name) null
-- Object-type = "table" or "index":
-- @segment_advisor.sql (object-type) (object-owner) (object-name)
-- Last Modified: 08-APR-2005
-- --------------------------------------------------------------------- 查看全文
02 10, 2005
Validates and rebuilds indexes
作者 xzh2000 13:45 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

由于格式太乱,已经删除了文章。。。


01 10, 2005
一个存储过程的四种写法
作者 xzh2000 23:24 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

一个存储过程的四种写法
create table test(
id number(8),
name varchar2(32),
constraint pk_test_id primary key (id)
);

begin
for i in 1..20000 loop
insert into test values(i,'abc');
end loop;
commit;
end;
/

 查看全文

30 09, 2005
对showsql脚本的再次改进
作者 xzh2000 17:42 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

编写脚本,怎么将由脚本消耗的资源降低也是需要考虑的因素,更重要的是使脚本的产出最大化,刚开始达到自己目的,然后考虑脚本的性能问题以及应对意外的情况.写一个完善的脚本真是件不容易的事情.

 查看全文

29 09, 2005
对监控topsql脚本的改进
作者 xzh2000 22:08 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

http://blog.itpub.net/post/96/42062这篇博客中,偶在试运行时发现了一个比较严重的bug,比如uptime返回load时,用awk取回的load可能有些问题,还有就是重复地检测实例是否启动会将nohup.out文件写入很多连接信息,改进如下:

 查看全文

28 09, 2005
在主机的负载突然增高时抓取topsql/event的shell
作者 xzh2000 23:26 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

看了d.c.b.a关于otop与opmon工具,感觉有些美中不足之处,经过几天的思考,终于决定在aix下用shell编写一个在系统的load突然增高(可能是大作业或者是异常的SQL)时,抓取系统中topsql与topevent的程序,本shell每隔5秒唤醒一次,执行时检查系统中load的情况,如果超过设定的阀值,就执行一些sql抽取系统中的topsql与topevent。

 查看全文

27 09, 2005
10gR2中ash最妙的描述.
作者 xzh2000 16:24 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Introduction
==========
Performance tuning and problem diagnosis are the two most challenging and important management tasks that any database administrator erforms. In line with the primary drive of the server manageability effort, the Autometic Database Diagnostic Monitor (ADDM) attempts to make, performing these two tasks, a lot simpler and easier. ADDM employs an iterative top-down approach and drives a rule-based expert system, to identify bottlenecks in a system and suggest relevant recommendations to tackle them.

 查看全文

27 09, 2005
10gR2dump出ashbuffer?
作者 xzh2000 16:17 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

如何dump出ash buffer?
SQL> oradebug setmypid;
SQL> oradebug unlimit;
SQL> oradebug dump ashdump 10
SQL> oradebug tracefile_name
/home/oracle/admin/test/udump/test_ora_10448.trc
SQL> host more /home/oracle/admin/test/udump/test_ora_10448.trc

 查看全文

26 09, 2005
分区表的主键必须全局吗?
作者 xzh2000 18:31 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

记得以前曾经做过分区表的测试,发现在9204上分区表的主键必须是GLOBAL类型的,今天在9206及10gR2上测试发现,分区表的主键可以是LOCAL类型的.

 查看全文

26 09, 2005
10gR2中dbms_sqltune案例
作者 xzh2000 18:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

这几天主要在考虑10gR2中awr/ash/addm与sqltuning advisor相关的一些内容,在生成awr的报表时,发现awr的snap level是2,但oracle的awr并没有给出改变快照级别的接口,郁闷.针对sqltuning advisor做了一个测试案例:

 查看全文

26 09, 2005
sqlplus通过错误号查错误
作者 xzh2000 00:59 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流
SQL>host oerr ora 03113
SQL>exec dbms_output.put_line(sqlerrm(-03113));
26 09, 2005
关闭awr快照收集的方法
作者 xzh2000 00:40 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

关闭awr快照收集的两种方法:
1 将awr快照的收集间隔设置为0,这将导致不能手工收集快照。
2 将statistics_level设置为basic,这种则允许手工收集快照。

 查看全文

21 09, 2005
红帽GFS获得Oracle、EMC和NetApp的支持
作者 xzh2000 12:46 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

红帽公司今天在旧金山举行的甲骨文全球技术与应用大会上宣布红帽全球文件系统GFS现在分别获得Oracle RAC解决方案、EMC CLARiiON®网络存储系统、EMC Celerra iSCSI网络存储NAS系统解决方案以及NetApp SAN接口解决方案的支持。红帽GFSOracle Linux平台RAC解决方案所支持的第一个第三方计算机集群文件系统。

 查看全文
21 09, 2005
达梦数据库是mssql与oracle搓合的怪胎吗?
作者 xzh2000 12:40 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

2005913日,达梦数据库管理系统DM V5.0版本已经由达梦公司研发部门完成开发工作,并经过测试部的测试,其功能基本达到要求,已经通过产品部验收,于是日正式发行。

 查看全文
19 09, 2005
10gR2中awr、ash、addm、statspack报表的区别
作者 xzh2000 01:57 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10gR2中,awr报表实际上是statpack报表的延伸,当然10gR2中还是保留了statpack,并且statpack也增加了对stream_pool的监控,awr与statpack的区别就是awr的快照的收集与维护更加自动化,默认的保留七天的快照,并且可以通过dbms_workload_repository表修改快照的收集频率与快照的保留时间,dba要干预的已经很少了,比statpack维护更简单。

 查看全文

14 09, 2005
10gR2中performance tuning的新功能
作者 xzh2000 17:09 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

相比与10gR1而言,10gR2在performance tuning方面更注重人机交互,不仅statpack得到了很大的增强,还提供了很多新的report机制,dba借助这些报表,可以更快地监控系统性能.

 查看全文

13 09, 2005
10gR2中rename file新功能
作者 xzh2000 14:59 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10g以前的版本,是不能随意地重命名datafile/redofile/tempfile的,但在10g中,这些都可以进行啦.当然重命名datafile与9i一样,要么数据库处于mount状态,要么数据文件或其表空间要offline,在重命名redofile时,数据库必须处于mount状态.

 查看全文

10 09, 2005
RAW设备20问[转贴]
作者 xzh2000 12:29 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

关于裸设备的使用20问,写得不错,但其中第9条则有待改进一下,如果库很,裸设备如果不创建ln,则管理起来将是巨头痛的事情,特修改一下,希望对使用RAW的朋友有所帮助。

CREATE TABLESPACE RAW_TS  DATAFILE '/dev/raw1' size 30712k   DATAFILE '/dev/raw2' size 30712k;

改成如下所示:
ln -s /dev/raw1 /opt/oracle/oradata/test/test01.dbf
ln -s /dev/raw2 /opt/oracle/oradata/test/test02.dbf

CREATE TABLESPACE RAW_TS
  DATAFILE '/opt/oracle/oradata/test/test01.dbf' size 30712k
  DATAFILE '/opt/oracle/oradata/test/test02.dbf' size 30712k;

 查看全文
10 09, 2005
LOB字段的cache语法
作者 xzh2000 12:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

LOB字段的cache语法与表的cache语法是不同的,查了一下文档,将表与LOB字段的语法记录如下:

 查看全文

09 09, 2005
求表中最新10条记录的方案
作者 xzh2000 13:28 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在一个比较大的表,如果要求最新添加的10条记录,通常肯定要对时间字段进行排序,也就是说至少也要进行索引全扫描(或者ffs),不知大家有没有其它的方案,下面给出偶的替代方案:

 查看全文

08 09, 2005
bulk collect into的使用
作者 xzh2000 13:42 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

果然可以快很多,存此备查.

 查看全文

30 08, 2005
10gR2stream模式级复制
作者 xzh2000 16:50 | Permalink 静态链接网址 | Comments 最新回复 (5) | Trackback 引用 (0) | 技术交流

真是比较郁闷,发现这篇博客突然少了一半,然后就从源来的文章编辑一下,编辑后保存,然后报文章分类没有选择,选择分类后然后再保存,系统报告保存成功,但实际上我这篇文章已经丢人,看来itpub的博客系统有很大的问题,只好把该文章重写从源文件上传一次,希望以后不要出现这样的错误啦。

 查看全文

30 08, 2005
表结构优化,你偏执了没有?
作者 xzh2000 14:34 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

在上亿级记录的表结构设计时,每节省一个字节都会节省大量的存储空间,而存储就是钱啊,所以设计这种类型的表,必须以最偏执的态度去对待,不冗余任何信息;但已经存在于业务系统中的巨型表结构该如何优化呢?

 查看全文

26 08, 2005
如何确定索引是否需要重建
作者 xzh2000 10:33 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

如果你知道某个表的insert/update/delete都比较频繁,那么这个表的索引隔段时间就需要进行rebuild,但如果你新接手一个系统的维护与管理,对表的DML频率并不清楚,那如何决定是否对这个表的索引进行rebuild呢?

 查看全文

19 08, 2005
SAN,NAS,DAS及架构区别
作者 xzh2000 11:18 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

随着计算机技术的发展和广泛应用,存储技术已经得到了业界和各个应用领域专业人士的重视。数据量的迅速增长为企业的发展提出了新的问题和要求,如何确保数据的一致性、安全性和可靠性,如何实现不同数据的集中管理,如何实现网络上的数据集中访问,如何实现不同主机类型的数据访问和保护等等。所有这些都呼唤着新的网络存储技术及其产品的出现。

 查看全文
16 08, 2005
理解和使用aix日志系统
作者 xzh2000 16:42 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

作者:天涯明月刀

通常我们在进行服务器的健康性检查,和在出现问题的时候都会去考虑查看系统的日志。
我在学习aix的过程中发现,aix的日志跟solaris或linux的日志存储和查看的方式有着相当大的区别,为了使自己对aix的日志认识的更系统就总结了一下。相当一部分是参考的 于宁斌《AIX 5L系统管理技术》

 查看全文

16 08, 2005
用mrtg吗? 用cacti监控性能
作者 xzh2000 16:30 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

作者: JoeCen[joecen{at}21cn{dot}com]
转载时请保持该通告


前言:
在CU的论坛上经常看到有人问MRTG的问题,还有很多的关于MRTG的精彩文章。MRTG的确是非常好的东东,但我认为它毕竟已经是一套很旧的软件了,其作者在多年前就已经开发了RRDTool代替该软件,现在已经发展得很成熟。既然有更好的选择,为什么我们还要用MRTG呢?

 查看全文
15 08, 2005
对大表求min/max注意事项
作者 xzh2000 18:40 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

有一个近亿条记录的表,当需要对主键字段求min/max时,如果在同一条sql中使用min/max时,将会特别的慢,如果分成两条sql执行时,则速度很快,测试如下:

 查看全文

09 08, 2005
10gR2监听的一个小问题
作者 xzh2000 15:26 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

不知10gR1是不是这样,当你修改了机器的IP地址,然后忘了修改listener.ora及tnsnames.ora文件,这时你再用lsnrctl start启动监听时,进程就会被挂住,不象9iR2会马上报错......

 查看全文

08 08, 2005
不小心又犯了一个低级错误
作者 xzh2000 19:18 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

前几天在修改一个移动信息到历史库的过程时,发现历史库机器某目录内有该过程的创建脚本,就不客气地直接在该脚本上做了修改,将修改后的脚本在历史库中执行了,该过程就被修改过的过程替代了,然后该过程安排在crontab中进行调度运行,跑了几天后,发现该过程有些问题,似乎数据没有迁移过来,才发现该过程以前已经修改过,但没有将修改的地方同步到脚本中来。

 查看全文

04 08, 2005
"="与"in"某种情况下的差异
作者 xzh2000 10:14 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

今天发现了一个sql,逻辑读与物理读都比较高,就分析了一下。

 查看全文

02 08, 2005
EMC存储与powerpath关系
作者 xzh2000 22:05 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

EMC中POWERPATH软件支持I/O负载均衡,那么如下图中所示,POWERPATH将IO数据平衡到达:SPA和SPB,二路数据去向应该是同一个LUN,此时SPA对LUN有控制权,SPB没有.二个主机端均能够看到LUN。
结论:
此时主机端二路数据均能够到达同一个LUN!

 查看全文

01 08, 2005
10gR2stream表级复制配置
作者 xzh2000 17:15 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

与dbms_streams_adm的maintain_global、maintain_tts、maintain_schemas等过程相比,maintain_tables过程使用则更灵活,可以为某些特殊的表拿出来单独配置,maintain_tables也象其它的过程一样,提供了一蓝子解决方案,如果要添加新的表到复制中,只需要再次执行maintain_tables过程即可。

 查看全文

30 07, 2005
10gR2stream表空间复制
作者 xzh2000 00:08 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

本人在博客中为大家介绍了10gR2的全库多源复制、模式级复制等,在做表空间级复制时,竟然遇到了一些问题,总之表空间复制目前并没有成功,怀疑是因为前面做了模式级的复制,清除复制环境时遗留了一些问题,如果大家有环境的话,可以试试偶的步骤,基本上应该是正确的。

 查看全文

29 07, 2005
轻而易举把10gR2整死啦
作者 xzh2000 23:33 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

这几天做10gR2的stream replication实验,感觉10gR2中stream功能比9iR2及10gR1强了很多,但也遇到两个比较莫名其妙的问题,一个就是10gR2安装后改机器名的问题,该问题已经在偶的博客中已经有描述(http://blog.itpub.net/post/96/36127

 查看全文

27 07, 2005
10gR2stream全库复制
作者 xzh2000 21:40 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在偶的这篇http://blog.itpub.net/post/96/35709博客中,主要为大家介绍了pre_instantiation_setup/post_instantiation_setup过程在配置全库复制的方法,本篇介绍dbms_streams_adm的maintain_global过程如何配置stream全库复制方法,适用于10gR2及以后版本。

 查看全文

27 07, 2005
10g中表监控与statistics_level
作者 xzh2000 19:53 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

在10g之前的版本,必须用dbms_stats的ALTER_DATABASE/SCHEMA_TAB_MONITORING过程或者create/alter table ... monitoring打开表的监控,在10g中,MONITORING与NOMONITORING关键字已经过时,如果你在create/alter table中指定表的监控或取消监控,该关键字将忽略,表监控特征被statistics_level控制,当statistics_level等于basic时,将禁止表的监控,如果等于typical或all时,表监控是激活的.

 查看全文

26 07, 2005
awr中baseline的意义
作者 xzh2000 19:24 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

awr中baseline的意义

 查看全文

26 07, 2005
10gR2中addmrpt的妙用
作者 xzh2000 16:17 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10g中,大家应该都知道addm是做什么的吧?如果不熟悉请去看看"Oracle Database 10 g : 为 DBA 提供的最佳前 20 位的特性",在$ORACLE_HOME/rdbms/admin目录中,addm产生报表的脚本有addmrpt.sql及addmrpti.sql,addmrpt.sql用于单实例,addmrpti.sql用于多实例.

测试请看如下所示:

 查看全文

26 07, 2005
10gR2中ashrpt的妙用
作者 xzh2000 16:09 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10gR2中,为了方便快捷地访问v$active_session_history字典表,当然也会访问与它相关的一些表,oracle提供了$ORACLE_HOME/rdbms/admin/ashrpt.sql及ashrpti.sql,其中ashrpt.sql是在单实例系统中运用,ashrpti.sql可以在多实例系统中运用.

 查看全文

26 07, 2005
10gR2中dbfusrpt的妙用
作者 xzh2000 15:58 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

你想知道你已经使用了数据库多少功能(模块)吗?$ORACLE_HOME/rdbms/adim/dbfusrpt.sql可以帮你完成这个问题.

 查看全文

26 07, 2005
10gR2中sqltrpt脚本的妙用
作者 xzh2000 15:50 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10gR2中,提供了$ORACLE_HOME/rdbms/admin/sqltrpt.sql脚本,用于抽取占用资源较多的sql,并可以为指定的sql生成执行计划,资源占用较多的sql分为两部分
1 15 Most expensive SQL in the cursor cache
2 15 Most expensive SQL in the workload repository

 查看全文

25 07, 2005
10gR2一个很严重的bug
作者 xzh2000 23:25 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

如果出将这个bug时,启动实例时报ORA-00600: [keltnfy-ldmInit], [46]错误,如果没有创建数据库,将无法创建数据库,同时sqlplus连接数据库会非常慢,这时大家可以用lsof去看sqlplus进程在干什么。

 查看全文

23 07, 2005
10gR2 Response-Time Analysis Made
作者 xzh2000 02:08 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Historically, in trying to achieve maximum database performance, Oracle DBAs and performance analysts have fought an uphill battle to obtain solid response time metrics for system as well as user session activity. The problem facing DBAs has always had two facets: first, determining exactly "where" the database or user sessions have been spending their time; and second, determining the objective nature of the user experience

 查看全文
23 07, 2005
10gR2.Top Features for DBA3(转贴)
作者 xzh2000 01:19 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Memory-attached SGA query (Arup's favorite Release 2 feature) tops this list, but optimizer statistics management, the new "compare periods" report, and other new features are equally compelling.

Covered in This Installment:
· Hung But Not Paralyzed: Memory-Attached SGA Query
· Interruptible SQL Access Advisor
· Check for Tracing Enabled
· Activity Session History
· Optimizer Statistics Management
· Transport AWR Data
· Compare Periods Report

 查看全文

21 07, 2005
10gR2中stream多源复制2
作者 xzh2000 18:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

上接

http://blog.itpub.net/post/96/35709

 查看全文

21 07, 2005
10gR2中stream多源复制1
作者 xzh2000 17:44 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

在10gR2中,oracle简化了stream的配置的全过程,在9iR2及10gR1中,需要针对stream的捕获、传播、应用进程进行配置的步骤已经被dbms_streams_adm新提供的过程(pre_instantiation_setup/post_instantiation_setup)给封装起来啦,配置stream只需要调用两个存储过程就可以搞定啦,真是太激动人心啦,下面给大家简单地介绍一下dbms_streams_adm的新过程的用法。

 查看全文

21 07, 2005
10gR2中关闭recyclebin?
作者 xzh2000 02:11 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

alter system set recyclebin=off;
alter system set recyclebin=on;


20 07, 2005
三联推荐的书,真多
作者 xzh2000 16:15 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
http://book.boxup.org/
20 07, 2005
10gR2,想说爱你不容易
作者 xzh2000 14:36 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

公司数据仓库在要换设备,选软件时用了rhel4.1+oracle10gR2,由于用了emc的存储,powerpath在2.9.11的内核下有点问题,最后只有选安装rhel3.4+oracle10gR2,但安装好rdbms后创建数据库时,报ora-600错误,拭了很多种方式,最后只有安装9204.

 查看全文
19 07, 2005
rootvg与odm库不同步[转]
作者 xzh2000 17:35 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

有台烂机(偶都不好意思说),想加一块硬盘作镜像。

 查看全文

16 07, 2005
non-unique index的index unique scan
作者 xzh2000 23:55 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

今天看了一个贴子,其中的问题是为什么non-unique index在产生的扫行计划中会出现index unique scan,大家知道,通常只有unique index才会产生index unique scan,non-unique index只能产生index range scan扫描,那为什么出现这种情况呢?

 查看全文

13 07, 2005
10gR2执行计划的变异
作者 xzh2000 18:35 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在10gR1及前的版本,用set autot on和explain plan for 产生执行计划的机制应该是不同的,在10gR2中,这种差异发生变化,10gR2统一了执行计划的生成方式,用set autot on和explain plan for产生执行计划是一样的.

 查看全文
11 07, 2005
10gR2 stream 新特征简报
作者 xzh2000 23:39 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

在近日发布的10gR2中,在stream方面,较10gR1有了很多不同,主要体现在如下方面:
stream性能增强
stream配置与管理增强
stream复制增强
stream规则接口增强
stream信息提供增强

real-time-downstream

 查看全文
10 07, 2005
10gR2.Top Features for DBA2(转贴)
作者 xzh2000 15:49 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

The Self-Managing Database becomes even more so with an Automatic Storage Management command-line tool, direct-attached SGA access, support for online partition redefinition, and more.

Covered in This Installment:
· ASM Command Line Tool
· Drop Empty Datafiles
· Direct SGA Access for Hung/Slow Systems
· Redefine a Partition Online
· Block Integrity Checking in Memory, Not Just on Disk
· Online Limit Changes
· Faster Startup
· Managing Multiple Objects in Oracle Enterprise Manager
· Automatic Segment Advisor
· Event-Based Scheduling

 查看全文
10 07, 2005
10gR2.Top Features for DBA1(转贴)
作者 xzh2000 15:45 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Part 1: SQL and PL/SQL Features

Transparent Data Encryption and XQuery support are the two major new SQL-related features in Oracle Database 10g Release 2, but the list doesn't end there.

Covered in This Installment:
· Transparent Data Encryption
· XML Query
· Enhanced COMMIT
· Error-Logging Clause
· WRAP Package
· Conditional Compilation
· Unlimited DBMS Output

 查看全文
08 07, 2005
aix培训第五天[aix管理基础]
作者 xzh2000 23:34 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
第十二章 备份与恢复
第十三章 系统安全性
第十四章 用户管理
第十五章 计划调度
第十六章 单机系统的可用性 查看全文
07 07, 2005
aix培训第四天[aix管理基础]
作者 xzh2000 21:43 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

今天进入aix培训第四天,讲师终于讲了一些有用的东西,对lvm的操作也有了点认识,虽然很多概念介绍的不深,但有个临时的测试环境也是好的,平时在生产库上什么都不敢做,现在可是想咋整就咋整。

第九章 LVM的管理维护
第十章 AIX的文件系统
第十一章 换页空间使用

 查看全文
07 07, 2005
如何删除primary dump设备
作者 xzh2000 18:10 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
如何删除primary dump设备?
在用rmps paging02时报错,
Before command completion, additional instructions may appear below.
0516-1251 rmlv: Warning, cannot remove logical volume paging02.
This logical volume is also used as the primary dump device.
Reset the dump device and retry the command.
0517-061 rmps: Cannot remove paging space paging02.
在sysdumpdev -l可以看到该设务为primary dump设备
sysdumpdev -l
primary /dev/paging02
secondary /dev/sysdumpnull
copy directory /var/adm/ras
forced copy flag TRUE
always allow dump FALSE
dump compression ON
用smitty sysdumpdev可以更改primary dump设备
# smitty sysdumpdev
# rmps paging02
06 07, 2005
aix培训第三天[aix管理基础]
作者 xzh2000 15:20 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

今天进入aix培训的第三天啦,渐渐新东西进来啦,而且有些命令记忆起来可不太容易啊,培训测试用的机器终于送来啦,有空自己安装几次来玩玩,用aix已经有两个多月了,基本上已经习惯aix不如linux操作方便这样的事实,aix为什么不多为用户考虑一下呢?

第五章 系统的启动与关闭
第六章 AIX的设备管理
第七章 打印机
第八章 AIX的存储管理

 查看全文
05 07, 2005
批量数据装载时索引处理
作者 xzh2000 15:27 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流
最近有个新项目,从老项目中迁移数据,由于新项目其实是从老项目重构的,所以表结构完全不同,但功能是差不多的,所以我在迁移这些数据时,先创建好表结构及索引,然后再用insert into select from的方式导入数据,发现在批量装入数据时,数据与索引的维护是分离的,开始装载数据时,索引表空间没有任何变化,当数据装载完毕后,索引表空间才开始变化,这样看来,那这样应该比insert into select from后再创建索引要更节省时间。
05 07, 2005
aix培训第二天[aix管理基础]
作者 xzh2000 15:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

第一章 AIX的管理概述
第二章 AIX的安装
第三章 系统管理工具
第四章 软件安装维护

 查看全文
04 07, 2005
如何创建这样的索引?
作者 xzh2000 23:27 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

这两个sql有很多的可选组合条件,只有forum_id是必选的,而且每种组合执行的都相当频繁,算下来为了满足这两个sql需要创建一个七列的组合索引,本来这个表才十多个字段,维护一个多列的组合索引的成本会很高吗?

其实如果对表结构进行优化的话,可以将动态组合的sql中的三个状态字段合并到一块,但设计时并没有被采用,还有一种思路是维护2个四列或五列的索引,但想想维护一个大索引应该比维护2个或多个小索引成本要低吧?

 查看全文

04 07, 2005
aix培训第一天[aix基础知识]
作者 xzh2000 22:56 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

本来基础课程安排3天时间,但由于偶们都有些linux/unix的基础,所以后来讲师就安排一天搞完了,实际上还讲课时间不到3个课时,现在越来越没有学习的感觉啦。

仔细地看了一下讲师给的电子教材,发现在网上已经流传的很广泛啦,不过这次培训还是比较放松的,一到公司,就有很多事情要处理,难得静一下。

很搞笑的事,今天停电两次,把培训用的测试p630搞坏了,还有就是这个培训老师很搞笑,上来也不自己介绍一下,就开始介绍课程安排及内容。

 查看全文
03 07, 2005
10gR1的stream初步研究
作者 xzh2000 13:58 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

http://blog.itpub.net/get/96/stream%20replication[v1.0].rar


23 06, 2005
aix上解压rhel的tar -zcvf?
作者 xzh2000 22:10 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

http://www.itpub.net/382632.html

谁知道,请帮忙!


23 06, 2005
让非root用户使topas
作者 xzh2000 21:52 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

#chomd o+r /dev/mem
$su - non root user
$topas

共有六台小机,其中五台是可以的,有一台报错:
pri:/home/oracle>$more topas.error
topas: Unable to initialize Spmi interface
Spmi: Unable to remove the unused Shared Area ( shmctl, error 1 )

TOPAS命令在使用时经常SPMI进程异常中断(死了),这时使用TOPAS时就会报以下错误:
topas: Unable to initialize Spmi interface
Spmi: Common Memory locked by process 288176, requestor: 41730 (SiInit)
出现这个错误是因为SPMI进程死了,该进程调用的内存没有释放,SPMI用的内存地址是 0x78XXXXXX 。
1、停止所有数据相关的进程
2、用ipcs -m 浏览内存使用情况
3、删除起始地址为0x78的共享内存(所有的0x78开始的内存)
#ipcrm -m ID
4、运行slibclean
这样内存可以释放,TOPAS应该可以用的


22 06, 2005
asktom关于v$open_cursor
作者 xzh2000 23:58 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

asktom关于v$open_cursor的解释
ops$tkyte@ORA817DEV.US.ORACLE.COM> select sql_text
from v$open_cursor
where user_name = user and sql_text like 'table%';
no rows selected
ops$tkyte@ORA817DEV.US.ORACLE.COM> create or replace type myTableType as table of number
/
Type created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> select sql_text
from v$open_cursor
where user_name = user and sql_text like 'table%';
SQL_TEXT
------------------------------------------------------------
table_1_0_10e_0_0_0

Ah-Hah -- there we go, we have that mysterious statement in there. Its all
about nested table types..
ops$tkyte@ORA817DEV.US.ORACLE.COM> create table t ( x int, y myTableType )
nested table y store as y_tab;
Table created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> select sql_text
from v$open_cursor
where user_name = user and sql_text like 'table%';
SQL_TEXT
------------------------------------------------------------
table_1_0_10e_0_0_0
table_1_0_116_0_0_0
table_1_0_112_0_0_0
and now we have MORE of them..
ops$tkyte@ORA817DEV.US.ORACLE.COM> insert into t values ( 1, myTableType( 1, 2,3 ) );
1 row created.
ops$tkyte@ORA817DEV.US.ORACLE.COM> select sql_text
2 from v$open_cursor
3 where user_name = user and sql_text like 'table%';
SQL_TEXT
------------------------------------------------------------
table_1_0_10e_0_0_0
table_1_0_116_0_0_0
table_1_0_112_0_0_0
ops$tkyte@ORA817DEV.US.ORACLE.COM>
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from t;
MYTABLETYPE(1, 2, 3)

ops$tkyte@ORA817DEV.US.ORACLE.COM> select sql_text
2 from v$open_cursor
3 where user_name = user and sql_text like 'table%';

SQL_TEXT
------------------------------------------------------------
table_1_0_10e_0_0_0
table_1_0_116_0_0_0
table_1_0_112_0_0_0

ops$tkyte@ORA817DEV.US.ORACLE.COM>

now, instead of just creating them and all, lets see what would happen day to day:

ops$tkyte@ORA817DEV.US.ORACLE.COM> disconnect
Disconnected from Oracle8i Enterprise Edition Release 8.1.7.2.0 - Production
With the Partitioning option
JServer Release 8.1.7.2.0 - Production
ops$tkyte@ORA817DEV.US.ORACLE.COM> connect /
Connected.
ops$tkyte@ORA817DEV.US.ORACLE.COM> select sql_text
2 from v$open_cursor
3 where user_name = user and sql_text like 'table%';

no rows selected

ops$tkyte@ORA817DEV.US.ORACLE.COM> save a rep
Wrote file a
ops$tkyte@ORA817DEV.US.ORACLE.COM> select * from t;

1 MYTABLETYPE(1, 2, 3)

ops$tkyte@ORA817DEV.US.ORACLE.COM> @a
ops$tkyte@ORA817DEV.US.ORACLE.COM> select sql_text
from v$open_cursor
where user_name = user and sql_text like 'table%'

SQL_TEXT
------------------------------------------------------------
table_1_0_10e_0_0_0
table_1_0_116_0_0_0
table_1_0_112_0_0_0

so, they are a natural side effect of using nested tables. Now, why are the
"open" -- well, they use the same cursor sharing technique as PLSQL does. In PLSQL when you close a cursor -- it'll still (most likely) be there in v$open_cursor which should really be called "v$MOST_LIKELY_STILL_open_cursor" --
the cursors for the nested table access are still there but -- they are
replaceable -- they will go away if someone else needs that slot (eg: they do not count against your open_cursor init.ora setting)

So, thats the mystery here, they are implicit sql (magic sql apparently) to do with nested table types. They will go away as their slots are needed, they are not "leaked" cursors (which is probably what you were looking for).


22 06, 2005
你是如何解决失眠的
作者 xzh2000 23:04 | Permalink 静态链接网址 | Comments 最新回复 (6) | Trackback 引用 (0) | 技术交流
失眠伴随我有段时间了,一下班后特累,然后就想休息一下,然后就是看看电脑,与朋友聊天,或者看看系统的监控报表,或者去网易下围棋,然后玩到十一点多才去冲凉,冲凉后精神大振,更不想休息啦,结果每次都三点多才睡,有时根本就没有睡意,上班时精神特差?你有什么好的消除失眠的好办法吗?我想了很久,发现如果下班回来就冲凉,然后玩电脑或者看书,累了就休息,这样睡得时间比以前也多一些,上班时精神也会好很多。
22 06, 2005
ORA-02019的解决办法
作者 xzh2000 10:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
1) set transaction use rollback segment system
(this is VERY important, otherwise database loss can occur)
(2) select * from dba_2pc_pending where state='collecting';
(3) for each local_tran_id in selected rows, delete where local_tran_id is that value from the following tables:
dba_2pc_pending
pending_sessions$
pending_sub_sessions$
19 06, 2005
10gR1stream的ora-25228
作者 xzh2000 02:13 | Permalink 静态链接网址 | Comments 最新回复 (5) | Trackback 引用 (0) | 技术交流
前天在10gR1(10.1.0.3)中做stream复制数据的实验时,死活都不能成功,同样的方法在9.2.0.4/9.2.0.6中都是成功的,后来决定将10.1.0.3升级到10.1.0.4,升级之后同样的方式就可以实现数据复制啦,但在alert.log中发现了很多的ORA-25228错误,查metalink竟然也没有找到答案,经d.c.b.a证实,该问题是10.1.0.4的bug,在10.1.0.4.99中fixed,还好该错误只能算一个警告,就是太多了点。
18 06, 2005
Stream结构的设计与规划
作者 xzh2000 20:18 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Stream结构的设计与规划

在单源复制结构中,stream结构的设计与规划,不需要考虑标识冲突,源库中出版对象的唯一索引将解决此类问题;在多源复制结构中,stream结构的设计与规划,不仅要考虑数据延迟问题、系统性能问题以及标识冲突问题。

 查看全文
17 06, 2005
Stream在10gR1的新特征
作者 xzh2000 23:35 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

10gR1stream replication的新特征主要集中在五个方面:stream性能、stream配置与管理、stream replicationstream messaging以及rule interfaces等,这些功能的增强,使stream replication在企业数据复制市场有更大作为。

 查看全文
17 06, 2005
Stream功能介绍
作者 xzh2000 23:34 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Stream功能介绍

信息共享促使企业利用各种技术把核心数据从它们的数据库中抽取出来,许多关键的商业企业需要更成熟、统一的方案,该数据抽取方案应具有充分的灵活性以适应商业企业高速发展所带来的变化,同时最大程度地降低企业的投资。

 查看全文
17 06, 2005
Stream/Standby/Rep对比
作者 xzh2000 23:24 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

dataguard在高可用及容灾方面一般是dba的首选,毕竟dataguard在这方面存在压倒性的优势,不管是物理备用库(physical standby database)还是逻辑备用库(logical standby database),它们都具有一些共同的待征。

 查看全文
15 06, 2005
在10gR1中清除stream环境
作者 xzh2000 16:53 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

清除stream replication环境

9iR2中,若要清除stream replication环境,将是一种较复杂的工作,很可能会在数据字典中留下一些垃圾数据;在10gR1中,清除stream replication环境是一种很简单的工作,只需要调用dbms_streams_admremove_streams_configuration过程。


15 06, 2005
9iR2中清除stream环境
作者 xzh2000 16:44 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

http://forums.oracle.com/forums/thread.jsp?forum=70&thread=233527&message=663207

Use this script to generate the cleanup script...I have used it in our test environment...

 查看全文

15 06, 2005
解释latch free产生的原因
作者 xzh2000 16:35 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Wait Event Enhancements in Oracle 10g

http://www.dbspecialists.com/presen...events_10g.html

很好地解释了latch free产生的一个原因.


09 06, 2005
开始脑筋,优化竟如此简单
作者 xzh2000 19:12 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

开始脑筋,优化原来如此简单
SELECT COUNT(*)
FROM BMW_ABCD t
WHERE t.USER_NICK = :1 AND t.ACTION_ID = :2;

下面显示的是表的结构与索引情况,很明显,该表的USER_NICK字段没有索引,
ACTION_ID虽然有索引,但它不是组合索引的前导字段,所以这个sql必然会全表扫描,
即使通过hints让action_id走组合索引进行跳跃扫描的话,性能也不会很好,
由于通过user_nick进行扫描的查询不多,没有必要为这个字段创建索引,
但可以与bmw_XYZ表做关联
11:52:35 SQL> desc bmw_abcd
Name Null? Type
----------------------------- -------- ----------------
ID NOT NULL NUMBER(11)
USER_NICK NOT NULL VARCHAR2(32)
USER_ID NOT NULL VARCHAR2(32)
ACTION_ID NUMBER(8)
....

11:51:07 SQL> @list_index
Enter value for table_name: bmw_abcd
INDEX_NAME COLUMN_NAME COLUMN_POSITION STATUS TABLESPACE_NAME
------------------------------ ------------------------------
IND_BMW_ABCD_USER_ACTION_ID USER_ID 1 VALID TBS_INDEX1
IND_BMW_ABCD_USER_ACTION_ID ACTION_ID 2 VALID TBS_INDEX1

12:13:52 SQL> explain plan for SELECT COUNT(*) FROM BMW_ABCD t
WHERE t.USER_NICK = :1 AND t.ACTION_ID = :2;
12:13:58 SQL> @plan
PLAN_TABLE_OUTPUT
----------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
----------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 101 | 3705 |
| 1 | SORT AGGREGATE | | 1 | 101 | |
|* 2 | TABLE ACCESS FULL | BMW_ABCD | 429 | 43329 | 3705 |
-----------------------------------------------
新修改后的sql如下所示,执行计划相当好.
SELECT COUNT(*)
FROM BMW_ABCD t,BMW_USERS bu
WHERE bu.NICK = :1 AND t.user_id = bu.id AND t.ACTION_ID = :2
-----------------------------------------------


09 06, 2005
每天执行较少次数sql的优化
作者 xzh2000 15:40 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
update tbf_thread
set thread_type = 3
where thread_type <> 3 and
((valid_start_date is null and sysdate - creation_date > 90) or
(valid_start_date is not null and sysdate - valid_start_date > 90))
拿到这个sql后,由于表是我创建的,知道这个表上在thread_type字段上有索引,
该索引的取值是1,2,3,但99%的贴子集中在3上面,第一印象看,需要将<>3改为<3,
这样就会走thread_type,实际测试后,发现从7分钟减少到45second,但由于该表
的访问相当频繁,但这个sql执行频繁却不高,每天一次,如果在一次作业过程中,
产生大量的锁也是很讨厌的,然后再分析表结构,发现valid_start_date是设计时
就不允许为空,所以可以精简为如下所示.
update tbf_thread
set thread_type = 3
where thread_type < 3 and
(sysdate - creation_date > 90 or sysdate - valid_start_date > 90)
由于目前这个表的tbf_thread的creation_date与valid_start_date都没有索引,所以
不管它怎么写都是一样的,但如果考虑到后来会创建索引或者为了符合一般的sql编写
规范的话,还可以继续改为如下所示.
update tbf_thread
set thread_type = 3
where thread_type < 3 and
(creation_date < sysdate - 90 or valid_start_date < sysdate - 90)
到为这个步聚,就已经比较明了啦,然后分析业务,发现可以将create_date这个条件去
掉,然后就成最终的sql语句啦,按将来的业务看,每次执行时要更新10w甚至更多些的的
记录,根据我们的访问量,即使在1分钟内完成,也会产生大量的锁.
update tbf_thread
set thread_type = 3
where thread_type < 3 and valid_start_date < sysdate - 90
为了彻底地减少锁,将这个sql用pl/sql来实现,批量进行提交,虽然效率降低了,但系统
的锁可以尽大限度地消除lock:
create or replace procedure sp_update_thread(v_count number default 200)
as
cursor cur_threads is select thread_id
from tbf_thread where thread_type < 3 and valid_start_date < sysdate - 90;
begin
for cur_row in cur_threads loop
update tbf_thread set thread_type=3 where thread_id = cur_row.thread_id;
if mod(cur_threads%rowcount,v_count) = 0 then
commit;
end if;
end loop;
commit;
end;

09 06, 2005
logminer在10g的一个改进
作者 xzh2000 11:38 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
logminer在10g的一个改进
当你在10g中执行dbms_logmnr_d的set_tablespace('&ts_name')过程后,
你可以到alter_sid.log中看看,你会发现一些输出信息,与logminer相关
的字典表的索引失效,系统会监控并写入alert_sid.log,然后会对这些字
共表的失效索引进行rebuild,比9i要更人性化一些.
Some indexes or index [sub]partitions of table SYSTEM.LOGMNR_ATTRCOL$ have been marked unusable
...
Indexes of table SYSTEM.LOGMNR_ATTRCOL$ have been rebuilt and are now usable

09 06, 2005
10gskip_unusable_indexes参数及其意义
作者 xzh2000 11:16 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

10g的一个新花样:skip_unusable_indexes
关于skip_unusable_indexes这个参数,大家从它的名称就基本上可以理解它是做什么的,但在使用时需要注意一个小问题,非唯一索引在失效(unusable)状态是允许继续对表进行DML操作,但唯一索引在失效状态是不允许DML操作.

这个富有人性化的改进可以避免因为dba的失误而导致很多事务回退,当dba对表进行move操作时,如果表上没有唯一索引,那我们在move时,就不必担心事务回退,所以如果有些表如果insert/delete非重频繁的话,最好不要创建唯一索引.

10g中加强了对unusable索引的监控,如果你move了表,这时将会在alert日志中记录如下信息:Some indexes or index [sub]partitions of table SCOTT.DEPT have been marked unusable


07 06, 2005
9206设set autot on生成执行计划太慢
作者 xzh2000 17:32 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

aix5.2上安装oracle9206,8CPUx32G RAM

16:35:17 SQL> set autot on
16:35:21 SQL> select sysdate from dual;
SYSDATE
-------------------
2005-06-07 16:35:31
1 row selected.
Elapsed: 00:00:02.83
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE
1 0 TABLE ACCESS (FULL) OF 'DUAL'
16:35:33 SQL> set autot off
16:35:40 SQL> select sysdate from dual;
SYSDATE
-------------------
2005-06-07 16:35:45
1 row selected.
Elapsed: 00:00:00.00
16:35:45 SQL> set autot on
16:35:50 SQL> select count(*) from v$session;
COUNT(*)
----------
875
1 row selected.
Elapsed: 00:00:02.89
16:35:59 SQL> set autot off
16:36:04 SQL> select count(*) from v$session;
COUNT(*)
----------
873
1 row selected.
Elapsed: 00:00:00.00

如果在9206中打开set autot on选项,执行时间竟然要2-4s,太过分啦,在metalink上发了tar,竟然是oracle在北京的客服MM打电话过来,感觉oracle的服务越来越好啦.但需要说明的:explain plan for +dbms_xplan显示执行计划时是正常的.


06 06, 2005
ibm的小机p590也会挂的
作者 xzh2000 21:53 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
今天是个比较特珠的日子,p590第一次挂了,真是搞笑, 当时是ibm的工程师在做测试,跑一个脚本,跑着跑着, 网站中有一些页面已经打不开啦,然后在topas中看到disk busy是100%, 再后来就不能登陆,只好从hmc重启...... 看得出来,ibm的工程师很不爽的,运行了多少年的脚本, 怎么一下子就这么挂了呢.
06 06, 2005
感觉ibm的hmc产品很烂的
作者 xzh2000 21:38 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

感觉ibm的hmc的产品很烂的,
偶公司有三台ibm p590,竟然需要三个hmc的终端去管理,
难道一个hmc的终端不能管理多台主机吗?


02 06, 2005
表move后索引还可以用吗?
作者 xzh2000 20:16 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

如果表中有数据,在执行alter table &table_name move tablesapce &tbs后,索引将失效,如果表中没有数据,索引不会失效.

select count(*) from TBF_POINT_balance;

  COUNT(*)
----------
         0

SQL> alter table tbf_point_balance move;

Table altered.

SQL> @list_index
Enter value for table_name: tbf_point_balance

PL/SQL procedure successfully completed.


INDEX_NAME                     COLUMN_NAME                    COLUMN_POSITION STATUS   TABLESPACE_NAME
------------------------------ ------------------------------ --------------- -------- --------------------
PK_POINT_BALANCE_BALANCE_ID    BALANCE_ID                                   1 VALID    TBS_FORUM


CONSTRAINT_NAME                C COLUMN_NAME                      POSITION STATUS   VALIDATED
------------------------------ - ------------------------------ ---------- -------- -------------
PK_POINT_BALANCE_BALANCE_ID    P BALANCE_ID                              1 ENABLED  VALIDATED

SQL> select count(*) from tbf_userperm;

  COUNT(*)
----------
         6

SQL> alter table tbf_userperm move;

Table altered.

SQL> @list_index
Enter value for table_name: tbf_userperm                 

PL/SQL procedure successfully completed.


INDEX_NAME                     COLUMN_NAME                    COLUMN_POSITION STATUS   TABLESPACE_NAME
------------------------------ ------------------------------ --------------- -------- --------------------
PK_USERPERM_USERPERM_ID        USERPERM_ID                                  1 UNUSABLE TBS_FORUM


CONSTRAINT_NAME                C COLUMN_NAME                      POSITION STATUS   VALIDATED
------------------------------ - ------------------------------ ---------- -------- -------------
PK_USERPERM_USERPERM_ID        P USERPERM_ID                             1 ENABLED  VALIDATED


01 06, 2005
rhel3下raw devices与基于lvm的raw devices的区别
作者 xzh2000 16:36 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

linux下raw device的用法
#fdisk /dev/sdb
raw /dev/raw/raw1 /dev/sdb1
raw /dev/raw/raw2 /dev/sdb2
...
如果想在每次启动时都绑定到RAWn,需要做如下操作
vi /etc/sysconfig/rawdevices
/dev/raw/raw1 /dev/sdb1
/dev/raw/raw2 /dev/sdb2

linux下基于lvm的raw device的用法
lvcreate -L 2000M -n lv_user_01 vg_db
lvcreate -L 2000M -n lv_user_02 vg_db
...
raw /dev/raw/raw1 /dev/vg_db/lv_user_01
raw /dev/raw/raw2 /dev/vg_db/lv_user_02
如果想在每次启动时都绑定到RAWn,需要做如下操作
vi /etc/rc.d/rc.local
raw /dev/raw/raw1 /dev/vg_db/lv_user_01
raw /dev/raw/raw2 /dev/vg_db/lv_user_02
也就是说,基本lvm的raw在机器重启后,绑定到raw的方法稍有不同.


31 05, 2005
笑谈2050年前中国空军战机前瞻[转贴]
作者 xzh2000 18:33 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

以胡锦涛为总书记的党的四代领导集体,提出要把我国建设成为高度文明,高度和谐的社会主义强国.要实现这一伟大目标,就必须拥有一支可与世界最大霸权国家相抗衡的武装力量.其中,空军力量尤为重要,它的强弱,决定了我国未来的空天安全.为此,党中央提出了国防建设与社会经济建设相协调发展的方针.在这一方针指引下,国防投资力度逐年增加,特别是对空军发展的投资力度,增加最快,并批准了一批事关我国空天安全的重大装备项目.为我空军装备持续的和跨越式的发展,打下了坚实的基础.

 查看全文

27 05, 2005
昨天犯了一个错误,呜呜呜
作者 xzh2000 15:44 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

昨天在为生产数据库添加数据文件时,在创建好lv后,用ln链接等,都做好后,

添加数据文件,不小心写错了一个数字,结果把数据文件添加到了本地文件

系统中,呜呜呜.

发现问题后,立即想把这个数据文件offline,然后dd到lv中去,然后再rename,

在dba_extents查了一下,发现已经有对象扩展到该数据文件上啦,看来只有

在下个月做维护时再move到存储中去.


27 05, 2005
ORA-02062: distributed recovery处理办法
作者 xzh2000 15:27 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
(1) set transaction use rollback segment system
(this is VERY important, otherwise database loss can occur)
(2) select * from dbc_2pc_pending where state='collecting';
(3) for each local_tran_id in selected rows, delete where local_tran_id is that value from the following tables:
dba_2pc_pending
pending_sessions$
pending_sub_sessions$

25 05, 2005
ORA600 [729] UGA Space Leak[metalink]
作者 xzh2000 04:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Note: For additional ORA-600 related information please read Note 146580.1

PURPOSE:           
  This article discusses the internal error "ORA-600 [729]", what
  it means and possible actions. The information here is only applicable
  to the versions listed and is provided only for guidance.

ERROR:             
  ORA-600 [729] [a]

VERSIONS:          
  versions 7.0 to 10.1

DESCRIPTION:       

  A space leak has been detected in the User Global Area (UGA).

  There is NO data corruption as a result of this error.

  It is an internal memory housekeeping problem.

ARGUMENTS:
  Arg [a] This is the number of bytes leaked

FUNCTIONALITY:     
  MEMORY COMPONENT

IMPACT:            
  PROCESS FAILURE - But only during logoff so impact is minimal.
  NON CORRUPTIVE - No underlying data corruption.


SUGGESTIONS:       

  Event 10262 can be set to safely ignore small memory leaks.

  Set the following in init.ora for example to disable space
  leaks less than 4000 bytes:

        event = "10262 trace name context forever, level 4000"

  and stop and restart the database.

  Repeated errors or large memory leaks can be diagnosed further by
  sending the alert.log and trace files to Oracle support.

  Please note that if you are running Oracle 8.1.7.3, then there is every
  chance that you have encountered
Bug 2177050. The workaround is to
  Set EVENT 10262 with a LEVEL of 102400.

  Known Issues:

  Bug# 3216432   See
Note 3216432.8
      PLSQL using recursive calls which open cursors may get OERI:KGIFLPUSH / 17278 / 17277
      Fixed: 9.2.0.6, 10.1.0.2

  Bug# 2887209   See
Note 2887209.8
      UGA memory leak / OERI:729 with failed shared database link connection
      Fixed: 9.2.0.7, 10.1.0.2

  Bug# 2884469   See
Note 2884469.8
      OERI[729] possible using literal replacement
      Fixed: 9.2.0.4, 10.1.0.2

  Bug# 2782196   See
Note 2782196.8
      ORA-3106 / OERI:729 after CTRL-C of INSERT..SELECT via a DBLINK
      Fixed: 9.2.0.4, 10.1.0.2

  Bug# 2678481   See
Note 2678481.8
      OERI[729] possible on SHUTDOWN
      Fixed: 9.2.0.3, 10.1.0.2

  Bug# 2537917   See
Note 2537917.8
      OERI:729 possible with XDB
      Fixed: 9.2.0.3

  Bug# 2295845   See
Note 2295845.8
      OERI:729 if TRUNCATE PARTITION / ALTER TABLE MODIFY COLUMN interrupted
      Fixed: 9.0.1.4, 9.2.0.2, 10.1.0.2

  Bug# 2177050   See
Note 2177050.8
      OERI:729 space leak possible (with tags "define var info" / "oactoid info")
      Fixed: 8.1.7.4, 9.0.1.0

  Bug# 2028564   See
Note 2028564.8
      ORA-7445 or OERI:17114 errors possible after OERI:729 - PMON may die
      Fixed: 9.0.1.4, 9.2.0.2, 10.1.0.2

  Bug# 1731079   See
Note 1731079.8
      OERI:729 space leak possible
      Fixed: 9.0.1.4, 9.2.0.1

  Bug# 1712645   See
Note 1712645.8
      OERI:729 space leak possible if DROP COLUMN is interrupted
      Fixed: 8.1.7.3, 9.0.1.1, 9.2.0.1

  Bug# 1674074   See
Note 1674074.8
      Leak of "ktatt" memory chunks possible (OERI:729) on failed creation of a TEMP segment
      Fixed: 9.2.0.1

  Bug# 1573524   See
Note 1573524.8
      OERI:729 / OERI:kghxhdr1 using DEFERRED TRANSACTION PROPAGATION with AUDITING enabled
      Fixed: 8.1.7.2, 9.0.1.0

  Bug# 1366596   See
Note 1366596.8
      Leak of "kgbt" memory chunks possible (OERI:729) on failed creation of a TEMP LOB
      Fixed: 9.0.1.0

  Bug# 918272   See
Note 918272.8
      OERI:729 memory leak when AUDIT_TRAIL=TRUE
      Fixed: 8.0.6.2, 8.1.6.2, 8.1.7.0

  Bug# 744179   See
Note 744179.8
      OERI:729 from shared server using DB Links at logoff
      Fixed: 7.3.4.5, 8.0.5.2, 8.0.6.0, 8.1.5.1

  Bug# 690413   See
Note 690413.8
      OERI:729 possible from failed direct export
      Fixed: 8.0.4.4, 8.0.5.2, 8.0.6.0

  Bug# 410215   See
Note 410215.8
      ORA-600 [729] [493888], [SPACE LEAK] after DIRECT LOAD
      Fixed: 7.3.3.1, 7.3.4.0

24 05, 2005
中国舰载导弹垂直发射系统跻身世界[转贴]
作者 xzh2000 23:39 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
近期出版的《汉和防务评论》将正在大连制造的中国051C大型导弹驱逐舰誉为“中华神盾舰”。“神盾”的称谓来自大名鼎鼎的美国“宙斯盾”舰载多任务区域攻防一体系统,它是构成美国航母编队防空/反导防御系统的核心和支柱,也是世界上最先进的舰载防御系统。
 查看全文
24 05, 2005
中国海洋机器人争雄美航母舰队[转贴]
作者 xzh2000 23:36 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
北星计划:海洋机器人争雄美航母舰队

  德国明镜周刊日前报道,美国中情局一官员透露出惊人消息,中国很可能在实行一项革命性的对抗航母的计划,其主角就是是中国近期十分重视的海洋机器人系统。
 查看全文
18 05, 2005
Tuning RHEL on xSeries
作者 xzh2000 22:29 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

http://www.redbooks.ibm.com/redpapers/pdfs/redp3861.pdf

Abstract Linux is an open source operating system developed by people all over the world.
The source code is freely available and can be used under the GNU General Public License.
The operating system is made available to users in the form of distributions from companies such as Red Hat.
Whereas some desktop Linux distributions can be downloaded at no charge from the Web,
the server versions typically must be purchased. IBM has embraced Linux,
and it is now recognized as an operating system suitable for enterprise-level applications running on IBM eServer xSeries servers.
Most enterprise applications are now available on Linux as well as Microsoft Windows,
including file and print servers, database servers, Web servers, and collaboration and mail servers.
With the use in an enterprise-class server comes the need to monitor performance and, when necessary,
tune the server to remove bottlenecks that affect users.
This IBM Redpaper describes the methods you can use to tune Red Hat Advanced Server,
tools you can use to monitor and analyze server performance,
and key tuning parameters for specific server applications.
Table of Contents Chapter
1. Tuning the operating system Chapter
2. Tuning tools Chapter
3. Analyzing performance bottlenecks Chapter
4. Tuning Apache Chapter
5. Tuning database servers Chapter
6. Tuning Samba for file and print Chapter
7. Tuning LDAP Chapter
8. Tuning Lotus Domino


18 05, 2005
Hidden Benefits of 10g
作者 xzh2000 09:39 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Hidden Benefits of 10g

by Jonathan Lewis

There are various features of Oracle 10g that get all the publicity and press, and for many people, the decision to migrate is driven by whether or not they happen to see anything in the high-profile features that might be useful.

 查看全文
18 05, 2005
取系统中FTS/FFSI/FSI的sql
作者 xzh2000 09:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

 set lines 121
 set pages 999
 col opname format a29
 col target format a29
 col target_desc format a12
 col perwork format a12
 col remain format 99
 col elapsed format 9999
 col start_time format a21
 col sofar format 99999999
 col totalwork format 99999999
 col sql_text format a101

 select opname,target,to_char(start_time,'yy-mm-dd:hh24:mi:ss') start_time,elapsed_seconds elapsed,buffer_gets/decode(executions,0,1,executions) bufgets,sql_text
 from v$session_longops sl,v$sqlarea sa
 where sl.sql_hash_value = sa.hash_value;


17 05, 2005
connect+level+dual的妙用
作者 xzh2000 14:54 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

1. In Sql*Plus (9.2.0.4 EE):

SQL> select *
2 from (select level from dual connect by level < 10);

LEVEL
----------
1
2
3
4
5
6
7
8
9

9 rows selected.

SQL> select level from dual connect by level < 10;

LEVEL
----------
1

 查看全文
15 05, 2005
东风四十一洲际导弹揭密
作者 xzh2000 15:04 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

二炮部队具备完整战术与战略导弹打击能力。中共对台部署500-550枚导弹。1995年开始将专供M-9/11导弹瞄准台湾,希望一举瘫痪系统关键节点。二炮兵力约13万人,有8个军级基地。部署19-23个导弹旅。未来导弹发展趋势在加装定位系统;战略导弹小型化;缩短发射准备时间;发展多弹头、诱饵助推火箭与弹头诱饵。

 查看全文

12 05, 2005
数据库管理员的职责[转贴]
作者 xzh2000 12:41 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

数据库管理员的职责:

一、 一般监视
1. 监控数据库的警告日志。Alert<sid>.log,定期做备份删除。
2. Linstener.log的监控,/network/admin/linstener.ora。
3. 重做日志状态监视,留意视图v$log,v$logfile,该两个视图存储重做日志的信息。
4. 监控数据库的日常会话情况。
5. 碎片、剩余表空间监控,及时了解表空间的扩展情况、以及剩余空间分布情况,如果有连续的自由空间,手工合并。
6. 监控回滚段的使用情况。生产系统中,要做比较大的维护和数据库结构更改时,用rbs_big01来做。
7. 监控扩展段是否存在不满足扩展的表。
8. 监控临时表空间。
9. 监视对象的修改。定期列出所有变化的对象。
10. 跟踪文件,有初始化参数文件、用户后台文件、系统后台文件

 查看全文
12 05, 2005
数据库管理员是什么[转贴]
作者 xzh2000 12:33 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流
数据库管理员是什么

  数据库管理员,英文是Database Administrator,简称DBA。这个职位对不同的人意味着不同的意义。一个小的软件开发工作室和一个分工高度明细的大公司相比,DBA的职责来得更加宽泛一些。一个公司,不管它是自己开发应用软件,还是购买第三方的应用软件,只要涉及到数据库(有多少不涉及数据库的应用软件呢?数据库是商业的灵魂和大脑啊),就需要确定是否雇佣一个或几个DBA。知道DBA这个职位有哪些要求,对于企业内部这个职位的定义或者对于那些未来的DBA将是至关重要的。

 查看全文

12 05, 2005
红帽企业版官方中文文档
作者 xzh2000 11:06 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
1 红帽群集套件配置和管理群集
 http://www.dvdshop.com.cn/manual/redhat_AS_3.0_CS/
2 红帽企业Linux4各体系的安装指南
 http://www.dvdshop.com.cn/manual/rhel-ig-x8664-multi-zh_cn-4/
3 红帽企业Linux4安全指南
 http://www.dvdshop.com.cn/manual/rhel-sg-zh_cn-4/
4 红帽企业Linux4用于IBM体系的安装指南
 http://www.dvdshop.com.cn/manual/rhel-ig-s390-multi-zh_cn-4/
5 红帽企业Linux4系統管理導論
 http://www.dvdshop.com.cn/manual/rhel-isa-zh_tw-4/

09 05, 2005
RHEL4关闭SELinux的方法
作者 xzh2000 14:51 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

起初是因为Apache不能认到/var/www以外目录的问题才了解到SELinux的。
在网上找了很多怎么关掉SELinux的文档,如:"在system-config-securitylevel把selinux关掉就可以了"。但都不正确。
RHEL4上关掉SELinux的正确方法为:
修改/etc/selinux/config文件中的SELINUX="" 为 disabled
然后重启。


28 04, 2005
视图中指定基表索引的方法
作者 xzh2000 13:33 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
视图中指定基表索引的方法
ADDRESS          HASH_VALUE DISK_READS elapsd_tm(s)    BGETS_PER EXECUTIONS FIRST_TIME
07000003B6D5ABE0 4264756908  190970.00  1082.47    486897.00     1 2005-04-28/12:10:26
select count(*)
 from bmw_users bu
where bu.user_regdate > to_date('2004-04-16','YYYY-MM-DD')
 and substr(user_from,instr(user_from,'<-||->')+6) in ('1205','1207','1336')
发现数据库中一个后台查询,执行了很久,其中bmw_users是一个视图.union all两个mv.
用explain plan查看它的执行计划,发现针对两个基本是全表扫描,而user_regdate上已
经创建了索引.
------------------------------------------------------------------------
| Id  | Operation             |  Name          | Rows  | Bytes | Cost  |
------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |                |     1 |   260 | 45228 |
|   1 |  SORT AGGREGATE       |                |     1 |   260 |       |
|   2 |   VIEW                | BMW_xxxxx      |  2309 |   586K| 45228 |
|   3 |    UNION-ALL PARTITION|                |       |       |       |
|*  4 |     TABLE ACCESS FULL | BMW_xxxxx_DB1  | 34762 |  8826K| 22615 |
|*  5 |     TABLE ACCESS FULL | BMW_xxxxx_DB2  | 34773 |  8829K| 22615 |
------------------------------------------------------------------------
添加hints如下所示:
select /*+ index(bu ind_db1_regdate ind_db2_regdate) */ count(*)
 from taobao.bmw_xxxxx bu
where bu.user_regdate > to_date('2004-04-16','YYYY-MM-DD')
 and substr(bu.user_from,instr(bu.user_from,'<-||->')+6) in ('1205')
用explain plan查看修改后的sql的执行计划:
----------------------------------------------------------------------------------
| Id  | Operation                      |  Name            | Rows  | Bytes | Cost  |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |                  |     1 |   260 | 83769 |
|   1 |  SORT AGGREGATE                |                  |     1 |   260 |       |
|   2 |   VIEW                         | BMW_xxxxx        |  2309 |   586K| 83769 |
|   3 |    UNION-ALL PARTITION         |                  |       |       |       |
|*  4 |     TABLE ACCESS BY INDEX ROWID| BMW_USERS_DB1    | 34762 |  8826K|  1289K|
|*  5 |      INDEX RANGE SCAN          | IND_DB1_REGDATE  |  3476K|       |  8496 |
|*  6 |     TABLE ACCESS BY INDEX ROWID| BMW_USERS_DB2    | 34773 |  8829K|  1233K|
|*  7 |      INDEX RANGE SCAN          | IND_DB2_REGDATE  |  3477K|       |  8662 |
----------------------------------------------------------------------------------
27 04, 2005
AIX 使用心得[转贴]
作者 xzh2000 20:16 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
AIX是IBM公司开发的业界领先的优秀商务Unix操作系统,在可靠性、可用性、开放性、扩展性、高性能、安全性等方面都非常突出,尤其是在Internet的关键应用领域以及系统和硬件管理能力方面,其性能表现更为出色,受到了业界的普遍认可和广泛使用。以下是笔者几年来使用AIX系统的一点心得,兹供使用该系统的其他读者参考。

1.如何禁止终端上的中断键(CTRL+C)?
在很多应用系统中,系统管理员希望普通用户只运行自己的应用程序,不能进入系统的shell提示符下,但缺省情况下当用户在终端上按CTRL+C键时就会退到系统提示符下。由于用户终端一般没有固定的端口号,为了禁止使用中断键,可采取下面办法:
(1)如果使用ksh, 可在$HOME/.profile中第一行加入如下内容:
trap "echo 'Abnormal operation'; exit" 123915
(2)如果使用csh(ksh亦可),可用如下命令:
%stty intr ^!
如果恢复正常情况,键入下列命令:
% stty intr ^c

2.如何在shell中不回显(echo)字符?
在实际应用中,一般当我们在键盘上键入口令时不希望将其显示在屏幕上,为此可采用下面的两种办法:
·使用stty 命令
stty -echo # do not display password
echo "Enter password: c"
read PASSWD #get the password
stty echo # restore standard configuration
·使用echo命令
设置保密属性:echo "33[8m"
取消保密属性:echo "33[m"

3.如何在某个目录及其所属子目录的所有文件中查找字符串?
在程序维护过程中,有时需要在某个目录及其所属子目录的所有文件中查找某一个字符串,为此可用下面两种方法(假设在*.cp文件中查找字符串"abc",结果放在文件out中):
(1)cat /dev/null > out
find ./ -name "*.cp" -exec grep "abc"{} >> out
(2)find ./ -name "*.cp" | xargs grep "abc" > out
推荐使用第二种方法,因其系统开销小、速度快。

4.如何对/etc/inittab文件中的一行进行注释?
我们都知道在shell中使用"#"作为注释符号,但在/etc/inittab中注释一行的方法是在第一个字符前插入字符":"。

5.如何转换DOS和AIX两种格式的文本文件?
如欲转换DOS和AIX两种格式的文本文件,有两种方法:
(1)用ftp命令:设置ASCII传输类型,在一台运行AIX的机器和另外一台运行Windows的机器之间互相传送,这里不再赘述。
(2)使用aix2dos或dos2aix命令
如将DOS格式的文本文件转换为AIX格式,可用命令A:dos2aix inputfile outfile,反之可用命令:aix2dos inputfile outfile,关于dos2aix和aix2dos命令的详细用法可参阅"dos2aix -h "和"aix2dos -h "。注意要使用这两个命令,必须首先安装文件集bos.pci。

6.如何解决某一PV上的VGDA与ODM库不一致的问题?
在系统维护过程中,因为操作错误或其他特殊原因,有可能使某一PV上的LVCB和VGDA与其对应的ODM库不一致,导致ODM库紊乱,对PV的有关操作无法进行,这时可采用如下两个AIX命令加以解决:
redefinevg -d hdisk_name vg_name
该命令以指定PV上的LVM信息重新定义给定VG的ODM库。
或:synclvodm -P -v vgname
该命令同步或重建给定VG的ODM库和LVM信息。

7.如何设置用户的文件大小限制?
在AIX系统中,用户使用系统资源是有一定限制的。如用户缺省可创建或扩展的最大文件为1G(参见/etc/security/limits: fsize = 2097151, fsize_hard=fsize 512-bytes blocks)。
如欲修改,可使用smit:
# smit chuser 选择用户,修改下面两项:
Soft FILE size [4194302]
# (2G,可根据需要设定)
Hard FILE size [4194302]
# (2G, 可根据需要设定)
用该用户身份登录,使用"ulimit -f "和"ulimit -Hf"可分别显示其fsize、fsize_hard的大小。

8、如何按文件大小排序列出一个文件系统下的文件?
当监控某一文件系统的空间使用情况时,如果该文件系统剩余空间较少或已使用空间增长较快,则有必要排序列出该文件系统中所有大于某一给定字节数的文件,以便进一步维护管理。为此,可用如下命令:
# find [filesystem_name] -xdev -size +[512-bytes bloks] -ls | sort -r -n -k7

以上所有命令在AIX4.3.3下全部测试通过。


27 04, 2005
smit的快捷方式[转贴]
作者 xzh2000 20:11 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

在smit菜单中,有很多快捷方式,用户就不必在菜单中一级级搜寻,可以直接进入子菜单,本文列出绝大多数的快捷方式。

 查看全文
27 04, 2005
AIX的页面管理[转贴]
作者 xzh2000 20:05 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

7 系统页面空间
系统把物理内存作为工作空间,把交互数据和程序放到磁盘上.这些空间就是页面空间.

 查看全文
27 04, 2005
AIX Paging Space[转贴]
作者 xzh2000 20:01 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

我们知道在AIX操作系统中,Paging Space是一项很重要的设备,AIX kernel(内 核)需要利用 Paging Space 来管理虚拟内存。和内存页面一样,AIX的 Paging Space也是以4KB为单位,当实际内存数的空闲值低于一定数量以后,系统需要把 实际内存中的某些计算页面(Computation Page)写回到Paging Space中(page out),以便释放出实际内存页面用于其他程序。在AIX 4.3.2及以后版本中,操作系统提供了3种 Paging Space的管理机制。分别为:
Early Page Space Allocation (EPSA)
Late Page Space Allocation (LPSA)
Deferred Page Space Allocation (DPSA)
Early Page Space Allocation

 查看全文
27 04, 2005
topas输出详细解决[转贴]
作者 xzh2000 19:51 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

第二个固定部分占用了显示器的最右端的25个位置。它包含如下统计信息的5个分部:
事件/队列 显示所选系统全局事件的每秒频率、线程运行和等待队列的平均大小:
Cswitch
在监视时间间隔内每秒上下文切换的数量。
Syscalls
在监视时间间隔内每秒执行的系统调用的数量。

在监视时间间隔内每秒执行的 read 系统调用的数量。

在监视时间间隔内每秒执行的 write 系统调用的数量。
派生
在监视时间间隔内每秒执行的 fork 系统调用的数量。
执行
在监视时间间隔内每秒执行的 exec 系统调用的数量。
运行队列
准备运行但需要等待处理器可用的平均线程数目。
等待队列
正在等待页面调度完成的平均线程数目。

 查看全文
26 04, 2005
AIX Problem检测[转贴]
作者 xzh2000 09:56 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

AIX Problem determination
1、 Boot 日志工具
用于跟踪Boot过程及可能在此期间发生问题的所在,可以使用alog命令监视这些问题,rc.boot 脚本使用alog命令重定向boot信息到文件/var/adm/ras/bootlog如果系统出现问题,可以单用户模式启动系统,使用alog –o –t boot命令查看该文件,确定是哪里出现了问题。

 查看全文

26 04, 2005
AIX 5L新特性[转]
作者 xzh2000 09:54 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

下面的文字是我辛辛苦苦敲上来的,我有一个感觉,大家学习AIX,绝大多数是4.3.3版本,对5L版本还不太熟悉。也许过去在4.3.3做起来要很复杂的事情,到了5L却很简单,还有的是在4.3中做的很顺利事情,到了5L却做不成功。所以希望大家不自己知道的5L新特性,无论大小,都跟帖到下面,我们来总结一下-:) 我自己今天 就遇到一个: .rhosts的权限必须设置为600,否则系统就会认为他无效。 类似的例子请大家跟帖亚,斑竹置顶就更好了。

 查看全文

26 04, 2005
191红皮书学习笔记.2
作者 xzh2000 09:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
191红皮书学习笔记(二)
http://www.chinaunix.net 作者:wangvi  发表于:2002-12-08 02:15:24

硬件助手
一、本章讨论各种确认设备安装的方法,这些方法有利于记录系统错误信息,然后采用一定的措施来解决系统故障。也讨论使用系统日志记录任何想要的信息
二、列出各种硬件设备:
1〕lsdev显示在系统中的设备及其属性,语法:
lsdev -C [ -c Class ] [ -s Subclass ] [ -t Type ] [ -f File ][ -F Format | -r ColumnName ] [ -h ] [ -H ] [ -l Name ][ -S State ]
lsdev -P [-c Class ] [ -s Subclass ] [ -t Type ] [ -f File ][ -F Format | -r ColumnName ] [ -h ] [ -H ]
参数意义:
-C:列出在自定义设备对象类中的设备信息,C是customized,通常列出设备名、状态、位置、描述,不能和-P一起使用;
-c class:指定输出设备的类;
-H:在输出栏中显示每栏的头;
-h:显示命令使用消息;
-P:显示预定义设备对象类中的设备信息,P是predefined,通常列出类、类型、子类、描述,不能和-C、-l、-S一起使用;
-S State:列出所有在指定状态的设备。
2〕lspv 显示在卷组中的物理卷的信息,语法:
lspv [ -l | -p | -M ] [ -n DescriptorPhysicalVolume] [-v VolumeGroupID] PhysicalVolume
-p:列出每个物理卷中物理分区范围、状态、在盘体中的区域(如outer、center等)、LV名、类型和mount点;
-v VGID:访问基于卷组ID变量的信息
3〕lsattr显示给定设备或给定设备种类的属性信息
三、配置系统设备
cfgmgr可以向系统中加入一个新设备或者配置在系统启动过程中无法侦测为可用状态的设备。设备的配置受作为设备配置数据库的一部分的Configuration Rules object class的约束。配置规则包含三个项目:一个可执行程序运行的全路径;何时运行该程序(和其它规则相关);在哪个阶段运行该程序。
cfgmgr在系统启动的第一阶段运行所有第一阶段的配置规则,这使得所有的基本设备被配置,此后第二阶段cfgmgr带参数-s被调用。一般来说cfgmgr命令在调用过程中会运行所有的配置规则〔第一阶段带有参数-f〕,但是如果-l参数被使用了,就会只配置指定的设备及其子设备。
如cfgmgr命令被调用时没有指定阶段,就会运行第二阶段规则。如果要运行第三阶段的规则,只能用-p 3指定。
每个阶段的配置规则都被安排好从指定的seq域中读取相应的值。这个域是一个整数,用来指定执行与其它在这阶段运行的规则关联的运行优先级,数值越小优先级越高,但是0代表最后运行。
典型的配置规则:
phase seq rule
1 1 /usr/lib/methods/defsys
1 10 /usr/lib/methods/deflvm
2 1 /usr/lib/methods/defsys
2 5 /usr/lib/methods/ptynode
210 /usr/lib/methods/startlft
215 /usr/lib/methods/starttty
3 1 /usr/lib/methods/defsys
3 5 /usr/lib/methods/ptynode
3 10 /usr/lib/methods/startlft
315 /usr/lib/methods/starttty
cfgmgr使用举例:当cfgmgr带-f参数被调用,执行上表中的两个第一阶段的命令;当带-s参数或-p 2或不带参数被调用时,执行上表中4个第二阶段的命令;当带-p 3调用时,执行4个第三阶段命令;
要配置连接在scsi0上的设备时,使用cfgmgr -l scsi0;要在配置时自动从安装介质安装,使用cfgmgr -i /usr/sys/inst.images
四、系统管理服务(System Managenmen Services):cfgmgr是从软件级别配置硬件,SMS可以从硬件级别检查配置系统。
使用sms程序的步骤:
1、首先确认机器是关闭的;
2、如果系统是需要sms软盘的,先在客户端插入软盘并打开机器,如果不插入软盘而需要软盘,将提示以后插入;
3、当显示器上底部图标从左向右显示时按下F1(图形菜单)或F4(文字菜单)进而sms菜单(如果没有按下F1或F4,将正常启动);
4、菜单显示,进行必要的测试或配置,也可修改进入查询密码,如果忘记,请主板放电。
五、硬件兼容性
RS/6000和RSPC系统支持PCI、ISA、SCSI接口的设备。如果设备支持软件安装了并且cfgmgr在系统引导时运行了并且无硬件冲突,PCI和SCSI设备会自动配置。
非本地的设备必须人工配置,可能需要改变设备的predefined 或customized属性值,尤其是当配置超过一个的相同设备的时候。
即使有多个适配器,也不一定能在相同的适配器上运行不同的设备。不同的机器规格有各种不同的配置。例如:如果有SCSI SE Ultra控制器,只有SE SCSI设备能接上去;同样地,如果有100M局域网,10M网卡就不能正常工作。
设备配置数据库:a、predefined数据库包含所有可能的系统中的已配置的设备的配置数据;b、customized数据库包含了所有当前系统中已定义和已配置的设备的配置数据。
无论在系统引导阶段还是运行阶段,只要cfgmgr程序在运行,设备配置数据库就允许机器进行自动配置。
对于非本地的ISA设备,包含在配置数据库中预定义部分的信息数据没有充分地自动完成,自由冲突,ISA设备配置。因此,在第一次配置设备是用户需要人工自定义一些被ISA设备使用的值〔如中断级别、共享内存地址等〕。
六、lsattr命令语法:lsattr { -D [ -O ] | -E [ -O ] | -F Format } -l Name [ -a Attribute ] [ -f File ] [ -h ] [ -H ]
lsattr { -D [ -O ] | -F Format } { [ -c Class ] [ -s Subclass ] [ -t Type ] }[ -a Attribute ] ... [ -f File ] [ -h ] [ -H ]
lsattr -R { -l Name | [ -c Class ] [ -s Subclass ] [ -t Type ] } -a Attribute [ -f File ] [ -h ] [ -H ]
参数意义:-D:显示属性名、默认值、描述、不使用-O参数的指定设备中用户可设定的参数值,当使用-O参数的时候,只显示属性名,默认值
-E:显示属性名、当前值、描述、不使用-O参数的指定设备中用户可设定的参数值,当使用-O参数时,只显示属性名,当前值,这个参数不和-c,-D,-F,-R,-s,-t一起使用
-F format:以指定的格式显示输出
-a attribute:显示指定设备或设备种类的属性
-c class:指定设备类名,不能和-E和-l参数一起使用
-f file:从文件中读取需要的参数
-H:在输出中显示栏标题,把-H和-O或-R一起使用没有意义,-O或-R优先
-l:指定要显示其属性名和values的自定义设备对象类中设备逻辑名,这些设备在/dev下都列出来了
-O:显示所有属性名,以冒号分开,第二行显示所有相应的属性值
-R:显示一个属性名的合法值,不能和-D,-E,-F和-O参数一起使用,但可以和-c,-s,-t,-l参数一起使用,显示结果以垂直列表的方式显示,-R参数可以显示从x到n的范围的属性值。
-s subclass:指定一个设备子类名,该参数不能和-E或-l一起使用
-t type:指定一个设备类型名,不能和-E或-l一起使用
当显示自定义设备的有效属性值的时候,这些信息来自配置数据库,而不是来自设备本身。通常数据库里的值反映了设备是如何配置的,除非该设备被以chdev -P或-T命令重新配置过。如果有这种情况,在下次重新启动之前,lsattr命令可能不会正确地反映当前设备的配置
如果使用的-D或-E参数,输出会显示属性名、属性值、描述、不带-O参数时用户可设定的字符串。-O表示显示所有指定属性的名字,以冒号分开。下一行显示相应的所有属性值。-H参数可以和-D,-E,-F一起使用显示栏头,-F参数可以指定输出的格式。

七、用smit管理设备,可以实现以下目的:在IPL后安装或配置附加的硬件;删除设备;列出存在的设备;改变或显示设备属性;实现设备问题的诊断。
八、系统错误日志:当某个操作系统模块探测到一个错误的时就会触发错误日志进程,错误侦测段代码就会发送错误信息到errsave和errlast kernel service或错误日志应用子程序,信息就被转入或写入/dev/error文件。进程然后加入时间戳到收集到的数据中去,可以使用errpt命令从错误日志中找到错误记录。
使用errdemon命令:errdemon进程经常检查/dev/error文件中的新条目,如果新数据匹配错误记录模板库中的某个项目时,后台程序就会收集其它系统组件中的信息.
errdemon通常在系统启动是自动启动,但是如果它被中断了,可以重新执行它:/usr/lib/errdemon.
确定系统错误日志文件的路径:/usr/lib/errdemon -l,结果如下:
# /usr/lib/errdemon -l
Error Log Attributes
--------------------------------------------
Log File /var/adm/ras/errlog
Log Size 1048576 bytes
Memory Buffer Size 8192 bytes
要改变log size,运行/usr/lib/errdemon -s 2000000;
要改变错误日志设备驱动器的内部缓冲,运行:/usr/lib/errdemon -B 16384;同时会显示以下信息:0315-175 The error log memory buffer size you supplied will be rounded up to a multiple of 4096 bytes.
使用errpt命令:errpt命令用errlog中的数据产生错误报告,它也可用参数来指定匹配特殊标准的条目,如果不带参数,就会列出所有的记录,并以从近到久的顺序排列,该命令不能完成日志分析,要分析需要用diag命令.
常用语法:
errpt [ -a ] [ -c ] [ -d ErrorClassList ] [ -e EndDate ] [ -g ] [ -i File ]
[ -j ErrorID [ , ErrorID ] ] | [ -k ErrorID [ , ErrorID ]] [ -J ErrorLabel
[ , ErrorLabel ] ] | [ -K ErrorLabel [ , ErrorLabel ] ] [ -l SequenceNumber ]
[ -m Machine ] [ -n Node ] [-s StartDate ] [ -F FlagList ]
[ -N ResourceNameList ] [ -R ResourceTypeList ] [ -S ResourceClassList ]
[ -T ErrorTypeList ] [ -y File ] [ -z File ]
常用参数意义:
-a:以详细方式显示错误日志中的错误信息,如果和-t参数联合使用,显示模板中所有的信息
-j errid[,errid]:显示指定errid的错误记录,可用逗号分隔多个errid,或附上双引号以逗号分隔或空格分隔.联合-t参数,条目从错误模板库中取出.
-s startdate:指定显示startdate之后的记录,startdate格式为mmddhhmmyy.
-t:对错误记录模板库进行处理而不是对错误日志,该参数可以用于查看报表中的错误记录模板.
-F flaglist:依据模板的Alert/Log/Report域的值选择错误记录模板.
-J errorlabel:列出由errorlabel指定的错误日志条目.
errloger:写错误日志
errclear:从错误日志中删除条目
errinstall:安装消息到错误日志消息集中
errupdate:更新错误记录模板库
九、诊断硬件问题
diag命令用于定位硬件问题,它测试系统并分析错误日志.有图形界面,也可直接用命令行.其使用方法:
1.运行diag命令;
2.在显示的信息屏中按下回车;
3.选择诊断程序;
4.选择故障定位.
同样地,也可以使用diag -d sysplanar0 -v -e完成相同的诊断任务.
十、系统日志
AIX使用syslogd记录系统消息.syslogd读取datagram socket并发送每个消息行到/etc/syslog.conf描述的目的地.syslogd后台在活动并收到挂起信号的时候读取配置文件.
syslogd后台创建/etc/syslog.pid文件.该文件只有这样一行:该行有syslogd后台的命令进程ID.它用于结束或重新配置syslogd后台.
当一个终结信号送达,syslogd后台终止.后台记录下终止信息并立即结束.
每条消息都只有一行,一条消息包含一个在行首由尖括号括起来的数字,该数字代表优先权,如果消息长度超过900字节,就会被截断.
/usr/include/sys/syslog.h包含定义一些文件灵敏度和优先级的代码,并被配置文件使用
本地被写入的应用程序使用包含在syslog.h文件中的定义通过syslogd后台来记录日志信息.
syslogd的语法syslogd [ -d ] [ -s ] [ -f ConfigurationFile ] [ -m MarkInterval ] [-r].
参数含义:
-d:进入调试
-f config file:指定一个可选的配置文件.
-m markinterval:指定两个mark命令消息之间的分钟数.如果不使用该参数,mark命令每20分钟会发送一个Log_info优先级的消息.facility也不能由选择所有其它facilities的selector域来选择
-s 指定发送精简的消息到其它系统从而使所有syslogd消息在本地系统上产生.
-r 禁止录入从远程主机接受到的消息.
syslogd后台使用一个配置文件根据消息的优先级和facility确定系统消息送达的地方.
默认情况下,syslogd读取默认的配置文件/etc/syslog.conf,但如果通过-f参数指定了,就可以指定替换的配置文件.
/etc/syslog.conf文件控制了syslogd后台的行为.如syslogd使用/etc/syslog.conf文件确认了送错误消息到哪里或者怎样应付不同的系统事件.
除了/etc/syslog.conf文件包含了syslogd后台的设置之外,/etc/syslog.pid也包含了运行syslogd后台的进程ID
配置文件的格式:
selector域定义了facility和优先级.以逗号分离facility名,以点号分离facility和优先级,以分号分离相同selector域中多个条目,选择所有的facilities用星号.
action域确定了一个接收消息的目的地.如果发送到一个远程主机,远程系统会象在自己的配置文件中指出的一样处理该消息,要在一个用户终端上显示消息,destination域必须包含一个登录到系统中的可用用户名.
facilities,下面列出一些在/etc/syslog.conf文件中使用的facilities:
Facility Description
kern Kernel
userUser level
mail Mail subsystem
daemon System daemons
auth Security or authorization
syslog syslogd daemon
lpr Line-printer subsystem
news News subsystem
uucp uucp subsystem
* All facilities
priority,下面列出在/etc/syslog.conf文件中使用的优先级,这些优先级可以在selector域中的消息优先级字段.指定优先级或高于该优先级的级别的消息直接发送.
Priority Level Description
emerg Specifies emergency messages (LOG_EMERG). These messages are not distributed to all users. LOG_EMERG priority messages can be logged into a separate file for reviewing.
alert Specifies important messages (LOG_ALERT), such as a serious hardware error. These messages are distributed to all users.
crit Specifies critical messages not classified as errors (LOG_CRIT),such as improper login attempts. LOG_CRIT and higher-priority messages are sent to the system console.
err Specifies messages that represent error conditions (LOG_ERR), such as an unsuccessful disk write.
warning Specifies messages for abnormal, but recoverable, conditions (LOG_WARNING).
notice Specifies important informational messages (LOG_NOTICE). Messages without a priority designation are mapped into this priority. These are more important than informational messages, but not warnings.
info Specifies informational messages (LOG_INFO). These messages can be discarded but are useful in analyzing the system.
debug Specifies debugging messages (LOG_DEBUG). These messages may be discarded.
none Excludes the selected facility. This priority level is useful only if preceded by an entry with an * (asterisk) in the same selector field.
destination,下面列出一些在/etc/syslog.conf文件中使用的destinations,可以在action域使用这些destinations
Destination Description
File Name Full path name of a file opened in append mode.
@Host Host name, preceded by @ (at sign).
User[, User][...] User names.
* All users.
修改syslog.conf文件后,需要重新启动syslogd后台.使用以下命令
1.查看syslogd后台进程ID是什么:ps -ef|grep syslogd
# ps -ef | grep syslogd
root 5426 4168 0 Nov 01 - 0:00 /usr/sbin/syslogd
root 24938 25854 2 12:04:03 pts/6 0:00 grep syslog
2.使用stoprc命令停止syslogd后台:stoprc -s syslogd
3.检查syslogd后台是否成功停止:ps -ef|grep syslogd
4.重启syslogd后台:startsrc -s syslogd
对/etc/syslog.conf作一些修改:
1.向/tmp/mailsyslog日志中录入所有的mail facility的级别为debug或超过debug级别的消息:mail.debug /tmp/mailsyslog.其中,mail是facility,debug是优先级,/tmp/mailsyslog是目的地.
2.送所有的系统信息[除了来自mail facility的]到一台名为rigil的主机:*.debug;mail.none @rigil.其中*和mail是facility,debug和none是优先级,@rigil是目的地.
3.把所有的mail facility消息送到所有用户终端显示上:mail.debug *

十一、设置ASCII终端
3151终端有几种方式连接到AIX系统:直接联机,通过modem连接.连接到AIX系统将占用一个串口.或通过异步适配器连接到AIX.
要加入一个终端的步骤如下:
1.使用smitty tty并选择Add a TTY,或者使用smitty maktty;
2.系统将询问tty类型及其父适配器,从列表中选择正确的值;
3.在PORT number域选择想使用的端口号,对于紧接着位置代码规则的RAN选择适当的端口号.
4.改变终端类型域的值为正确的值,如果该设置不正确,可能无法使用所有的健.终端环境动态存储这些设置.
5.设置线速度和通讯种类
这些将会创建一个设备特殊文件到/dev目录下,并在/etc/inittab文件中加入一条,以便在系统启动的时候在终端上运行getty使终端可用,同时也会在自定义ODM数据库中加入一条该终端的定义.
也可以通过命令行方式直接加入一个终端.要加入一个ibm3151终端,通过串口rs232,使用sa0适配器的s1端口,使用:mkdev -c tty -t tty -s rs232 -p sa0 -w s1 -a login=enable -a term=ibm3151
可以以以下命令删除一个终端:rmdev -l ttyname -d,这里ttyname可以通过使用tty命令列出来并确认.

26 04, 2005
191红皮书学习笔记.1
作者 xzh2000 09:45 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
191红皮书学习笔记(一)
http://www.chinaunix.net 作者:wangvi  发表于:2002-12-05 02:20:58

[这个贴子最后由老农a在 2002/12/08 11:04pm 编辑]

英文水平比较差,所以有些地方很生涩!
一、系统启动问题处理:
1、基本的启动进程和有序关机:
(1)基本命令:alog、cfgmgr、last、bootlist、uptime、mpcfg、shutdown
a、alog:对系统日志进行读写。rc.boot通过alog命令把引导信息重定向到/var/adm/ras/bootlog
FlagDescription
-f  LogFile指定日志文件名,如果文件不存在,就创建,如果alog无写权限,就会写入 /dev/null。
-L 列出当前定义在alog配置数据库中的日志类型,如果使用-L参数并带有 -t LogType 参数,指定的 LogType 属性被列出来。
-t用来标识一个定义在alog配置数据库中的日志。alog命令从alog配置数据库中得到日志的文件名和大小。
-o 列出日志文件的内容;连续地把日志文件的内容写到标准输出。
-q 把标准输入拷贝到日志文件,但不写入标准输出。
b、cfgmgr:用来配置设备并随时把设备软件安装到系统中。常用语法:cfgmgr [ -f | -s | -p Phase ] [ -i Device ] [ -l Name ] [ -v ]
Flag Description
-f 指定 cfgmgr命令运行第一阶段配置规则,该参数在运行时不可用(即系统启动后)。
-i Device 指定安装介质的路径。
-l Name 指定单独配置的设备及其子设备Specifies the named device to configure along with its children.
-p Phase 指定 cfgmgr 命令运行的阶段
-s 指定 cfgmgr 命令紧接着第2阶段的配置规则
-v 指定 verbose 输出.  cfgmgr 命令把关于它所做的操作信息写到标准输出
设备的配置由Configuration Rules object class来控制,Configuration Rules object class是设备配置数据库的一部分。每条配置规则指定了三个项目:一个可执行程序的全路径;何时运行该程序(和其它规则关联);在哪个阶段运行。
系统引导包含两个阶段:当核心使系统开始引导,并且引导文件系统被初始化的时候第一阶段开始,在这一阶段cfgmgr被调用,通过cfgmgr -f来指定目前是第一阶段。该命令在这阶段运行所有需要在第一阶段配置的基本设备的配置规则;
在第二阶段,该命令以-s参数被调用。
cfgmgr命令认可配置规则的三个阶段:第一阶段、正常模式引导的第二阶段、维护模式引导的第二阶段。
c、last:用于显示所有以前login或logout的记录,这些记录记录在/var/adm/wtmp中,以从最近到最久的顺序排列。
用法:last [ -f FileName ] [ - Number ] [ Name ... ] [ Terminal ... ]
Flag Description
- Number在输出设备中显示的行数
Name 以名字样式指定的用户的登入和登出记录
Terminal以终端样式指定的终端的登入和登出记录
shutdown显示以前关机的记录
d、bootlist:用来显示并改变一个已经启动过的系统的启动设备的列表(即定义从哪个设备启动)。可以改变三种启动模式的列表:正常引导模式下的启动设备列表、维护模式下的和上次的启动设备列表。
用法:bootlist [ { -m Mode } [ -r ] [ -o ] [ [ -i ] |[ [ -f File ] [ Device [ Attr= Value ... ] ... ] ] ]
Flag Description
-m mode 指定哪个启动列表被显示或改变,有三种:正常模式,维护模式,上次引导模式.
-f File 指出启动设备信息从其后指定的文件中读取.
-i 使通过-m参数设置的设备列表无效.
-o 和-m参数一起用来显示指定模式的启动列表.
-r 指明是否显示已经改变过的的启动列表.
可启动的设备名
Device Description
fd xx 软盘Diskette drive device logical names
hdisk xx 硬盘Physical volume device logical names
cd xx 光盘SCSI CD-ROM device logical names
rmt xx磁带Magnetic tape device logical names
ent xx 网络Ethernet adapter logical names
tok xx 令牌环Token ring adapters logical names

e、uptime:显示系统已经运行了多久,该命令的输出实际上与w命令输出的第一行一样。
用法:uptime
结果:05:10PM up 6 days, 21:45, 13 users,load average 4.00, 3.00, 0.00
含义:当前时间运行了多久在线用户数平均负载,进程数(前5、10、15分钟)

f、mpcfg:略
g、shutdown:关闭系统,
用法:shutdown [ -d ] [ -F ] [ -h ] [ -i ] [ -k ] [ -m ] [ -p ] [ -r ] [ -t mmddHHMM [ yy ] ] [ -v ] [ + Time [ Message ] ]
Flag Description
-d 使系统从分布式模式关闭成为多用户模式
-F快速关机
-h 完全关闭系统,和-v参数相同
-i 指定为交互模式,显示交互信息引导用户关机
-k避免关闭系统
-m 使系统关闭并切换到维护模式
-r 重新启动系统
-v完全关闭系统
每次系统在关闭前会检查是否存在一个文件/etc/rc.shutdown,如果存在,在关闭系统之前会先执行该脚本,但是该脚本必须是可执行的,它是要被/usr/sbin/shutdown脚本调用的。

(2)启动进程
a、引导操作系统的必要条件:一个在机器启动的时候可以加载的启动镜象;可以使用的/和/usr文件系统。
b、系统引导有三种方式:硬盘引导、无盘网络引导、维护引导
c、硬盘引导过程:找到本地硬盘上的引导镜象,然后引导,配置在本地找到的所有硬件设备,并初始化其它系统运行必要的基本软件(如LVM),启动进程最后是mount文件系统,以使它们可用
d、系统引导过程中发生的事件分为三个阶段:
(1)Read Only Storage (ROS) Kernel Init Phase:检查主板、ROS程序加载搜索bootlist,找到后boot image被读入内存,系统初始化开始;
(2)Base Device Configuration Phase:配置所有设备,cfgmgr中有提到;
(3)System Boot Phase:所有LV被启用,paging启动,/etc/inittab文件被处理;
(3)加电顺序、LED和声音信号:考试中也包含一些LED代码的含义。
二、解决启动中的问题
1、导致启动失败的原因:a、人为原因;b、环境因素;c、机器故障
http://www.chinaunix.net/jh/9/17145.html
26 04, 2005
IBM RS/6000使用点滴
作者 xzh2000 09:44 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流
IBM RS/6000使用点滴
http://www.chinaunix.net 作者:qingzhou 发表于:2003-12-25 14:54:09

★IBM C V5.0 快速配置

将/usr/vac/cforaix_n.lic中的nodelock项拷贝到/var/ifor/nodelock文件中。

★AIX如何自动logout用户

有的用户登录后就长时间空闲,有可能导致安全上的问题。通过打开/etc/profile中

TMOUT注释,将自动在所设置的时间到达后,logout用户。
例如:export TMOUT=120
那么,用户两分钟没有击键将自动logout。
★如何备份裸设备

AIX中mksysb和savevg都只备份mount的文件系统,如果想备份裸设备,可选择用dd命令,将裸设备中的内容硬拷贝成文件。较完善的方法是选择成熟软件,如IBM的SYSBACK或Storix Backup Administrator for AIX(该软件可从http://www.storix.net上下载)
★AIX中,如何打印Xwindows下的屏幕

首先用xwd命令dump一个XWINDOWS屏幕,然后用xpr将其输出到打印机。

★如何实现两台UNIX之间的磁带拷贝

执行下列命令,利用网络实现磁带拷贝
tar cvfbX - . | compress | rsh AIXMACHINE "uncompress | dd of=/dev/rmt0 obs=20b"
注意:两台UNIX网络设置应允许rsh工作正常!



★将man文件转换成普通文本文件

正确的将man文件输出转成文本文件的方法是:
$ man ls | col -b > man.txt



★如何在打印队列出现故障时发邮件通知管理员

#!/bin/ksh
ERR_Q=""*** WARNING - Printer queue"
enq -AW | while read QUEUE DEVICE STATUS
do
if [ $STATUS = "DOWN" ]
then
ERR_Q="${ERR_Q} ${QUEUE}"
fi
done
echo "${ERR_Q} is down ***" | mail operator



★如何把一台RS/6000上的打印机设置原封不动移到另一台?

不要想得太复杂,只需简单地把/etc/qconfig文件拷贝到目的RS/6000上的/etc目录下,qdaemon会自动生成其他配置,如:把qconfig(ASCII文本)转换为qconfig.bin(二进制格式),这样即实现把一台RS/6000上的打印机设置原封不动移到另一台上去。

25 04, 2005
STATISTICS_LEVEL详解
作者 xzh2000 20:24 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Setting the Level of Statistics Collection

Oracle9i Release 2 (9.2) provides the initialization parameter STATISTICS_LEVEL
, which controls all major statistics collections or advisories in the database.
This parameter sets the statistics collection level for the database.

Depending on the setting of STATISTICS_LEVEL, certain advisories and statistics
are collected, as follows:

BASIC: No advisories or statistics are collected.

TYPICAL: The following advisories or statistics are collected:

    * Buffer cache advisory
    * MTTR advisory
    * Shared Pool sizing advisory
    * Segment level statistics
    * PGA target advisory
    * Timed statistics

ALL: All of the preceding advisories or statistics are collected, plus the
following:

    * Timed operating system statistics
    * Row source execution statistics

The default level is TYPICAL. STATISTICS_LEVEL is a dynamic parameter and can be
altered at the system or the session level.

When modified by ALTER SYSTEM, all advisories or statistics in the preceding
list are dynamically turned on or off, depending on the new value of
STATISTICS_LEVEL.

When modified by ALTER SESSION, only the following advisories or statistics are
turned on or off in the local session only. Their systemwide state is not
changed.

    * Timed statistics
    * Timed operating system statistics
    * Row source execution statistics
</quote>


Or you might mean:

<quote>

Dynamic Sampling for the Optimizer

The purpose of dynamic sampling is to improve server performance by determining
more accurate selectivity and cardinality estimates. More accurate selectivity
and cardinality estimates allow the optimizer to produce better performing
plans.

You can use dynamic sampling to:

    * Estimate single-table predicate selectivities when collected statistics
cannot be used or are likely to lead to significant errors in estimation.
    * Estimate table cardinality for tables without statistics or for tables
whose statistics are too out of date to trust.

The DYNAMIC_SAMPLING hint lets you control dynamic sampling to improve server
performance by determining more accurate selectivity and cardinality estimates.
You can set the value of DYNAMIC_SAMPLING to a value from 0 to 10. The higher
the level, the more effort the compiler puts into dynamic sampling and the more
broadly it is applied. Sampling defaults to cursor level unless you specify a
table.
See Also:

    * "Dynamic Sampling" for information about when and how to use dynamic
sampling
    * "DYNAMIC_SAMPLING" for details about using this hint

......

Dynamic Sampling

The purpose of dynamic sampling is to improve server performance by determining
more accurate selectivity and cardinality estimates. More accurate selectivity
and cardinality estimates allow the optimizer to produce better performing
plans.

You can use dynamic sampling to:

    * Estimate single-table predicate selectivities when collected statistics
cannot be used or are likely to lead to significant errors in estimation.
    * Estimate table cardinality for tables without statistics or for tables
whose statistics are too out of date to trust.
    * How Dynamic Sampling Works

The primary performance attribute is compile time. Oracle determines at compile
time whether a query would benefit from dynamic sampling. If so, a recursive SQL
statement is issued to scan a small random sample of the table's blocks, and to
apply the relevant single table predicates to estimate predicate selectivities.
The sample cardinality can also be used, in some cases, to estimate table
cardinality.

Depending on the value of the OPTIMIZER_DYNAMIC_SAMPLING initialization
parameter, a certain number of blocks are read by the dynamic sampling query.

25 04, 2005
位图索引与 B-tree 索引:选择与时间
作者 xzh2000 20:12 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

位图索引与 B-tree 索引:选择与时间
Vivek Sharma

了解每个索引的正确应用对性能会有很大影响。

一般认为,位图索引最适合于具有低相异值的列(如 GENDER、MARITAL_STATUS 和 RELATION)。然合,这种观点并不完全正确。实际上,对于那些并不经常由许多并行系统更新其数据的系统来说,总是建议采用位图索引。事实上,正如我此处所阐明的,在具有 100% 唯一值(主键的列候选键)的列上的位图索引与 B-tree 索引同样有效。

在本文中,我将提供一些示例和优化程序决策,它们对于低基数列和高基数列上的索引类型是通用的。这些示例将帮助 DBA 了解位图索引的使用实际上并不依赖于基数,而是依赖于应用程序。

比较索引

在唯一列上使用位图索引( Oracle 不建议这种方法)有几个缺点,其中一个对充足空间的需求。然而,位图索引的大小依赖于列的基数,位图索引是在该列上创建,同时进行数据分配。因此,GENDER 列上的位图索引将小于相同列上的 B-tree 索引。相反,EMPNO(主键的候选键)上的位图索引将比此列上的 B-tree 索引大得多。但是因为访问决策支持系统 (DSS) 的用户比访问交易处理 (OLTP) 系统的用户要少,所以资源对于这些应用程序不是问题。

为演示这一点,我创建了两个表 TEST_NORMAL 和 TEST_RANDOM。我使用 PL/SQL 块在 TEST_NORMAL 表中插入一百万行,然后随机在 TEST_RANDOM 表中插入这些行:

Create table test_normal (empno number(10), ename varchar2(30), sal number(10));

Begin
For i in 1..1000000
Loop
Insert into test_normal 
values(i, dbms_random.string('U',30), dbms_random.value(1000,7000));
If mod(i, 10000) = 0 then
Commit;
End if;
End loop;
End;
/
  
Create table test_random 
as 
select /*+ append */ * from test_normal order by dbms_random.random;

SQL> select count(*) "Total Rows" from test_normal;

Total Rows
----------
   1000000

Elapsed: 00:00:01.09

SQL> select count(distinct empno) "Distinct Values" from test_normal;

Distinct Values
---------------
        1000000

Elapsed: 00:00:06.09
SQL> select count(*) "Total Rows" from test_random;

Total Rows
----------
   1000000

Elapsed: 00:00:03.05
SQL> select count(distinct empno) "Distinct Values" from test_random;

Distinct Values
---------------
        1000000

Elapsed: 00:00:12.07
注意 TEST_NORMAL 是条理的,而 TEST_RANDOM 表是随机创建的,因此 TEST_RANDOM 表的数据是无条理的。在上面的表中,列 EMPNO 包含完全相异的值,是很好的一个候选主键。如果您将此列定为主键,则您将创建一个 B-tree 索引而非位图索引,因为 Oracle 不支持位图主键索引。

要分析这些索引的行为,我们将执行下列步骤:

  1. 在 TEST_NORMAL 上:
    1. 在 EMPNO 列上创建一个位图索引,并使用等式谓词执行某些查询。
    2. 在 EMPNO 列上创建一个 B-tree 索引,使用等式谓词执行某些查询,并比较由查询做出的逻辑和物理输入/输出,以取出不同值集的结果。
  2. 在 TEST_RANDOM 上:
    1. 与步骤 1A 相同。
    2. 与步骤 1B 相同。
  3. 在 TEST_NORMAL 上:
    1. 与步骤 1A 相同,除了查询是使用在一定范围的谓词执行之外。
    2. 与步骤 1B 相同,除了查询是使用一定范围的谓词执行之外。现在比较统计值。
  4. 在 TEST_RANDOM 上:
    1. 与步骤 3A 相同。
    2. 与步骤 3B 相同。
  5. 在 TEST_NORMAL 上:
    1. 在 SAL 列上创建一个位图索引,然后使用等式谓词执行某些查询,及使用范围谓词执行某些查询。
    2. 在 SAL 列上创建一个 B-tree 索引,然后使用等式谓词执行某些查询,和使用范围谓词(与步骤 5A 中相同的某些值集)执行某些查询。比较由查询完成的输入/输出以取出结果。
  6. 将 GENDER 列添加到全部两个表中,并使用三个可能值更新列:M 代表男,F 代表女,null 代表不适用。基于一定条件使用这些值对列进行更新。
  7. 在此列上创建一个位图索引,并使用等式谓词执行某些查询。
  8. 在 GENDER 列上创建一个 B-tree 索引,并使用等式谓词执行某些查询。与步骤 7 的结果比较。
步骤 1 到步骤 4 涉及一个高基数(100% 不同)列,步骤 5 涉及一个普通基数列,而步骤 7 和步骤 8 涉及一个低基数列。

步骤 1A(在 TEST_NORMAL 上)

在此步骤中,我们将在 TEST_NORMAL 表上创建一个位图索引,然后检查此索引的大小、其群集因子和表的大小。然后我们将使用等式谓词运行某些查询,并使用此位图索引注明这些查询的输入/输出。

SQL> create bitmap index normal_empno_bmx on test_normal(empno);

Index created.

Elapsed: 00:00:29.06
SQL> analyze table test_normal compute statistics for table for all indexes for all indexed columns;


Table analyzed.

Elapsed: 00:00:19.01
SQL> select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
2  from user_segments
3* where segment_name in ('TEST_NORMAL','NORMAL_EMPNO_BMX');
 
SEGMENT_NAME                               Size in MB
------------------------------------       ---------------
TEST_NORMAL                                50
NORMAL_EMPNO_BMX                           28

Elapsed: 00:00:02.00
SQL> select index_name, clustering_factor from user_indexes;

INDEX_NAME                             CLUSTERING_FACTOR
------------------------------         ---------------------------------
NORMAL_EMPNO_BMX                       1000000

Elapsed: 00:00:00.00
您会看到在前面表中索引的大小是 28 MB,而群集因子等于表中的行数。现在让我们使用等式谓词针对不同值集执行查询:
SQL> set autotrace only
SQL> select * from test_normal where empno=&empno;
Enter value for empno: 1000
old   1:select * from test_normal where empno=&empno

new   1:select * from test_normal where empno=1000

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=1 Bytes=34)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_NORMAL' (Cost=4 Car
d=1 Bytes=34)
2    1     BITMAP CONVERSION (TO ROWIDS)
3    2       BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_EMPNO_BMX'

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
5  consistent gets
0  physical reads
0  redo size
515  bytes sent via SQL*Net to client
499  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
1  rows processed
步骤 1B(在 TEST_NORMAL 上)

现在我们将丢弃此位图索引并在 EMPNO 列上创建一个 B-tree 索引。同以前一样,我们将检查索引的大小及其群集因子并针对相同的值集执行相同的查询,以比较输入/输出。

SQL> drop index NORMAL_EMPNO_BMX;

Index dropped.

SQL> create index normal_empno_idx on test_normal(empno);

Index created.

SQL> analyze table test_normal compute statistics for table for all indexes for all indexed columns;

Table analyzed.

SQL> select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
2  from user_segments
3  where segment_name in ('TEST_NORMAL','NORMAL_EMPNO_IDX');

SEGMENT_NAME                               Size in MB
----------------------------------         ---------------
TEST_NORMAL                                50
NORMAL_EMPNO_IDX                           18

SQL> select index_name, clustering_factor from user_indexes;

INDEX_NAME                            CLUSTERING_FACTOR
----------------------------------    ----------------------------------
NORMAL_EMPNO_IDX                      6210
很清楚在此表中,B-tree 索引比 EMPNO 列上的位图索引更小。B-tree 索引的群集因子更加接近表中的块数;由于这一原因,B-tree 索引对于范围谓词查询效率更佳。

现在我们将使用我们的 B-tree 索引针对相同的值集运行相同的查询。

SQL> set autot trace
SQL> select * from test_normal where empno=&empno;
Enter value for empno: 1000
old   1:select * from test_normal where empno=&empno
new   1:select * from test_normal where empno=1000

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=1 Bytes=34)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_NORMAL' (Cost=4 Car
d=1 Bytes=34)
2    1     INDEX (RANGE SCAN) OF 'NORMAL_EMPNO_IDX' (NON-UNIQUE) (C
ost=3 Card=1)

Statistics
----------------------------------------------------------
29  recursive calls
0  db block gets
5  consistent gets
0  physical reads
0  redo size
515  bytes sent via SQL*Net to client
499  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
1  rows processed
正如您可以看到的那样,针对不同的值集执行查询时,对于在完全唯一列上的位图和 B-tree 索引,一致性读请求和物理读取的数量是相同的。

位图EMPNOB-TREE
一致性读数物理读数一致性读数物理读数
50100050
52239852
52854552
529800852
528534252
5212844452
5285852

步骤 2A(在 TEST_RANDOM 上)

现在我们将在 TEST_RANDOM 上执行相同的实验:

SQL> create bitmap index random_empno_bmx on test_random(empno);

Index created.

SQL> analyze table test_random compute statistics for table for all indexes for all indexed columns;

Table analyzed.

SQL> select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
2  from user_segments
3* where segment_name in ('TEST_RANDOM','RANDOM_EMPNO_BMX');
 
SEGMENT_NAME                               Size in MB
------------------------------------       ---------------
TEST_RANDOM                                50
RANDOM_EMPNO_BMX                           28

SQL> select index_name, clustering_factor from user_indexes;

INDEX_NAME                             CLUSTERING_FACTOR
------------------------------         ---------------------------------
RANDOM_EMPNO_BMX                       1000000
再次,统计值(大小和群集因子)对于 TEST_NORMAL 表上的那些索引是相同的。
SQL> select * from test_random where empno=&empno;
Enter value for empno: 1000
old   1:select * from test_random where empno=&empno

new   1:select * from test_random where empno=1000

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=1 Bytes=34)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_RANDOM' (Cost=4 Card=1 Bytes=34)
2    1     BITMAP CONVERSION (TO ROWIDS)
3    2       BITMAP INDEX (SINGLE VALUE) OF 'RANDOM_EMPNO_BMX'

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
5  consistent gets
0  physical reads
0  redo size
515  bytes sent via SQL*Net to client
499  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
1  rows processed
步骤 2B(在 TEST_RANDOM 上)

现在,与步骤 1B 中一样,我们将丢弃该位图索引并在 EMPNO 列上创建一个 B-tree 索引。

SQL> drop index RANDOM_EMPNO_BMX;

Index dropped.

SQL> create index random_empno_idx on test_random(empno);

Index created.

SQL> analyze table test_random compute statistics for table for all indexes for all indexed columns;

Table analyzed.

SQL> select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
2  from user_segments
3  where segment_name in ('TEST_RANDOM','RANDOM_EMPNO_IDX');

SEGMENT_NAME                               Size in MB
----------------------------------         ---------------
TEST_RANDOM                                50
RANDOM_EMPNO_IDX                           18

SQL> select index_name, clustering_factor from user_indexes;

INDEX_NAME                            CLUSTERING_FACTOR
----------------------------------    ----------------------------------
RANDOM_EMPNO_IDX                      999830
此表显示此索引的大小等于其在 TEST_NORMAL 表上的大小,但群集因子更加接近行数,这使得此索引对于范围谓词查询无效(我们将在步骤 4 中看到这种情况)。此群集因子将不会影响等式谓词查询,因为行具有全异的值,且每个键的行数为 1。

现在让我们来运行具有等式谓词和相同值集的查询。

SQL> select * from test_random where empno=&empno;
Enter value for empno: 1000
old   1:select * from test_random where empno=&empno

new   1:select * from test_random where empno=1000

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=4 Card=1 Bytes=34)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_RANDOM' (Cost=4 Card=1 Bytes=34)
2    1     INDEX (RANGE SCAN) OF 'RANDOM_EMPNO_IDX' (NON-UNIQUE) (Cost=3 Card=1)

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
5  consistent gets
0  physical reads
0  redo size
515  bytes sent via SQL*Net to client
499  bytes received via SQL*Net from client
2  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
1  rows processed

同样,结果几乎与步骤 1A 和 1B 中的的结果一样。数据分配不影响唯一列的一致性读请求和物理读取的数量。

步骤 3A(在 TEST_NORMAL 上)

在这一步中,我们将创建位图索引(与步骤 1A 相似)。我们知道索引的大小和群集因子,它等于表中的行数。现在让我们使用范围谓词运行某些查询。

SQL> select * from test_normal where empno between &range1 and &range2;
Enter value for range1: 1
Enter value for range2: 2300
old   1:select * from test_normal where empno between &range1 and &range2

new   1:select * from test_normal where empno between 1 and 2300

2300 rows selected.

Elapsed: 00:00:00.03

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=451 Card=2299 Bytes=78166)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_NORMAL' (Cost=451 Card=2299 Bytes=78166)
2    1     BITMAP CONVERSION (TO ROWIDS)
3    2       BITMAP INDEX (RANGE SCAN) OF 'NORMAL_EMPNO_BMX'

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
331  consistent gets
0  physical reads
0  redo size
111416  bytes sent via SQL*Net to client
2182  bytes received via SQL*Net from client
155  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
2300  rows processed
步骤 3B(在 TEST_NORMAL 上)

在这一步中,我们将对具有 B-tree 索引的 TEST_NORMAL 表执行查询。

SQL> select * from test_normal where empno between &range1 and &range2;
Enter value for range1: 1
Enter value for range2: 2300
old   1:select * from test_normal where empno between &range1 and &range2

new   1:select * from test_normal where empno between 1 and 2300

2300 rows selected.

Elapsed: 00:00:00.02

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=23 Card=2299 Bytes=78166)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_NORMAL' (Cost=23 Card=2299 Bytes=78166)
2    1     INDEX (RANGE SCAN) OF 'NORMAL_EMPNO_IDX' (NON-UNIQUE) (Cost=8 Card=2299)

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
329  consistent gets
15  physical reads
0  redo size
111416  bytes sent via SQL*Net to client
2182  bytes received via SQL*Net from client
155  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
2300  rows processed
为不同的范围集执行这些查询时,结果会显示如下:

位图EMPNO(范围)B-TREE
一致读数物理读数一致读数物理读数
33101-23003290
28508-19802830
346191850-425034416
4273128888-3185042428
3712782900-8547836723
2157149984888-1000000213935

您会发现,这一次两个索引的一致读数和物理读数又几乎一样。最后一个范围 (984888-1000000) 几乎返回 15,000 行,这是针对上面给出的所有范围所取得的行的最大数量。因此,我们请求了全表扫描(通过给出提示 /*+ full(test_normal) */),一致性读数和物理读数的分别为 7,239 和 5,663。

步骤 4A(在 TEST_RANDOM 上)

在这一步中,我们将在具有位图索引的 TEST_RANDOM 表上使用范围谓词运行查询,并检查一致性读数和物理读数。此处您将看到群集因子的影响。

SQL>select * from test_random where empno between &range1 and &range2;
Enter value for range1: 1
Enter value for range2: 2300
old   1:select * from test_random where empno between &range1 and &range2

new   1:select * from test_random where empno between 1 and 2300

2300 rows selected.

Elapsed: 00:00:08.01

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=453 Card=2299 Bytes=78166)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_RANDOM' (Cost=453 Card=2299 Bytes=78166)
2    1     BITMAP CONVERSION (TO ROWIDS)
3    2       BITMAP INDEX (RANGE SCAN) OF 'RANDOM_EMPNO_BMX'

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
2463  consistent gets
1200  physical reads
0  redo size
111416  bytes sent via SQL*Net to client
2182  bytes received via SQL*Net from client
155  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
2300  rows processed

步骤 4B(在 TEST_RANDOM 上)

在这一步中,我们将具有 B-tree 索引的 TEST_RANDOM 上执行范围谓词查询。记住,此索引的群集因子与表中的行数非常接近(且因而无效)。此处是优化程序关于这一点的建议:

SQL> select * from test_random where empno between &range1 and &range2;
Enter value for range1: 1
Enter value for range2: 2300
old   1:select * from test_random where empno between &range1 and &range2

new   1:select * from test_random where empno between 1 and 2300

2300 rows selected.

Elapsed: 00:00:03.04

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=613 Card=2299 Bytes=78166)
1    0   TABLE ACCESS (FULL) OF 'TEST_RANDOM' (Cost=613 Card=2299 Bytes=78166)

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
6415  consistent gets
4910  physical reads
0  redo size
111416  bytes sent via SQL*Net to client
2182  bytes received via SQL*Net from client
155  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
2300  rows processed

此优化程序选择全表扫描,而不是使用索引,原因是群集因子:

位图EMPNO(范围)B-TREE
一致性读数物理读数一致性读数物理读数
246312001-230064154910
2114318-198063894910
257211351850-425064184909
3173162028888-3185064564909
2762135882900-8547864314909
72543329984888-100000072544909

仅对于最后的范围 (984888-1000000),优化程序选择了位图索引的全表扫描,然而,对于所有范围,它选择 B-tree 索引的全表扫描。群集因子是导致这一差异的原因:使用位图索引生成执行计划时,该优化程序不考虑群集因子的值,然而,对于 B-tree 索引,它会考虑群集因子的值。在这种情况下,位图索引执行会比 B-tree 索引更加有效。

下面的步骤列举关于这些索引的值得关注的更多情况。

步骤 5A(在 TEST_NORMAL 上)

在 TEST_NORMAL 表的 SAL 列上创建位图索引。此列具有正常的基数。

SQL> create bitmap index normal_sal_bmx on test_normal(sal);

Index created.

SQL> analyze table test_normal compute statistics for table for all indexes for all indexed columns;

Table analyzed.

现在让我们来获取索引的大小和群集因子。

SQL>select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
2* from user_segments
3* where segment_name in ('TEST_NORMAL','NORMAL_SAL_BMX');

SEGMENT_NAME                                Size in MB
------------------------------              --------------
TEST_NORMAL                                 50
NORMAL_SAL_BMX                              4

SQL> select index_name, clustering_factor from user_indexes;

INDEX_NAME                             CLUSTERING_FACTOR
------------------------------         ----------------------------------
NORMAL_SAL_BMX                         6001
现在开始进行查询,首先使用等式谓词运行它们:
SQL> set autot trace
SQL> select * from test_normal where sal=&sal;
Enter value for sal: 1869
old   1:select * from test_normal where sal=&sal

new   1:select * from test_normal where sal=1869

164 rows selected.

Elapsed: 00:00:00.08

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=39 Card=168 Bytes=4032)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_NORMAL' (Cost=39 Card=168 Bytes=4032)
2    1     BITMAP CONVERSION (TO ROWIDS)
3    2       BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
165  consistent gets
0  physical reads
0  redo size
8461  bytes sent via SQL*Net to client
609  bytes received via SQL*Net from client
12  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
164  rows processed
然后使用范围谓词:
SQL> select * from test_normal where sal between &sal1 and &sal2;
Enter value for sal1: 1500
Enter value for sal2: 2000
old   1:select * from test_normal where sal between &sal1 and &sal2

new   1:select * from test_normal where sal between 1500 and 2000

83743 rows selected.

Elapsed: 00:00:05.00

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=601 Card=83376 Bytes
          =2001024)
1    0   TABLE ACCESS (FULL) OF 'TEST_NORMAL' (Cost=601 Card=83376
Bytes=2001024)

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
11778  consistent gets
5850  physical reads
0  redo size
4123553  bytes sent via SQL*Net to client
61901  bytes received via SQL*Net from client
5584  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
83743  rows processed
现在丢弃位图索引,并在 TEST_NORMAL 上创建一个 B-tree 索引。
SQL> create index normal_sal_idx on test_normal(sal);

Index created.

SQL> analyze table test_normal compute statistics for table for all indexes for all indexed columns;

Table analyzed.
查看索引和群集因子的大小。
SQL> select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
2  from user_segments
3  where segment_name in ('TEST_NORMAL','NORMAL_SAL_IDX');

SEGMENT_NAME                         Size in MB
------------------------------       ---------------
TEST_NORMAL                          50
NORMAL_SAL_IDX                       17

SQL> select index_name, clustering_factor from user_indexes;

INDEX_NAME                           CLUSTERING_FACTOR
------------------------------       ----------------------------------
NORMAL_SAL_IDX                       986778

在上面的表中,您可以看到此索引比相同列上的位图索引大。群集因子也接近此表中的行数。

下面要进行测试了,首先使用等式谓词:

SQL> set autot trace
SQL> select * from test_normal where sal=&sal;
Enter value for sal: 1869
old   1:select * from test_normal where sal=&sal

new   1:select * from test_normal where sal=1869

164 rows selected.

Elapsed: 00:00:00.01

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=169 Card=168 Bytes=4032)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_NORMAL' (Cost=169 Card=168 Bytes=4032)
2    1     INDEX (RANGE SCAN) OF 'NORMAL_SAL_IDX' (NON-UNIQUE) (Cost=3 Card=168)

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
177  consistent gets
0  physical reads
0  redo size
8461  bytes sent via SQL*Net to client
609  bytes received via SQL*Net from client
12  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
164  rows processed
然后,范围谓词:
SQL> select * from test_normal where sal between &sal1 and &sal2;
Enter value for sal1: 1500
Enter value for sal2: 2000
old   1:select * from test_normal where sal between &sal1 and &sal2

new   1:select * from test_normal where sal between 1500 and 2000

83743 rows selected.

Elapsed: 00:00:04.03

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=601 Card=83376 Bytes
          =2001024)
1    0   TABLE ACCESS (FULL) OF 'TEST_NORMAL' (Cost=601 Card=83376
Bytes=2001024)


Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
11778  consistent gets
3891  physical reads
0  redo size
4123553  bytes sent via SQL*Net to client
61901  bytes received via SQL*Net from client
5584  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
83743  rows processed
针对不同的值集执行查询时,输出结果(如下表中所示)揭示一致性读数和物理读数是相同的。

位图
SAL(等式)
B-TREE取出的行数
一致性读数物理读数一致性读数物理读数
16501869177164 
1691633548181167 
1741666500187172 
756970008173 
1771632500190175 

位图
SAL(范围)
B-TREE取出的行数
一致性读数物理读数一致性读数物理读数
11778 5850 1500-2000 11778 3891 83743
11765 5468 2000-2500 11765 3879 83328
11753 5471 2500-3000 11753 3884 83318
17309 5472 3000-4000 17309 3892 166999
39398 5454 4000-7000 39398 3973 500520

对于范围谓词,优化程序选择为所有的不同值集进行全表扫描(它根本不使用索引)然而,对于等式谓词,该优化程序使用索引。和以前一样,一致性读数和物理读数是相同的。

因此,您可以得出结论:对于一般基数列,优化程序针对两种类型索引做出的决策都是相同的,且在输入/输出之间不存在显著的差异。

步骤 6(添加 GENDER 列)

在低基数列上执行测试之前,让我们将一个 GENDER 列添加到此表中,并使用 MFnull 值更新它。

SQL> alter table test_normal add GENDER varchar2(1);

Table altered.

SQL> select GENDER, count(*) from test_normal group by GENDER;

S     COUNT(*)
-     ----------
F     333769
M     499921
      166310

3 rows selected.
此列上的位图索引的大小大约是 570 KB,如下表中所示:
SQL> create bitmap index normal_GENDER_bmx on test_normal(GENDER);

Index created.

Elapsed: 00:00:02.08

SQL> select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
2  from user_segments
3  where segment_name in ('TEST_NORMAL','NORMAL_GENDER_BMX');

SEGMENT_NAME                        Size in MB
------------------------------      ---------------
TEST_NORMAL                         50
NORMAL_GENDER_BMX                   .5625

2 rows selected.
相反,此列上的 B-tree 索引的大小为 13 MB,它比此列上的位图索引要大得多。
SQL> create index normal_GENDER_idx on test_normal(GENDER);

Index created.

SQL> select substr(segment_name,1,30) segment_name, bytes/1024/1024 "Size in MB"
2  from user_segments
3  where segment_name in ('TEST_NORMAL','NORMAL_GENDER_IDX');

SEGMENT_NAME                       Size in MB
------------------------------     ---------------
TEST_NORMAL                        50
NORMAL_GENDER_IDX                  13

2 rows selected.
现在,如果我们使用等式谓词执行查询,则优化程序将不利用此索引,不管它是位图索引或 B-tree 索引。它将选择完全表扫描。
SQL> select * from test_normal where GENDER is null;

166310 rows selected.

Elapsed: 00:00:06.08

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=601 Card=166310 Bytes=4157750)
1    0   TABLE ACCESS (FULL) OF 'TEST_NORMAL' (Cost=601 Card=166310 Bytes=4157750)

SQL> select * from test_normal where GENDER='M';

499921 rows selected.

Elapsed: 00:00:16.07

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=601 Card=499921 Bytes=12498025)
1    0   TABLE ACCESS (FULL) OF 'TEST_NORMAL' (Cost=601 Card=499921Bytes=12498025)

SQL>select * from test_normal where GENDER='F'
 /

333769 rows selected.

Elapsed: 00:00:12.02

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=601 Card=333769 Byte
s=8344225)
1    0   TABLE ACCESS (FULL) OF 'TEST_NORMAL' (Cost=601 Card=333769
Bytes=8344225)
结论

现在我们已经了解优化程序是如何对这些技术作出反应的,接下来让我们分析一种情况,它将清楚地演示位图索引和 B-tree 索引各自的最佳应用。

在 GENDER 列已有位图索引,在 SAL 列上创建另一个位图索引,然后执行某些查询。将针对这些带 B-tree 索引的列重新执行这些查询。

从 TEST_NORMAL 表中,您需要得到月工资为下列任何值的所有男性雇员的数量:

1000
1500
2000
2500
3000
3500
4000
4500
执行:
SQL>select * from test_normal 
where sal in (1000,1500,2000,2500,3000,3500,4000,4500,5000) and GENDER='M';
这是一个典型的数据仓库查询,当然,您应该永远都不会在 OLTP 系统执行该查询。下面是在两个列上都有位图索引时得到的结果:
SQL>select * from test_normal 
where sal in (1000,1500,2000,2500,3000,3500,4000,4500,5000) and GENDER='M';

1453 rows selected.

Elapsed: 00:00:02.03

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=198 Card=754 Bytes=18850)
1    0   TABLE ACCESS (BY INDEX ROWID) OF 'TEST_NORMAL' (Cost=198 Card=754 Bytes=18850)
2    1     BITMAP CONVERSION (TO ROWIDS)
3    2       BITMAP AND
4    3         BITMAP OR
5    4           BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'
6    4           BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'
7    4           BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'
8    4           BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'
9    4           BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'
10    4           BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'
11    4           BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'
12    4           BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'
13    4           BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_SAL_BMX'
14    3         BITMAP INDEX (SINGLE VALUE) OF 'NORMAL_GENDER_BMX'

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
1353  consistent gets
920  physical reads
0  redo size
75604  bytes sent via SQL*Net to client
1555  bytes received via SQL*Net from client
98  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
1453  rows processed
为 B-tree 索引时:
SQL>select * from test_normal 
where sal in (1000,1500,2000,2500,3000,3500,4000,4500,5000) and GENDER='M';

1453 rows selected.

Elapsed: 00:00:03.01

Execution Plan
----------------------------------------------------------
0      SELECT STATEMENT Optimizer=CHOOSE (Cost=601 Card=754 Bytes=18850)
1    0   TABLE ACCESS (FULL) OF 'TEST_NORMAL' (Cost=601 Card=754 Bytes=18850)

Statistics
----------------------------------------------------------
0  recursive calls
0  db block gets
6333  consistent gets
4412  physical reads
0  redo size
75604  bytes sent via SQL*Net to client
1555  bytes received via SQL*Net from client
98  SQL*Net roundtrips to/from client
0  sorts (memory)
0  sorts (disk)
1453  rows processed
正如您此处可以看到的那样,使用 B-tree 索引,优化程序选择了全表扫描,然而在位图索引情形中,它使用索引来响应该查询。您可以根据取出结果所需的输入/输出数量来判断性能高低。

总之,不管基数如何,位图索引最适合于 DSS,原因如下:

  • 使用位图索引,优化程序可以有效地响应包括 AND、OR 或 XOR 的查询。(Oracle 支持 B-tree 到位图的动态转换,但它可能效率很低。)
  • 使用位图,在搜索空值或对其计数时,优化程序可以响应查询。位图索引也可以索引空值(与 B-tree 索引不同)。
  • 最重要的是,DSS 系统中的位图索引支持即席查询,然而,B-tree 索引不支持即席查询。更为特殊的是,如果您有一个具有 50 列的表,且用户经常查询它们中的 10 个(查询全部 10 个或有时查询其中一个),则创建 B-tree 索引将非常困难。如果在所有这些列上创建 10 个位图索引,则所有查询都可以由这些索引来响应,而不管针对全部 10 列的查询,或其中 4 或 6 列的查询,或者是单个列上的查询。AND_EQUAL 提示为 B-tree 索引提供此功能,但一个查询仅能针对少于五个索引。使用位图索引将不会有这一限制。
但 B-tree 索引更适合于 OLTP 应用程序,在该应用程序中用户的查询是相对固定的(并在生产部署之前进行过很好的调整),这与即席查询相反,这些相对固定的查询出现频率更低,且在非高峰工作时间执行。因为数据在 OLTP 应用程序中经常更新,并已从 OLTP 应用程序中删除,所以在这些情形下,位图索引会导致严重的死锁问题。

本文提供的数据能让你清楚的了解各种情况。这两个索引都具有一个相似的目的:尽快地返回结果。但您选择使用哪个索引应该完全取决于应用程序的类型,而不是取决于基数的级别。


25 04, 2005
捕捉变化数据[转贴]
作者 xzh2000 20:10 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

作者:Sanjay Mishra

使用变化数据捕捉特性可以简化数据仓库应用中的ETL过程。

数据提取是所有数据仓储的一个完整组成部分。数据通常是在晚上从事务处理系统中被提取出来并被传输到数据仓库。一般情况下,数据仓库中的所有数据都是由从源系统中提取出的数据来更新。但是在提取和传输海量数据时,资源和时间的消耗都是巨大的。

由于数据提取每日都在进行,因此如果只是提取和加载自上次提取之后发生变化的数据,那么效率就会大大提高。但是,在大多数源系统中,识别并提取最新变化的数据即使是可能的,也非常困难。

除了识别最新变化数据的挑战之外,许多提取、转换和加载(ETL)环境都包含一个源系统,为多个目标系统提供数据。另外,从一个源系统到多个目标系统同步改变数据也是一个挑战。

Oracle变化数据捕捉(Change Data Capture,CDC)特性简化了识别自上次提取后发生变化的数据的过程。CDC提供了易于使用的API来设置CDC环境。 如果你是参与数据集成项目的DBA或开发人员,需要定期从一个系统提取大量数据并将其传输到另一个系统或多个系统,那就赶快考虑使用CDC来缩短ETL的时间吧。

本文将为你提供一种设置CDC环境的循序渐进的方法,概述设置CDC环境的先决条件,并讨论为你的应用程序设置CDC时需要掌握的API。

概述

CDC特性是在Oracle9i数据库中引入的。CDC能够帮助你识别从上次提取之后发生变化的数据。利用CDC,在对源表进行INSERT、UPDATE或DELETE等操作的同时就可以提取数据,并且变化的数据被保存在数据库的变化表中。这样就可以捕获发生变化的数据,然后利用数据库视图以一种可控的方式提供给目标系统。

图 1 给出了CDC环境的基本体系结构。

CDC建立订阅者视图来控制目标系统对变化数据的获取。目标系统是任何需要使用从源系统中捕获的数据的应用程序。

发布者和订阅者

CDC体系结构基于发布者/订阅者模型。发布者捕捉变化数据并提供给订阅者。订阅者使用从发布者那里获得的变化数据。通常,CDC系统拥有一个发布者和多个订阅者。

发布者首先需要识别捕获变化数据所需的源表。然后,它捕捉变化的数据并将其保存在特别创建的变化表中。它还使订阅者能够控制对变化数据的访问。

订阅者需要清楚自己感兴趣的是哪些变化数据。一个订阅者可能不会对发布者发布的所有数据都感兴趣。 订阅者需要创建一个订阅者视图来访问经发布者授权可以访问的变化数据。

Change Data Capture architecture

图1: 变化数据捕捉的体系结构

设置CDC环境

CDC特性是Oracle9i (及更高版本)数据库软件的一部分,你无需安装除Oracle9i外的任何其他软件就可以使用CDC。要使用Oracle9i 数据库的CDC特性,请按下述步骤进行:

  • 启用数据库中的Java功能(Java虚拟机,JVM)。有关配置Oracle JVM的详细说明,请参见《Oracle9i数据库Java开发人员指南》。当使用数据库配置助理(Database Configuration Assistant,DBCA)创建数据库时,你可以选择安装Oracle JVM。

  • 启用系统触发器。当创建数据库时,系统触发器默认情况下是启用的。

一旦你的数据库做好了CDC准备,你就可以按照以下步骤设置CDC环境。

1. 确定源表。
2. 设置发布者。
3. 创建变化表。
4. 设置订阅者。
5. 订阅源表并激活订阅过程。
6. 设置CDC窗口。
7. 准备订阅者视图。
8. 访问变化表中的数据。
9. 删除订阅者视图,并清除CDC窗口。
10. 重复第6到第9步,以查看新数据。

出于本文的目的,我将使用一个销售应用程序作为示例。源应用程序是记录关于每笔销售的信息的事务处理系统。该系统的表的计划所有者是SALES_OP。

我设置一个基于销售运营数据的数据仓库。用户SALES_DW是数据仓库的所有者。我的CDC系统的目的是高效地将变化数据从事务处理系统(SALES_OP拥有的源表)传输到数据仓库系统(SALES_DW拥有的目标表)。 变化数据包括:

  • 自上次提取后在源表中插入(INSERT)的数据;

  • 自上次提取后在源表中更新(UPDATE)的数据;

  • 自上次提取后从源表中删除的(DELETE)的数据。

在下面几节中,我将向你演示如何在源系统中捕捉变化数据并将其提供给目标系统。

1.识别源表

数据库用户SALES_OP拥有两个表:PRICE_LIST和SALES_TRAN。这两个表分别保存已售商品的价格清单和每笔销售交易的细节。

SQL> DESC PRICE_LIST

 Name          Null?     Type
 ----------    -------   -------
 PRODUCT_ID    NOT NULL  VARCHAR2(20)
 UOM           NOT NULL  VARCHAR2(20)
 PRICE_PER_UOM NOT NULL  NUMBER(10,2)

SQL> DESC SALES_TRAN

 Name           Null?    Type

 ----------     -------  -------
 PRODUCT_ID     NOT NULL VARCHAR2(20)
 SALE_DATE_TIME NOT NULL TIMESTAMP(6)
 QUANTITY       NOT NULL NUMBER(10,2)

每天早上,这两个表中发生变化的数据必须被提取出来并传送到数据仓库系统。

2.设置发布者

发布者是创建和维护变化表的数据库用户。正如前面提到的,发布者的职责是识别并提取变化数据,并将其提供给订阅者。要做到这一点,必须给发布者分配以下两个数据库角色:

  • SELECT_CATALOG_ROLE
  • EXECUTE_CATALOG_ROLE

为了简单起见,让用户SALES_OP 充当发布者的角色。因为SALES_OP拥有源表,所以将其指定为发布者会比较简单。不过,你也可以指定任何其他数据库用户为发布者。在由多个数据库用户拥有的表构成源表的情况下,最好指定另一个用户作为发布者。在这种情况下,该用户需要在源表上有SELECT权限。

3.创建变化表

每个源表都需要一个变化表。发布者使用DBMS_LOGMNR_CDC_PUBLISH .CREATE_CHANGE_TABLE过程来创建变化表,如清单 1所示。在这个例子中,与PRICE_LIST和 SALES_TRAN 相对应的变化表分别被命名为CDC_PRICE_LIST和CDC_SALES_TRAN。

CREATE_CHANGE_TABLE 过程将变化集的名字作为一个变量来传递。一个变化集是一个变化表的集合。 在清单 1中,我使用了系统生成的变化集:SYNC_SET。

4.设置订阅者

在我的例子中,目标系统SALES_DW是订阅者。为了能够订阅变化数据,订阅者必须在源表和变化表上有SELECT权限,如下所示:

connect sales_op/sales_op

grant select on PRICE_LIST to sales_dw;
grant select on SALES_TRAN to sales_dw;
grant select on CDC_PRICE_LIST 
  to sales_dw;
grant select on CDC_SALES_TRAN 
  to sales_dw;

5.订阅源表并激活订阅过程

在典型的CDC环境中会有多个订阅者,每个订阅者只需要订阅自己所需要的表。此外,订阅者可能不希望看到自己所订阅的表的所有字段。

在可以订阅发布的数据之前,你需要得到一个订阅句柄。订阅句柄使订阅者能够管理自己感兴趣的变化表和字段。在Oracle的CDC环境中,一个订阅只能由一个订阅句柄识别,而无论你订阅了多少个表,你只需创建一个订阅句柄。 使用DBMS_LOGMNR_ CDC_SUBSCRIBE.GET_SUBSCRIPTION HANDLE过程就可以得到一个订阅句柄。这个过程以变量的方式返回句柄值。你可以在你的会话中定义一个变量来接收来自过程的句柄值,如下所示:

variable sh_sales number;
EXECUTE - 
DBMS_LOGMNR_CDC_SUBSCRIBE

  .GET_SUBSCRIPTION_HANDLE( -
    CHANGE_SET=>'SYNC_SET', -
    DESCRIPTION=>'Change data from 
Sales Appln.', -
    SUBSCRIPTION_HANDLE=>:sh_sales);

一旦你建立了句柄,你就可以订阅你想要的变化数据。当订阅变化数据时,需要指定你希望订阅的表和字段,如下所示:

EXECUTE DBMS_LOGMNR_CDC_SUBSCRIBE
  .SUBSCRIBE( -
    SUBSCRIPTION_HANDLE=>:sh_sales, -
    SOURCE_SCHEMA=>'SALES_OP', -
    SOURCE_TABLE=>'PRICE_LIST', -

COLUMN_LIST=>'PRODUCT_ID,UOM,
PRICE_PER_UOM');


EXECUTE DBMS_LOGMNR_CDC_SUBSCRIBE
  .SUBSCRIBE( -
    SUBSCRIPTION_HANDLE=>:sh_sales, -
    SOURCE_SCHEMA=>'SALES_OP', -
    SOURCE_TABLE=>'SALES_TRAN', -
    COLUMN_LIST=>'PRODUCT_ID,SALE_DATE_TIME,
QUANTITY');

当指定了希望订阅的表和字段后,你就可以激活你的订阅。无论订阅多少个表,你都只需要激活订阅一次。一旦激活了一个订阅,你就不能再将任何其他表或字段添加到你的订阅中。为了激活订阅,你可以调用将订阅句柄作为参数调用DBMS_LOGMNR_CDC_SUBSCRIBE.ACTIVATE_ SUBSCRIPTION过程,并将订阅句柄传递给它:EXECUTE - DBMS_LOGMNR_CDC_SUBSCRIBE .ACTIVATE_SUBSCRIPTION( - SUBSCRIPTION_HANDLE=>:sh_sales)。

6. 设置CDC窗口

源表中的数据不断变化(插入、更新或删除) ,而不管对变化数据的订阅。因此,订阅要设置(扩展)一个窗口――CDC窗口,通过该窗口可以看到任何变化。DBMS_LOGMNR_CDC_SUBSCRIBE.EXTEND_WINDOW过程可以被用来设置CDC窗口,如下所示:

EXECUTE -
DBMS_LOGMNR_CDC_SUBSCRIBE.EXTEND_WINDOW( -
    SUBSCRIPTION_HANDLE=>:sh_sales); 

当你执行了EXTEND_WINDOW过程后,如果你没有清除窗口并再次对它进行扩展,那么对源表所做的改变在订阅中就无法看到(后面对此有更详细介绍)。

7.准备一个订阅者视图

一旦你设置了CDC窗口,你就需要为订阅者准备一个视图,以便订阅者能够看到变化数据。你需要为订阅者订阅的每个源表准备一个视图。DBMS_LOGMNR_CDC_SUBSCRIBE.PREPARE_SUBSCRIBER_VIEW过程可以被用来准备一个订阅者视图。你需要将订阅句柄、源模式名和源表名传递给该过程,该过程就会以变量的方式返回订阅者视图的名字。在本例中,源表PRICE_LIST和SALES_TRAN 的订阅者视图名分别以变量sv_price_list 和sv_sales_tran返回。

variable sv_price_list varchar2(30);

EXECUTE -
DBMS_LOGMNR_CDC_SUBSCRIBE
  .PREPARE_SUBSCRIBER_VIEW( -
    SUBSCRIPTION_HANDLE =>:sh_sales, -
    SOURCE_SCHEMA=>'SALES_OP', -
    SOURCE_TABLE=>'PRICE_LIST', -
    VIEW_NAME => :sv_price_list); 

variable sv_sales_tran varchar2(30);

EXECUTE -

DBMS_LOGMNR_CDC_SUBSCRIBE
  .PREPARE_SUBSCRIBER_VIEW( -
    SUBSCRIPTION_HANDLE =>:sh_sales, -
    SOURCE_SCHEMA=>'SALES_OP', -
    SOURCE_TABLE=>'SALES_TRAN', -
    VIEW_NAME => :sv_sales_tran); 

你可以从这两个变量中得到视图名。视图名是系统产生的,一般包括一个CDC前缀和一个数字。例如:

SQL> select :sv_price_list from dual;

:SV_PRICE_LIST
----------------
CDC#CV$1430621

SQL> select :sv_sales_tran from dual;

:SV_SALES_TRAN
-----------------
CDC#CV$1430623

8.访问变化表中的数据

订阅者视图包含你所需要的变化数据。它还包含使用变化数据所需的其他一些附加信息:

SQL> desc CDC#CV$1430621

 Name         Null?     Type
----------    -------   --------
 OPERATION$	        CHAR(2)	
 CSCN$                  NUMBER
 COMMIT_TIMESTAMP$      DATE
 TIMESTAMP$             DATE
 USERNAME$              VARCHAR2(30)
 PRICE_PER_UOM          NUMBER(10,2)
 PRODUCT_ID             VARCHAR2(20)
 UOM                    VARCHAR2(20)

例如,字段OPERATION$ 表示变化是INSERT、UPDATE还是DELETE。字段CSCN$、COMMIT_TIMESTAMP$、TIMESTAMP$和USERNAME$表示是谁在源表中做的改变以及是何时做的。其他字段是源表中订阅的字段。你可以使用SELECT语句查看订阅者视图中的数据,例如:

SQL> select * from CDC#CV$1430621;


OP PRICE_PER_UOM   PRODUCT_ID   UOM
-- ------------    ------------ ----
I  2.99            P101         pound
I  4.99            P102         pound

9.删除订阅者视图,清除CDC窗口

下一步

阅读关于变化数据捕捉的更多信息
Oracle9i数据仓储指南第2版(9.2)
Oracle9i提供的PL/SQL包和类型参考第2版(9.2)

otn.oracle.com/documentation

当你了解并提取了变化数据并且不再需要在订阅者视图中显示变化数据时,你需要删除订阅者视图并清除CDC窗口,这样你才可以建立(扩展)新的窗口来查看新的变化数据。删除已有的订阅者视图,使用DBMS_LOGMNR_CDC_SUBSCRIBE.DROP_SUBSCRIBER_VIEW过程。在你可以清除旧的CDC窗口并建立新窗口之前,你需要逐个删除子订阅的每个订阅者视图。

EXECUTE -

DBMS_LOGMNR_CDC_SUBSCRIBE
  .DROP_SUBSCRIBER_VIEW( -
    SUBSCRIPTION_HANDLE =>:sh_sales, -
    SOURCE_SCHEMA=>'SALES_OP', -
    SOURCE_TABLE=>'PRICE_LIST');

EXECUTE -
DBMS_LOGMNR_CDC_SUBSCRIBE
  .DROP_SUBSCRIBER_VIEW( -
    SUBSCRIPTION_HANDLE =>:sh_sales, -
    SOURCE_SCHEMA=>'SALES_OP', -
    SOURCE_TABLE=>'SALES_TRAN');

删除订阅者视图后,你就可以清除窗口。使用DBMS_LOGMNR_CDC_SUBSCRIBE. PURGE_WINDOW过程来清除窗口:

EXECUTE -
DBMS_LOGMNR_CDC_SUBSCRIBE.PURGE_WINDOW( -
    SUBSCRIPTION_HANDLE=>:sh_sales);

10.重复第6到第9步以查看新数据

要定期提取变化数据,你需要重复第6到第9步。如果你每日都要提取变化数据,你的每日(最好在晚上)数据提取工作将包括建立订阅窗口(EXTEND_WINDOW)、准备订阅者视图(PREPARE_SUBSCRIBER_VIEW)、从订阅者视图中访问数据、删除订阅者视图(DROP_SUBSCRIBER_VIEW)、清除窗口(PURGE_WINDOW)。

步骤总结

第1步到第5步是配置步骤,对于一个给定的发布者/订阅者环境只需要设置一次。定期执行第6到第9步,以从源系统中提取越来越多的变化数据。

Sanjay Mishra (smishra_tech@yahoo.com) 已经与人合著了3本关于Oracle的书:《Oracle并行处理》《Oracle SQL Loader:权威指南》和《掌握Oracle SQL》,这三本书全部由O'Reilly and Associates出版。


25 04, 2005
关于提取,存储与索引[转贴]
作者 xzh2000 20:05 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

作者:Tom Kyte

我们的技术专家按顺序提取、按列存储、全局索引。

我们遇到一个有关PL/SQL块中ORA-01002错误的问题。我们了解到,在对所选的数据进行更新,如在使用SELECT进行UPDATE操作的特殊情况下,有时会发生这种错误。但这里的情况并非如此。奇怪的是我们只有在从一个指针中读取数据,而没有对该指针数据进行任何更新时才会遇到这一错误。在执行一个回滚到保存点语句时会发生这一错误:

 查看全文
25 04, 2005
中国获俄新潜射导弹[转]
作者 xzh2000 19:14 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
有评论昨天提供的消息指出,大陆已从俄罗斯接收了首批射程达220公里的3M-54E型潜艇发射反舰导弹。这种导弹可能对美国航空母舰特混舰队构成实质威胁。

该消息表示,俄罗斯NOVATOR导弹设计局总设计师Gorbarenko Vliacheslav接受访问时证实,中国大陆海军近日已收到第一批3M-54E潜对舰导弹。Gorbarenko拒绝透露中国一共接收了多少数量的导弹。

据说,这些反舰导弹专供俄罗斯基洛级(KILO)潜艇使用;中国大陆一共购买了8艘能够发射3M-54E的基洛636潜艇,并从去年底起交货,预计今年是交货高峰期。每艘基洛级636携带4枚3M-54E导弹。

该消息表示,这是东亚地区国家首次获得这种高性能的远端潜水艇发射导弹。目前只有印度海军装备这种型号的导弹。

该消息认为,中国大陆在获得这种型号的导弹之后,大大强化了对美军的远端投射力量,并且达到了实战标准,配合相当安静的基洛级潜舰,有可能对美海军航母特混舰队构成实质性威胁。

25 04, 2005
AIX中的网络管理[转贴]
作者 xzh2000 15:36 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

 Chap 11 Networking
11.1 适配卡、接口、和配置问题
11.1.1添加一个网络适配卡(network adapter)
如果系统不支持热插拔卡,则要关闭和重启系统。
1、 检查系统上已安装的适配卡
#lscfg |grep –i adaper
2、 检查已定义的接口
#lsdev –Cc if
3、 关闭系统并下电(对于支持热插拔功能的系统,则不用关闭系统)
4、 安装新的网络适配卡
5、 加电到正常模式
6、 系统启动时自动运行cfgmgr命令,会自动检测新装的网络适配卡并且添加相应的接口。
注意:如果系统运行完cfgmgr命令后,提示一下信息:系统里没有安装某设备驱动包
则你必须把这些驱动包安装到系统中去。
7、 重新运行lscfg 和lsdev确认网络适配卡已经正常地添加到系统中去。
11.1.2移除一个网络适配卡
在移除一个网络适配卡之前,要记得先用ifconfig命令来删除系统中该网络适配卡和网络接口的定义。
ifconfig Interface [  AddressFamily [ Address [DestinationAddress ] ] [Parameters… ]  ]
主要参数:
alias:网络接口别名
delete:删除接口的网络地址
detach:从网络接口列表里删除一个接口
down:使网络接口不活动
mtu Value:设置mtu值
netmask Mask:网络掩码
up: 激活接口
步骤:操作之前,确认没有应用或进程在使用你准备要移除的网络接口上,同时系统可能需要重启机器。
1、 使接口不活动
#ifconfig Interface down
2、 删除网络接口列表里所有的网络接口定义
#ifconfig Interface detach
3、 从系统中删除网络接口定义
#redev –dl Interface
4、 删除网络适配卡的定义
#rmdev –dl Adapter
5、 关闭系统并下电
6、 移除该网络适配卡
7、 系统加电
11.1.3适配卡和接口配置问题
网速(Ring and media speed)配置问题
更正网速问题步骤:
1、 从网管那里获得正确的网络速度
2、 移除所有的网络接口
#ifconfig Interface detach
3、 使用smit chgtok-令牌环网卡(或者smit chgnet-以太网卡)
有相应的Ring speed或Media speed选项。
线缆类型配置问题:
smit tcpip里有Your CABLE Type选项
网络接口的MTU大小问题:
网络包长度可以从60 bytes到65535 bytes大小不等,缺省情况下,16Mb的令牌环网络接口的传输包大小是1492 bytes,而一个以太网接口是1500 bytes大小。
在同一个本地网中,网络通信包需要同样大小的MTU。
调整MTU大小步骤:
1、 检查一个网络接口的MTU大小
#lasttr –El Interface
2、 使网络接口不活动
#ifconfig Interface down
3、 用ifconfig来调整MTU值
#ifconfig Interface mtu Value
如:#ifconfig en0 mtu 1500
也可以用chdev命令来调整MTU
#chdev –l Interface –a mtu=Value
11.2 TCP/IP
11.2.1 TCP/IP 的初始化
/etc/rc.tcpip脚本:
与tcp/ip有关的守护进程:inetd、gated、routed、named、timed、rwhod。
注意:在一台主机里不能同时运行gated和routed守护进程,或者会带来不可意料的结果。
还有一些进程是从/etc/rc.tcpip脚本去启动的:lpd、portmap、sendmail、syslogd。
注意:如果在系统启动的时候/etc/rc.tcpip脚本在/etc/inittab中没有被初始化,而且你有一个图形界面,则要确认你的/etc/rc.dt(也是在/etc/inittab脚本里)没有被初始话,或者你的控制台会被挂起,而且由于telnet、rlogin等连接通讯工具没有被初始化,所以你没办法恢复。
11.2.2启动和关闭tcp/ip守护进程
1、 启动和关闭某一进程
#startsrc(stopsrc)  –s Daemon
2、 关闭所有的tcp/ip守护进程
#stopsrc –g tcpip
3、 像在系统启动过程中(IPL)过程中启动所有的tcp/ip守护进程一样,
#/etc/rc.tcpip
注意:不要用#startsrc –g tcpip命令来启动所有的tcp/ip守护进程,因为这样会启动定义在ODM中的所有属于tcpip组的守护进程,包括routed和gated服务进程。
11.2.3inetd守护进程
#列出inetd里启动的子守护进程
#lssrc –ls inetd
刷新inetd进程
#refresh –s inetd
11.2.4inetd及其子进程的错误
1、 首先用ping检查网络的连通性
2、 检查inetd是否有启动起来,包括它的子守护进程如telnet、ftp、rlogin、rexec等。
3、 如果以上都没有问题,则要检查是否虚终端(pseudo-terminal)是否够用。
#smit chgpty
缺省情况下,但一个rloing、telnet、rsh命令在系统中打开一个会话时,或者在图形终端中打开一个shell窗口时,系统会产生(spwan)一个虚终端会话。
11.3 IP地址、网关和子网
11.3.1 IP地址
A、B、C、D类地址
Netstat命令:
-rn:可以查看网络接口的路由表。
-in:可以查看网络接口信息,包括MTU大小、IP地址、流经网络接口(流入、流出)的数据包数量。
改变网络接口的状态:
1、 使网络接口不活动
#ifconfig tr0 down
#netstat –ni  可以看到该接口带*号,但#netstat –rn没变化
2、 删除网络接口
#ifconfig tro detach
这时,用netstat –ni或-rn都看到变化。
3、 重新激活或添加原来删除(detached)的网络接口
#ifconfig tr0 up
11.3.2网关
使用traceroute命令
定义一个缺省网关
#route add net 0 9.3.1.74
(或者也可以用#route add default 9.3.1.74)
11.3.3子网及子网掩码的问题
不同子网的网络地址是不能相连通的。
11.4网络配置文件
本节讨论的所有文件需要权限设置为600并且所有者是root。
1、/etc/resolv.conf和/etc/netsvc.conf文件
作为DNS(域名服务)的配置文件,前者指定域名服务器的IP地址(注意是IP地址而不是hostname),并且指定该系统所在的域。
后者指定域名解析(for sendmail,the gethostbyname,gethostaddr,and gethostent subroutines,and alias resolution for sendmail)的顺序。
缺省顺序:
1、 BIND/NDS(named, 使用/etc/resolv.conf文件)
2、 NIS
3、 Local /etc/hosts文件
格式如下:
#cat /etc/netsvc.conf
hosts = nis,local,bind
也可以指定环境变量NSORDER来指定解析顺序:
#echo $NSORDER
NSORDER=local,bind
2、/etc/hosts
指定主机名和别名(aliases)和IP地址的对应关系。
3、$HOME/.netrc
用于指定rexec和ftp命令自动登录的认证信息,该文件用明文存储了登录口令。所有远程系统的口令信息对于有root权限的用户是暴露的。
4、/etc/hosts.equiv和$HOME/.rhosts文件
用于定义信任主机(远程主机用户登录本地主机时不要提高口令认证)
文件格式如下:
[+|-] HostName [+|-] UserName or @NetGroup
注意:由于文件是从上往下顺序读的,因此条项的顺序不同可能导致不同的结果。
如:为了允许用户ethan从主机H70登录则:
ethan H70
11.5 输出X-Windows和图形应用
在Aix中,可以通过指定DISPLAY环境变量来输出X-Windowns会话和图形应用到别的系统上。
DISPLAY环境变量格式:
HostName:Number.Screen
11.5.1启动X-Windows应用失败
检查以下三项:
1、 DISPLAY环境变量是否设置
2、 X-Windows 服务是否已经启动
3、X-Windows准入控制已经启用,则要确认远程系统在准入列表(access control list)
中。
对于第三条,可以使用xhost +命令:
#xhost +
#xhost +H70A
H70A being added to access control list
#xhost
access control enabled,only authorized clients can connect INET:H70A
11.6网络高级配置选项
11.6.1ARP缓存
arp命令,-a和-d选项。
11.6.2检测网络瓶颈
1、使用spray命令:
-c Count:指定发送数据包的数量
-d Delay:指定发送发送数据包中间的时延,以毫秒记
-i: 指定使用ICMP代替RPC协议来回应数据包。
#spray H70A –c 1200 –d 2
2、使用netstat命令:
可以使用#netstat –i来查看,使用-Zi来清零网络接口的统计信息。
3、 使用topas命令
#topas –d0 –i0 –p0
11.6.3 no命令介绍
no {-a | -d Attribute | -o Attribute [=NewValue] }
-a:列出属性值
-d Attribute:设置属性值回缺省值
-o Attribute [=NewValue]: 设置属性值为一个新的指定值,如果没有指定New Value,则显示属性的原有值。
比如:
1、 IP forwarding
#no –o ipforwarding   (maybe output 0)
#no –o ipforwarding=1
2、 Route revalidation(路由重定向)
#no –o routerevalidation=1
11.6.4网络调优
网络传输也是使用实际内存作为communication pool(包括mbufs和clusters)
thewall:mbuf pools分配到的最大数量的内存(以kB为单位),在no命令里称为thewall参数。


25 04, 2005
volume manage笔记[转贴]
作者 xzh2000 15:30 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
一、获取机器ID和机器类型的命令
#hostid
#uname -i
二、添加License的命令
#vxlicense -c
三、查看License的命令
# vxlicense -p
四、名词解析
VRTSvxvm      VxVM软件
VRTSlic         VxVM licensing utilities
VRTSvmdoc      VxVM电子文档
VRTSvmman     VxVM帮助手册
VRTSvmdev      VxVM developer’s package
VRTSvxsa        VxVM图形管理界面
VRTSvxfs        VxFS软件
VRTSfsdoc       VxFS文档
五、添加VxVM和VxFS包
#mount –F hsfs –o ro /dev/dsk/c0t6d0s2 /mnt
# pkgadd –d path_name product_packages
注意:要以超级用户权限登录系统,完了后还要重启系统。
六、安装VxFS后,修改/etc/system ,在里面添加一行:
set lwp_default_stksize=0x4000
  并将原始的文件拷贝一份。    
七、检查安装包:
#pkginfo   列出所有安装的包
#pkginfo | grep VRTS  列出安装的VERITAS的包
#pkginfo –l pkckage 列出某个安装包的详细信息
八、用vxinstall来创建rootdg 。
选择Custom安装。
九、显示执行过的命令:
#tail  –f  /var/opt/vmsa/logs/command
十、命令行
在如下几个目录中,可以找到在命令行中使用的命令:
/etc/vx/bin
/usr/sbin
/usr/lib/vxvm/bin
注:把这些目录加入到PATH环境变量中去。
十一、几条常用命令:
vxassist 、vxprint 、vxdg 、vxdisk
十二、检查是否有别的VMSA版本存在:
      #pkginfo –l | grep vmsa
      如果有则删除:
      #pkgrm VRTSvmsa
十三、启动VMSA
1.以root用户登录;
2.#./vmsa_server &
3.xhost + system_name (这一步有时需要做)
4.DISPLAY=’uname –n ‘:0.0 ;export  DISPLAY(这一步有时需要做)
十四、启动VMSA客户端
1.本地启动:# vmsa
2.远程启动:# vmsa  remote_machine_name
十五、几个命令
1.确定VMSA是否运行:# vmsa_server  -q
2.停止VMSA服务:   # vmsa_server  -k
3.显示VMSA运行版本:# vmsa_server  -v
4.启动自动模式:# autostart  on
5.显示当前运行模式:# netstat -a | grep vmsa
6.改变自动模式:# autostart  off
7.运行在只读模式下:# vmsa_server  -r  & 和# vmsa  -r  &
十六、添加磁盘的方法:(行命令)
1.vxdisksetup :configures a disk for VxVM
2.vxdg addisk :add a disk to a disk group
3.# /etc/vx/bin/vxdisksetup –i disk_address [attributes]
注:The disk_address defines the controller , target , and SCSI logical unit number of the disk to be set up and takes the form c # t # d # . The –i option writes a disk header to the disk , making the disk derectly usable .
4.# vxdg –g diskgroup adddisk disk_name=device_name
十七、查看磁盘信息(命令行)
1.vxdisk  list :list disk information
2.prtvtoc :Display VTOC configuration
3.vxdisk –o alldgs list :show all disk groups in the output .
4.# vxdisk list disk_name :显示某个磁盘的信息。
5.# prtvtoc physical_disk_path
6.# prtvtoc /dev/rdsk/c1t10d0s2
注:注意磁盘在卷中和不在卷中,prtvtoc命令结果显示的不同。
十八、Evacuating a disk // remove a disk(命令行)
1.vxevac –g diskgroup from_diskname to_diskname
2.例子:# vxevac –g datadg datadg02 datadg03
3.vxdg rmdisk :returns a disk to the free disk pool
4.vxdiskunsetup :returning a disk to an uninitialized state
5.vxdg –g diskgroup rmdisk disk_name
6.例子:# vxdg –g newdg rmdisk newdg02
7./etc/vx/bin/vxdiskunsetup –[C] disk_address
8.例子:# vxdiskunsetup c1t0d0
十九、给磁盘重命名(命令行)
1.# vxedit –g diskgroup rename old_diskname new_diskname
2.Using vxdg deport and vxdg import rename a disk group
二十、The rootdg disk group cannot be destroyed and must exist on every system , because it is an essential part of the VxVM boot process .
二十一、创建磁盘组(命令行)
1.vxdg init diskgroup disk_name=device_name
2.# vxdg init newdg newdg01=c1t1d0s2
二十二、创建备用磁盘
# vxdg –g diskgroup set spare=on|off disk_media_name
二十三、Deporting a disk group(命令行)
1.# unmount /filesystem(先卸载磁盘组上的文件系统)
2.# vxdg deport diskgroup
3.# vxdg –n new_name deport old_name(deport and rename a disk group)
4.# vxdg –h hostname deport diskgroup(deport to a new host)
二十四、Importing a disk group(命令行)
1.# vxdg import diskgroup
2.# vxdg –n new_name import old_name(import and rename a disk group)
http://www.uxma.com/sheke/news/pic/8.swf
3.# vxdg –t –n temp_name import old_name(import and rename temporaily)
4.# vxdg –tC –n newerdg import newdg(clear import locks,add the –C option)
5.# vxdg –f  import newdg(force an import)
二十五、Rename a disk group:CLI
1.# vxdg –n new_name deport old_name
2.# vxdg import new_name
以上是第一种方式
3.# vxdg deport old_name
4.# vxdg –n new_name import old_name
5.# vxvol –g diskgroup_newname  startall(在命令行中重命名磁盘组后要重启volume)
二十六、Destroying a disk group
# vxdg destroy diskgroup
二十七、查看磁盘组信息
1.vxdisk  –s  list 显示磁盘组名和ID
2.vxdisk –o alldg list 显示所有磁盘组的信息,包括已经destroy的。
3.vxdg –g diskgroup free 显示磁盘组中的free space 。
4.vxdg free
二十八、显示磁盘组的版本
1.# vxdg list diskgroup
2.# vxprint -l
二十九、升级磁盘组版本
1.vxdg [-T version] upgrade diskgroup
2.# vxdg  –T 40 upgrade datadg(把datadg从20升级到40)
3.# vxdg upgrade datadg(把datadg升级到当前的版本90)
4.# vxdg  -T  50  init  newdg  newdg01=c0t3d0s2(创建版本为50的磁盘组)

24 04, 2005
配置NFS服务stepbystep
作者 xzh2000 19:24 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
1、NFS包
-----------
NFS需要5个RPM,分别是:
setup-* : 共享NFS目录在/etc/exports中定义
initscripts-* : 包括引导过程中装载网络目录的基本脚本
nfs-utils-* : 包括基本的NFS命令与监控程序
portmap-* : 支持安全NFS RPC服务的连接
quota-* : 网络上共享的目录配额,包括rpc.rquotad (这个包不是必须的)

2、基本监控程序
-------------------
要顺利运行NFS,至少需要五个Linux服务,它们各有不同的功能,有的负责装载服务,有的保证远程命令指向正确的位置。这些服务通过/etc/rc.d/init.d目录中的nfs,nfslock和portmap脚本启动。下面简单介绍每个监控程序:
(1) 基本NFS
rpc.nfsd是NFS服务器监控程序,它通过/etc/rc.d/init.d目录中的nfs脚本启动。NFS监控程序还启动rpc.mountd装载监控程序,并导出共享目录。

(2) RPC装载
可以用mount命令连接本地目录或网络目录,但还需要一个装载NFS目录的特殊监控程序rpc.mountd

(3) 端口映射器
portmap监控程序只是定向RPC通信数据流,但它对于NFS服务很重要。如果不运行portmap,则NFS客户机无法找到从NFS服务器共享的目录。

(4) 重新启动与statd
当NFS服务需要中断或者重新启动时,rpc.statd监控程序和rpc.lockd在服务器重新启动之后使客户机恢复NFS连接。

(5) 锁定
通过共享NFS目录打开文件时,锁定可以使用户不能覆盖同一个文件。锁定通过nfslock脚本并使用rpc.lockd监控程序启动运行。

3、配置NFS
-------------
共享的NFS目录在/etc/exports中列出,这个文件控制对目录的共享。书写规则是:(每个共享规则一行)
共享目录 主机(参数)
例如:
/mnt/cdrom *.abc.com(ro,sync) master.abc.com(rw,sync)
上面的规则代表将/mnt/cdrom目录以只读同步方式共享给*.abc.com域,并且以读写同步方式共享给master.abc.com主机。

任何共享目录都要指定sync或async,也就是指定文件写入磁盘之前共享NFS目录是否响应命令。

下面是一些NFS共享的常用参数:
ro    只读访问
rw    读写访问
sync    所有数据在请求时写入共享
async    NFS在写入数据前可以相应请求
secure    NFS通过1024以下的安全TCP/IP端口发送
insecure    NFS通过1024以上的端口发送
wdelay    如果多个用户要写入NFS目录,则归组写入(默认)
no_wdelay    如果多个用户要写入NFS目录,则立即写入,当使用async时,无需此设置。
hide    在NFS共享目录中不共享其子目录
no_hide    共享NFS目录的子目录
subtree_check    如果共享/usr/bin之类的子目录时,强制NFS检查父目录的权限(默认)
no_subtree_check    和上面相对,不检查父目录权限
all_squash    共享文件的UID和GID映射匿名用户anonymous,适合公用目录。
no_all_squash    保留共享文件的UID和GID(默认)
root_squash    root用户的所有请求映射成如anonymous用户一样的权限(默认)
no_root_squas    root用户具有根目录的完全管理访问权限
anonuid=xxx    指定NFS服务器/etc/passwd文件中匿名用户的UID
anongid=xxx    指定NFS服务器/etc/passwd文件中匿名用户的GID


4、启动NFS
--------------
# service portmap start
# service nfs start


检查NFS的运行级别:
# chkconfig --list portmap
# chkconfig --list nfs

根据需要设置在相应的运行级别自动启动NFS:
# chkconfig --level 235 portmap on
# chkconfig --level 235 nfs on


另外,还需要查看系统的iptables、/etc/hosts.allow、/etc/hosts.deny是否设置了正确的NFS访问规则。

21 04, 2005
我老婆是买的[长篇连载]
作者 xzh2000 19:30 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

http://www.bucuo.com.cn/book/11200.html

好心的村民为孤儿丁念然买了房媳妇,但被丁念然放了,他觉得无颜面对关心他的人,所以走出了山,经过不懈的努力终于在北京站住了脚,在这里,竟然又与他买的媳妇碰面了~~~


15 04, 2005
Unix痛恨者手册.4[转贴]
作者 xzh2000 19:50 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
第九章 编程

“牛牛别怕,不疼的。”

别惹Unix,它弱不禁风,动不动就吐核(core dump)

——无名氏

如果你是通过在Unix上写C代码而学会的编程,那么可能会觉得这一章有些别扭。不幸的是,Unix如此广泛地被应用到了科研教育领域,很少有学生能意识到Unix的许多设计并不是严瑾合理的。

例如,听了我们关于有许多语言和环境比C/Unix要好的说法后,一个Unix爱好者是这么为Unix和C辩护的:

日期: 1991 Nov 9
发信人:
tmb@ai.mit.edu (Thomas M. Breuel)

Scheme, Smalltalk和Common Lisp这些语言确实提供了强大的编程环境。但是Unix内核,shell和C语言则针对的是更为广泛的问题空间,而这些问题不是上面那些语言所擅长的(有的根本就无法处理)。

这些问题空间包括内存管理和局部性(locality)(在进程的产生和终止中实现),、持续性(persistency)(使用文件存储数据结构),并行性(parallelism)(通过管道,进程和进程通讯机制来实现),保护和恢复(通过独立的地址空间实现),以及可直观读取的数据表现方式(使用文本文件实现)。从实用的角度来看,Unix能很好地处理这些问题。

Thomas Breuel夸奖Unix能够解决复杂的计算机科学问题。幸运的是,这不是其他科学领域用来解决问题的方法。

日期: Tue, 12 Nov 91 11:36:04 -0500
发信人:
markf@altdorf.ai.mit.edu
收信人: UNIX-HATERS
主题: Random Unix similes (随机的Unix笑脸)

通过控制进程的产生与终止来进行内存管理,这就如同通过控制人的生死来对付疾病——这忽视了真正问题。

通过Unix文件获得持续性就如同把你所有的衣服仍进衣柜,幻想着能从里面找到需要的衣服(不幸的是,我正是这么去做的)。

通过管道,进程和进程通讯机制来实现并行化?Unix进程的代价是如此之高,以至于并行化得不偿失。就象是鼓励员工多生孩子,以解决公司人力资源短缺问题。

不错,Unix当然可以处理文本。他还能处理文本。嗯,还有,我有没有提到过Unix能够很好地处理文本?

——Mark

蔚为壮观的Unix编程环境

Unix狂热分子们总在宣扬Unix的所谓“编程环境”。他们说Unix提供了丰富的工具,能够使得编程工作更为容易。这是Kernighan和Mashey在《Unix编程环境》一文中的说法:

Unix环境最能提高编程效率,这归功于众多的又小又有用的程序——工具,这些工具为日常的编程工作提供帮助。下面列举的这些程序被认为是其中最为有用的。我们在下文中将以他们为例说明其他观点。

wc files —— 统计文件中的行数,字数和字符数。
pr files —— 打印文件,支持标题和多栏打印。
lpr files —— 打印文件
grep pattern files —— 找到符合某种模式的文件行。

许多程序员的工作就是用它们和一些其他相关程序完成的。例如:

wc *.c

用于对所有C源代码文件进行代码量统计;

grep goto *.c

用于找到所有的goto语句。

这些就是“最为有用的”?!?!

有道理。这就是程序员的日常工作。事实上,今天我就用了不少时间来统计我的C代码量,以至于没有多少时间去做其他事情。等一下,我想我还得再数一遍。

同一期《IEEE计算机》上还有一篇文章,是Warren Teitelman和Larry Masinter写的《Interlisp编程环境》.Interlisp是个极为复杂的编程环境。1981年Interlisp就有了Unix程序员到了1984还在梦想的工具。

Interlisp环境的设计者们使用的是完全不同的方法。他们决定开发一个复杂的工具,需要花不少时间来掌握,好处是一旦学会了,极大地提高编程效率。听上去有些道理。

悲哀的是,今天很少有程序员能体会使用这类环境的感觉了。

在柏拉图的洞穴里编程

我总有一种感觉,计算机语言设计和工具开发的目标应该是提高编程效率而不是降低。

——comp.lang.c++上的一个贴子

计算机以外的其他产业早就体会到了自动化的意义。当人们走进快餐点,他们需要的是一致标准的东西,而不是什么法国大菜。大规模地提供一致的一般食物,这比小批量的精耕细作要赚钱得多。

——netnews上一个技术人员的回复

Unix不是世界上最好的软件环境——它甚至不是一个好的环境。Unix编程工具又简陋又难用;Unix调试器和PC上的没法比;解析器(interpreters)仍然是富人的玩具;修改日志(change log)和审记(audit trail)总是想起来才去做。可Unix仍然被当成程序员的梦。也许它只能让程序员梦到了效率的提高,而不是真的提高效率。

Unix程序员有点象数学家。你能从他们身上观察到一个神秘现象,我们称之为“空头编程”(Programming by Implication)。一次我们和一个Unix程序员聊天,谈到需要这样一个工具,能够回答诸如“函数foo被谁调用过?”或者“那个函数改变过全局变量bar”之类的问题。他也认为这个工具会很有用,提议到,“你们可以自己写一个。”

公平地说,他之所以只是说“你们可以自己写一个”而不是真正写一个,这是因为C语言的一些特性和Unix“编程环境”的强强联手,使得写这样的程序难于上青天。

使用yacc进行解析(parsing with yacc)

"Yacc"就是我用过yacc(1)之后想喊的。

——匿名

"YACC"是再一个编译编译器的编译器(Yet Another Compiler Compiler)的意思。它接受与上下文无关(context-free)的语法,构造用于解析的下推自动机(pushdown automaton)。运行这个自动机,就得到了一个特定语言的解析器。这一理论是很成熟的,因为以前计算机科学的一个重要课题就是如何减少编写编译器的时间。

这个方法有个小问题:许多语言的语法不是与上下文无关的。这样yacc的使用者不得不在每一个状态转换点上加上相关代码,以处理和上下文有关的部分(类型检查一般就是这么处理的)。许多C编译器使用的都是yacc生成的解析器;GCC 2.1的yacc语法有1650行之多 (如果不用yacc,GCC应该能成为自由软件基金会不错的作品)。由yacc生成的代码就更多了。

有些编程语言的语法比较容易解析。比如,Lisp能够用一个递归下降解析器进行解析。“递归下降”是一个计算机术语,含义是“喝杯可乐的功夫就能实现”。作为试验,我们写了一个Lisp递归下降解析器,只用了250行C代码。如果是用Lisp写的,那么一页纸也用不了。

在上面提到的那个计算机科学原始时代,这本书的编辑还没有生出来呢。计算机房是恐龙的天下,“真正的人”都在用仪表盘上的开关来编程。今天,社会学家和历史工作者想破脑袋也无法理解为什么理智的程序员却设计、实现和传播了如此难解析的语言。也许他们那时候极需一个困难的研究项目,设计一个难于解析的语言似乎是个不错的课题。

一直想知道他们在那个时代吃的是什么药。

上面提到的那个工具类似于一个C编译器的前端。C编译器前端是个极其复杂的东西,这是C的复杂语法和yacc的使用造成的。没有人真正动手去写一个这样的工具,这还有什么奇怪的么?

死硬的Unix分子会说你不需要这么一个程序,因为有grep就足够了。而且,你还能在shell管道中使用grep。有一天,我们想找出BSD内核源码中所有使用min函数的地方。这是其中一个结果:

% grep min netinet/ip_icmp.c
icmplen = oiplen + min(8, oip->ip_len);
* that not corrupted and of at least minimum length.
* If the incoming packet was addressed directly to us,
* to the incoming interface.
* Retrieve any source routing from the incoming packet;
%

挺不错的吧,grep找到了所有的min函数调用,而且还不止这些。

“不知道怎么做爱。我撤。”("Don't know how to make love. Stop.")

理想的编程工具应该是这样的,它能让简单的问题保持简单,让复杂的问题有解决的可能。不幸的是,许多Unix工具过分追求通用性,而忽视了简洁。

Make就是这样一个典型。从抽象意义而言,make的输入是一个倚赖关系的描述。倚赖图上的每个节点都对应这一组命令,当节点过期时(由它所倚赖的节点来决定),这些命令会被执行。节点和文件相关,文件的修改时间决定了节点是否过期。下面是一个简单的倚赖关系图,也就是Makefile:

program: source1.o source2.o
cc -o program source1.o source2.o

source1.o: source1.c
cc -c source1.c

source2.o: source2.c
cc -c source2.c

这里program, source1.o, source2.o, source1.c,source2.c就是关系图上的节点。节点program倚赖于source1.o和source2.o。

如果source1.o或source2.o比program要新,make便会运行命令cc -o program source1.o source2.o重新生成program。当然,如果修改了source1.c,那么source1.o和program都会过时,所以make会重新进行编译和链接。

尽管make的模型很通用,可惜设计者从没有考虑过简单性。不过,许多Unix新手都能体会到make能多么简单地“钻”(screw)了他们。

继续我们上面的那个例子,假定有个程序员Dennis想调试source1.c,于是要编译使用调试选项。他修改了一下Makefile:

program: source1.o source2.o
cc -o program source1.o source2.o

# I'm debugging source1.c
source1.o: source1.c
cc -c source1.c
source2.o: source2.c
cc -c source2.c

"#"打头的那行是注释,会被make忽略。可怜的Dennis运行了一下make,这是它得到的:

Make: Makefile: Must be a speparator on line 4.
Stop

make歇菜了。Dennis盯着Makefile看了有好几分钟,又看了几小时,还是不明白哪儿出错了。他觉得是注释行的问题,可不是很肯定。

毛病出在当他加入注释行时,他不小心在第二行开始的制表符(tab)前敲入了一个空格。制表符是Makefile语法的一个重要部分。所有的命令行(例子中cc开始的行)必须以制表符打头。这就是Dennis的Makefile不工作的原因。

“那又怎样?”你可能会说,“这有什么不对的?”

它本身没什么不对。不过如果你想一下其他Unix编程工具的工作方式,就会觉得制表符语法就好象《地雷战》里的头发丝雷,看上去一马平川,踩上去呜呼哀哉。

你知道,制表符、空格符和换行符一般被统称为“白字符”(whitespacecharacters)。“白字符”意味着“你可以放心大胆地忽略它”许多程序正是这么做的,对空格和制表符一视同仁。就make孤芳自赏桀骜不驯鹤立鸡群冰清玉洁众人皆醉唯我独醒。于是我们这位Dennis兄弟恐怕只能给自己脑袋来一枪,告别这悲惨的Unix世界。

可怜的Dennis最终也没有找到自己那个Makefile的毛病,他现在落魄到只好去给一个中西部州立大学维护sendmail配置文件。默哀三分钟。

头文件

C语言有个东西叫头文件,里面是一些说明信息,在编译时被源文件使用。和Unix上的其他玩意一样,如果只有一个两个,可以工作得很好,多了就没戏了。

要知道你的源文件该使用那个头文件,这可不是件容易事。头文件是C预处理器(preprocessor)根据#include指令(directive)加载的。这个指令有两个用法:

#include <header1.h>



#include "header2.h"

这两种用法的区别和各个C预处理器的实现有关,也就是说,任何实现都可以大着胆子撒着欢儿由着性子乱来。

让我们来看看Dennis的朋友Joey,Joey也是个Unix新手。Joey有个C程序foo.c,使用了foo.h中定义的一些数据结构, foo.c和foo.h放在了同一个目录下。你可能已经知道"foo"是程序员常用的名字。Joey机器上的系统程序员也做了一个foo.h文件,并把它放到了缺省系统头文件目录/usr/include

倒霉蛋Joey编译了foo.c,得到一堆语法错误。他迷惑不解,编译器总在他定义的一些数据结构处报错,可是这些数据结构在foo.h里被定义的好好的呀。

你我估计能猜到Joey的问题在哪儿,他一定是这么加载头文件的:

#include <foo.h>

而不是写成:

#include "foo.h"

可Joey不知道这个。也可能他确实是用的引号方式,只是他的编译器的查找方式有些特别。不管怎样,Joey是被干掉了,很无辜地被干了。

维护很多头文件是件挺头疼的事,不幸的是,如果你写个有用点儿的C程序,这是不可避免的。头文件一般 于定义数据结构,一个头文件往往倚赖于其他一?头文件。去把那些头文件的倚赖关系整理一下,你这回可不愁没事儿做了。

当然,编译器会帮你的。如果你把倚赖关系搞错了,编译器会毫不留情地指出语法错误。记住,编译器是个很忙很有身份的程序,它没时间去区分未定义的数据结构和输入错误的区别。事实上,即使你只是忘了敲个分号,C编译器也会恼羞成怒,立马撂挑子不干了。

在编译器社区,这一现象被称为“错误雪崩”,或者按照编译器自己的说法:“我完蛋了,起不来了。” 缺个分号会把解析器彻底搞晕,狂吐不止。这个解析器很可能是用yacc写成的,yacc对语法正确的程序(很少见的一种情况)处理得很好,但要让它生成健壮容错自动恢复的解析器,这就有点儿勉为其难了。有经验的C程序员都知道只有第一条解析错误才是有意义的。

工具程序和Man手册

Unix工具是自成一体的;可以任意解释命令行参数。这样的自由有些烦人;别以为学会了一套命令行规则就一劳永逸了,你必须去读每个命令的Man手册,才能知道如何去使用。

知道有那么多清楚明白的Man手册供你参考,你一定很开心吧。

看一下下面这个例子。“摘要”一栏总结得挺不错的,是不是?

LS(1) Unix程序员手册 LS(1)

名称
ls - 列出目录内容

摘要
ls [ -acdfgilqrstu1ACLFR ] 名称 ...

描述
对于每个目录参数,ls列举那个目录的内容;对于每个文件参数,
ls 给出文件名以及要求的其他信息。缺省情况下,输出将按照字
母顺序排列。如果没有参数,则列举当前目录的内容。如果有不只
一个参数,这些参数首先会被适当排序,但是文件参数总是会被排
在目录参数前面。

ls有很多选项:

[ ... ]

BUGS
文件名中的换行符和制表符会被可打印字符

输出设备会被假设有80列宽

输出会根据输出设备的不同而不同,比如"ls -s"的结果和"ls -s| lpr"的结果不一样。这是不正确的,然而如果不这么做,一些倚赖这个功能的旧有shell脚本就会完蛋。

如果你想玩个游戏,不妨读一下每个Man手册的BUGS部分,然后想像一下每个bug是如何造成的。看一下这个shell的man手册:

SH(1) Unix程序员手册 SH(1)

名称
sh, for, case, if, while, :, ., break, continue, cd,
eval, exec, exit, export, login, read, readonly, set,
shift, times, trap, umask, wait - 命令语言

摘要
ls [ -ceiknrstuvx ] [参数] ...

描述
Sh是一个命令程序语言,它执行来自终端或文件的命令。下面是各
个选项的说明。

[ ... ]

BUGS

如果把使用<<提供的标准的输入提供给使用&运行起来的非同步的进程,shell会搞不清楚输入文档的名字。会生成一个垃圾文件/tmp/sh*,shell会抱怨找不到使用另外一个名字的文档。

我们用了好几分钟也没搞明白这个bug究竟是他妈什么意思。一个Unix专家看过之后说:“我边看边挠脑袋,有写这段BUGS的功夫,估计足够这家伙改掉这个吊玩意了。”

不幸的是,修改bug几乎是不可能的,因为它会随着每个新发布的操作系统而卷土重来。在80年代早期,在这些bug还没有被Unix信徒奉为神圣以前,一个BBN的程序员真的修改了伯克利make的这个制表符bug。这不是很难,也就是几行代码的事儿。

和所有责任感的公民一样,BBN的骇客们把补丁发给了伯克利,希望能把它加入主Unix代码中。一年过后,伯克利发布了新版本的Unix,make的这个bug还是存在。BBN的骇客第二次做了修改,又把补丁交给了伯克利。

....然而伯克利的第三次发布还是老样子,BBN的程序员彻底失望了。他们没有再提交补丁,而是把他们所有的Makefile中空格打头的行替换成了制表符。毕竟BBN雇佣他们是来写新程序的,而不是反复修改同一个bug。

(据说,Stu Felman(make的作者)一开始就查觉到了这个问题,他没有修改,因为那时已经有10个用户开始用了。)

源码就是文档。哇~~ 牛逼!

如果我写着不容易,那么你理解起来就不应该容易。

—— 一个Unix程序员

我们在《文档》一章里提到Unix程序员认为操作系统的源代码是最好的文档。一个著名的Unix历史学家曾经指出:“毕竟,操作系统自己也是靠读源代码来知道下一步该干嘛的。”

可是通过阅读源代码来理解Unix,这就如同开着Ken Thompson的老爷车(对,就是闪着大红问号的那辆)周游世界。

Unix内核源码(更准确的说,是ftp.uu.net上发布的伯克利网络磁带2版的代码)几乎没有注释,充斥这大"段"没有空行的代码,goto 随处可见,绞尽脑汁给妄图读懂它的人制造麻烦。有个骇客感叹到:“阅读Unix代码就好象走在伸手不见五指的巷子里。我总是停下来摸摸口袋,脑子里回响着一个声音‘老天,我就要遭劫了。’”

当然,内核代码有它自己的警报系统。四处散布着这样的小小注释:

/* XXX */

意思是有什么东西不太对劲儿。你应该知道哪儿出事儿了。

这绝不可能是bug,我的Makefile需要它!

BBN的程序员应该算是另类。大部分Unix程序员是不去修改bug的:他们没有源代码。即使修改了也于事无补。这就是为什么Unix程序员遇到bug的第一个反应不是修了它,而是绕过它。

于是我们看到了悲惨的一幕:为什么不一劳永逸地解决问题,而是一错再错?也许早期的Unix程序员是尼采“永恒轮回”思想的信徒。

对于调试方法,存在着两个截然不同的派别:一个是“外科手术派”,包括流行于早期ITS和Lisp系统,程序运行过程中始终有调试器参与,如果程序崩溃了,调试器(也就是所谓外科大夫)会对问题进行诊断医治。

Unix是属于更古老的“尸体解剖派”。Unix下如果一个程序崩溃了,会遗留下一个core文件,从各个方面看这都和尸体没什么两样。Unix调试器然后会找出死因。有趣的是,Unix程序常常和人一样,死于本可治疗的疾病、事故以及疏忽。

对付Core

如果你的程序吐核(core)了,你首先要做的是找到它。这不该太困难,因为core文件总是很大——4, 8, 甚至12兆。

core文件之所以这么大,是因为它包括了所有用来调试的信息:堆栈,数据,代码指针等等,无所不包,除了程序的动态状态。如果你在调试一个网络程序,在你的程序吐核的时候,已经为时太晚了;程序的网络连接已经没有了,更致命的一击是,所有打开的文件现在都被关上了。

不幸的是,在Unix上只能如此。

例如,不能把调试器作为命令解析器,或者在内核发生异常时把控制交给调试器。如果想让调试器在程序崩溃时进行接管,那你只能在调试器里面运行所有程序(是的,有的Unix版本让你用调试器接管一个运行中的进程,但是你手边必须有一个还有符号的程序文件)。如果你想调试中断代码,你的调试器必须截获每个中断,然后把合适的中断返回给程序。你能想像emacs里每敲一键都发生3个进程切换(context switch)的感觉么?显然,例程调试(routine debugging)思想和Unix哲学是格格不入的。

日期: Wed, 2 Jan 91 07:42:04 PST
发信人: Michael Tiemann <cygint!tiemann@labrea.stanford.edu>
收信人: UNIX-HATERS
主题: Debuggers (调试器)

想过Unix调试器为什么这么蹩脚么?这是因为如果它想提供什么功能,那一定会跟来一堆bug,如果有bug,它一定会吐核(dump core),如果它吐核,靠,你用来调试的那个core文件就会被覆盖。如果能让程序来控制如何吐核,何时吐核,以及吐在哪里,那就太好了。

bug骨灰盒

和其他操作系统不同,Unix把bug供奉为标准操作。之所以那么多Unix bugs得不到修正,这里有个不可告人的原因——如果修正了,那么已有的一些程序就会死逼了。然而,荒唐的是,Unix程序员在增加新功能时却从来不去考虑向下兼容。

考虑到这些,Michael Tiemann给出了Unix调试器覆盖core文件的10个理由:

日期: Thu, 17 Jan 91 10:28:11 PST
发信人: Michael Tiemann <tiemann@cygnus.com>
收信人: UNIX-HATERS
主题: Unix Debuggers (Unix调试器)

David Letterman (美国著名晚间脱口秀主持人)的10个最佳理由是:

10. 这会破坏已有代码。
9. 这需要修改文档。
8. 太难实现了。
7. 这怎么是调试器的活儿?为什么不写个“工具”做它?
6. 如果调试器吐了核,你应该丢开你自己的程序,开始调试调试器。
5. 太难理解了。
4. 哪儿有饼干?
3. 为什么非得现在做?
2. Unix也不是神仙。
1. 哪儿有问题?

Unix程序员总是打着“这会破坏已有代码”的幌子,不愿意修正bug。可这里面还有内幕,修正bug不但会破坏已有代码,还必须修改简单完美的Unix 接口,而这正是Unix教众们的命根子。至于这个接口是否工作,这并不重要。Unix教众们不去提出更好的接口,也不去修正bug,而是齐声高唱 “Unix接口好简洁,好简洁。Unix接口就是美,就是美!Unix无罪!Unix有理!”。

不幸的是,绕过bug是个很恶劣的行为,它使得错误成为了操作系统规范的一部分。你越是等,就越难以修正,因为越来越多的程序会尽力绕过bug,以至于没有了bug反而活不了了。同理,修改操作系统接口带来的影响更大,因为更多的程序必须根据这个正确的新接口进行修改。(这解释了为什么ls有那么多的选项来完成几乎一样的工作)。

如果你把一只青蛙仍到开水里,它会马上跳出来。它知道开水很烫。可是,如果你把青蛙放到冷水里,再慢慢地加热,青蛙感觉不到什么,直到最后被烫死。

Unix接口已经开锅了。以前,输入/输出的全部接口只包括open, close, read和write。网络支持给Unix添了一大把柴禾。现在,至少有五种方法向一个文件句柄输入数据:write, writev, send, sendto和sendmsg。每个都在内核中有不同的实现,这意味着有五倍的可能出现bug,有五种不同的性能结果需要考虑。读文件也一样(read, recv, recvfrom和recvmsg)。等死吧,青蛙们。

文件名扩展

Unix“所有程序自成一体”的规定有一个例外。Unix程序经常要处理一个或多个文件。Unix shells提供了命名一组文件的方法,shell会把这组文件展开,做为一个文件列表传递给各个命令。

例如,假设你的目录下有文件A, B和C。如果象删除所有这些文件,你可以运行rm *。shell会把"*"扩展成为"A B C",并把他们做为rm的参数传递给它。这个方法有不少问题,这在上一章已经提到过了。不过,你应该知道让shell来扩展文件名不是偶然的:而是精心设计的结果。在Kernighan和Mashey发表的《Unix编程环境》一文中(IEEE计算机杂志,1981年四月),他们指出:“把这个作为 shell的一个机制,这避免了各个程序的重复劳动,而且保证了为所有程序提供一致的输入。” (Unix的一个理想是让任何人能够运行任何shell。现在你没法运行任何shell;你的shell必须提供文件名扩展)。

别忙。标准输入/输出库(Unix所谓的stdio)不就能“为所有程序提供一致的输入”么?提供一个用于扩展文件名的库函数不就成了?这些家伙没有听说过链接库么?那些关于性能的说法也是无稽之谈,因为他们无法提供任何的性能数据,他们甚至没有说明“性能指标”是什么。指的是开发一个小程序会快一些?还是指能高性能地把一个新手的所有文件一扫而光?

大多数情况下,让shell进行文件名扩展也无所谓,因为这和程序自己扩展的结果没什么不同。可是,和Unix上的许多玩意一样,它早晚会咬你一口,而且不轻。

假设你是个Unix新手,目录下有两个文件A.m和B.m。你习惯了MS-DOS,想把它们的名字换成A.c和B.c。嗯~~ 没找到rename命令,不过mv命令似乎差不多。于是你执行mv *.m *.c。shell将这个命令扩展为 mv A.m B.m,你辛辛苦苦写了几小时的B.m就这么被干掉了。

再好好思考一下上面这个问题,你就会发现理论上你完全不可能提供一个和MS-DOS "rename"一样的功能。对于软件工具,就扯这么多吧。

健壮性,或者说“所有输入行必须小于80个字符”

1990年11月份的《ACM通讯》上登了Miller Fredriksen等人写的一篇精采文章,题目是《Unix工具的稳定性的经验性研究》。他们使用一些随机数据作为Unix工具的输入,发现有24- 33%(不同的Unix发布结果有所不同)的工具崩溃了。有时候甚至整个系统都完蛋了。

文章是以一个笑话开头的。其中一位作者曾使用一个极差的电话连接工作,发现许多工具都垮掉了。于是他决定针对这一现象进行更系统的调查研究。

许多bug都可以归因于C语言的陈规陋习。事实上,Unix的许多内在脑损伤都是C语言造成的。Unix的核心以及所有的工具程序都是用C语言写的。著名语言学家Benjamin Whorf说过:语言决定思想。Unix有深深的C烙印。C语言使得程序员根本无法想像能写出健壮的程序。

C语言是极小的。它被设计成能在各种硬件上快速地进行编译,所以它有着和硬件类似的结构。

Unix诞生之初,使用高级语言编写操作系统是个革命性的想法。现在则应该考虑使用一种有错误检查的语言了。

C是个最为底层的语言,诞生于硬件更为底层的时代。PDP-11没有的,C语言也不会有。过去几十年的编程语言研究表明,语言中加入错误处理,自动内存管理和抽象数据类型等功能,会使得开发出的程序更为健壮可靠。你在C里面找不到这些东西。C语言太流行了,没人去考虑给它增加诸如数据标记或硬件垃圾回收支持等功能。即使硬件提供了垃圾回收功能,也只是多费了一些硅片罢了,因为许多C语言编写的程序根本无法使用它。

回想一下,C是无法处理整数溢出的。解决方法是使用超过问题需要的整数大小,希望这个大小在你有生之年足够用。

C也没有真正意义上的数组,它有个象是数组的东西,实际不过是一个指向一块内存的指针。数组定位表达式(array[index])不过是表达式 (*(array+index))的简写版。所以你甚至可以说index[array],这和表达式(*(array+index))是一个意思。聪明吧?在字符处理时经常能见到这个用法。数组变量和指针变量经常可以互换。

举个例子,假设你有:

char *str = "bugy";

于是下面的这些语句都是一样的:

0[str] == 'b'
*(str+1) == 'u'
*(2+str) == 'g'
str[3] == 'y'

C语言够伟大的吧?

这个做法的问题是C根本不做任何自动数组边界检查。为什么该C去做呢?数组在C里只是个指针而已,你可以把指针指向内存的任何地方,是不是?不过,一般你不想在内存里乱写乱画,特别在是一些关键的地方,比如程序的堆栈。

这把我们引到了Miller的文章里提到的一类bug。许多程序是在读取输入到堆栈上的一块字符缓冲区时崩溃的。许多C程序是这么做的;下面的C程序把一行输入读到堆栈上的一个数组里,然后调用do_it函数进行处理。

a_function()
{
char c, buff[80];
int i = 0;

while ((c = getchar()) != 'n')
buff[i++] = c;
buff[i] = '00';
do_it(buff);
}

这类代码把Unix搞得臭不可闻。知道为什么缓冲区被定为80个字符么?这是因为许多Unix文件每行最多有80个字符。知道为什么没有边界检查,也没有文件尾检查么?这是因为这个程序员喜欢把c = getchar()这样的赋值语句嵌入到while循环中。信不信,有些人还推崇C的这种缩简写法,管他妈什么可读性可维护性。最后,调用do_it(),数组摇身一变成了指针,作为第一个参数传了进去。

作为练习:如果在一行当中到达了文件尾,这个程序的结果是什么?

当Unix用户查觉到这个内置的限制后,他们想到的不是去修正这个bug,而是想方设法躲过它。比如,Unix的磁带备份工具(tape archiver)tar不能处理超过100个字符的路径名(包括目录)。解决方法是:不要备份目录到磁带,或者使用dump。更好的办法是:不要建立太深的目录,这样文件的绝对路径就不会超过100个字符。

2038年1月18日上午10点14分07秒,Unix马虎编程将在这一刻上演精采的一幕,那时Unix的32位timeval将耗尽...

再回到我们前面那个例子,假设输入行有85个字符。这个函数毫无问题地接受了这个输入,可问题是最后那5个字符会被放到哪里呢?答案是它们会占据任何排放在数组后面的5个字节。之前那里放着的是什么呢?

c和i这两个变量可能会被分配在字符数组之后,所以有可能会被85字符长的输入冲垮。如果输入了850个字符呢?则可能会毁掉堆栈上的重要的C运行环境系统信息,比如返回地址等。毁掉这些信息的最好结果是程序可能崩溃。

我们说“可能崩溃”是因为程序的编写者从没想到过你竟能毁掉堆栈。想像一下我们的这个程序读入了很长的一行,约有2,000个字符,这行字符被用来覆盖堆栈上的返回地址以及其他环境信息,它将调用2,000个字符里埋藏的一段代码。这段代码可能会做一些很有用的事情,比如执行(exec)出一个 shell,运行一些命令。

Robert T. Morris的著名Unix蠕虫病就是使用了这个机制(以及其他一些技巧)黑进Unix主机的。我不知道其他人为什么还会这么做,真的不知道,嘻嘻。

日期: Thu, 2 May 91 18:16:44 PDT
发信人: Jim McDonald <jlm%missoula@lucid.com>
收信人: UNIX-HATERS
主题: how many fingers on your hands? (你共有几根手指?)

icon_sad.gif 下面是给我的上司的一个报告:

一个用来更新Make文件的程序使用了一个指针,对它的访问毁掉了一个存放倚赖关系的数组,这个倚赖关系被用来生成Makefile。直接后果是生成的错误Makefile不能用于编译任何东西,没有生成所需的对象文件(.o),所以编译最终失败了。一天的工作就这么付之东流了,只是因为一个傻瓜认为10个头文件足够所有人使用了,然后对它进行了极其危险的优化以在1毫秒内生成所有的Make文件!

网络化的坏处是,你没法再闯进某人的办公室里把他的心给挖出来。

(关于堆栈溢出攻击,可参考经典论文href=http://www.phrack.org/phrack/49/P49-14>

Smashing The Stack For Fun And Profit --me)

异常处理

编写健壮程序的最大挑战是如何正确处理错误和其他异常。不幸的是,C几乎没有为此提供什么帮助。今天在学校里学会编程的人里很少有谁知道异常是什么。

异常是函数无法正常运行时所产生的一个状态。异常经常发生在请求系统服务时,比如分配内存,打开文件等。由于C没有提供异常处理支持,程序员必须自己在服务请求时加入异常处理代码。

例如,下面是所有C语言课本中推荐的使用malloc()分配内存的方法:

struct bpt *another_function()
{
struct bpt *result;

result = malloc(sizeof(struct bpt));
if (result == 0) {
fprintf(stderr, "error: malloc: ???n");

/* recover gracefully from the error */
[...]
return 0;
}
/* Do something interesting */
[...]
return result;
}

another_function函数分配了一个类型为bpt的结构,返回了一个指向这一结构的指针。这段代码说明了如何分配内存给这个结构。因为C没有显式的异常处理支持,C程序员必须自己去做这件事(就是粗体的那些代码)。

当然你可以不这么干。许多C程序员认为这是小事一桩,从来不做异常处理。他们的程序往往是这样的:

struct bpt *another_function()
{
struct bpt *result = malloc(sizeof(struct bpt));

/* Do something interesting */
[...]
return result;
}

多么简单,多么干净,大多数系统服务请求都会成功的,是不是?这样的程序在大多数场合运行良好,直到它们被应用到复杂特殊的地方,往往就会神秘地失效。

Lisp的实现总是包括一个异常处理系统。异常条件包括OUT-OF-MEMORY这样的名称,程序员可以为特定的异常提供异常处理函数。这些处理函数在异常发生时被自动调用——程序员不需要介入,也不需要做特殊的检查。适当地使用,可以让程序更为健壮。

CLU这样的编程语言也有内置的异常处理。每个函数定义都有一系列可以发出的异常条件。对异常的显式支持可以帮助编译器检查那些未被处理的异常。CLU程序总是十分健壮,因为编译器逼着CLU程序员去考虑异常处理问题。C程序是个什么样子呢:

日期: 16 dec 88 16:12:13 GMT
主题: Re: GNU Emacs
发信人:
debra@alice.UUCP

<448@myab.se>
lars@myab.se (Lars Pensy)>写到:
... 所有的程序都应该检查系统调用(如write)的返回结果,这非常重要。

同意,可不幸的是很少有程序在进行读(read)写(write)时这么做。

Unix工具程序一般会检查open系统调用的返回值,假设所有随后的read,write和close总会成功。

原因很明显:程序员很懒,不做错误处理程序会显得更小更快。(这样你的系统会有更优异的性能表现)。

这封信的作者继续指出,由于大部分系统工具不对write()等系统调用的返回值进行检查,系统管理员就必须保证文件系统时时刻刻都有足够的空间。正是如此:许多Unix程序假设它们可以写任何成功打开的文件,想写多少就写多少。

读到这里你可能会皱眉头,"嗯~~”一下。最为可怕的是,就在《Unix工具的稳定性的经验性研究》这篇文章的前几页,登载了一份报告,说明休斯顿外层空间中心的飞船控制实时数据采集系统是如何转型为Unix系统的。"嗯~~”

捕捉bug是社会所不能接收的

不去检查和报告bug,这会使制造商生产的系统显得似乎更为健壮和强大。更重要的是,如果Unix系统报告每一个错误,那么就根本不会有人去用它!这是活生生的现实。

日期: Thu, 11 Jan 90 09:07:05 PST
发信人: Daniel Weise <daniel@mojave.stanford.edu>
收信人: UNIX-HATERS
主题: Now, isn't that clear? (现在明白了么?)

惠普做了一些工作,这样我们的惠普Unix系统能够报告一些可能会影响它的网络错误。这些惠普系统和SUN, MIPS, DEC工作站共享一个网络。我们经常会发现其他机器所引发的问题,可是当我们通知给那些机器的主人时(因为这些系统不报告错误,他们不知道自己的机器有一半时间是用在重发数据包上了),他们往往反称是我们这里的问题,因为只有我们这里报出了错误。

“两国相争,不斩来使”,不过在Unix世界里,你最好别当信使。

修不了?重启!

如果某个关键软件不能适当处理错误的数据和操作条件,那么系统管理员该如何是好呢?嗯~~,如果它能在一段时间里正常工作,你就能通过不断重启它来凑合着运行。这个法子不是很可靠,也不具有扩展性,不过足够让Unix苟 硬写 一阵子了。

下面就是这么一个例子,说明如何在named程序不稳定的情况下提供邮件服务:

日期: 14 May 91 05:43:35 GMT
发信人:
tytso@athena.mit.edu (Theodore Ts'o) (著名的Ted Ts'o? --me)
主题: Re: DNS performance metering: a wish list for bind 4.8.4
(DNS性能测试:bind 4.8.4的期待功能表)
收信人: comp.protocols.tcp-ip.domains

我们现在是这么解决这个问题的:我写了一个叫"ninit"的程序以非精灵(deamon)模式(nofork)运行named,然后等待它退出。当named退出时,ninit重新启动一个新的named。另外,每隔五分钟,ninit会醒来一次发给named一个SIGIOT信号,named接到这个信号后会包一些状态信息写入/usr/tmp/named.stats文件中。每隔60秒钟,ninit会用本地named进行一次域名解析。如果短时间内没有得到结果,它会杀掉named,重新启动一个新的。

我们在MIT的名称服务器上和我们的邮件网关(mailhub)上运行了这个程序。我们发现它很有用,能够捕捉named的神秘死亡或僵死。这在我们的邮件网关上更是不可缺少,因为即使域名解析中断一小会儿,我们的邮件队列也会给撑炸了。

当然,这类办法会引发这样的问题:如果ninit有bug,那么该怎么办呢?难道也要写一个程序不断重启ninit么?如果写了,你又如何保证那个正常工作呢?

对于软件错误的这种态度并不少见。下面这个man手册最近出现在我桌上。我们还不能肯定这是不是个玩笑。BUGS部分很是发人深省,因为那里列举的bug是Unix程序员总也无法从代码中剔除的:

NANNY(icon_cool.gif Unix程序员手册 NANNY(icon_cool.gif

名称
nanny - 奶妈,运行所有服务的服务

摘要
/etc/nanny [switch [argument]] [...switch [argument]]

描述
许多系统都为用户提供各种服务(server)功能。不幸的是,这些服务经常不明不白地罢工,造成用户无法获得所需要的服务。Nanny(奶妈)的作用就是照看(babysit)好这些服务,避免关键服务的失效,而不需要系统管理员的随时监视。

另外,许多服务使用日志文件作为输出。这些数据常会很讨厌地充满磁盘。可是,这些数据又是重要的跟踪记录,应该尽量保存。Nanny会定期把日志数据重定向到新文件。这样,日志数据被化整为零,旧的日志文件就能被任意转移走,而不对服务构成影响。(现在这成了logrotate的任务 --me)

最后,nanny还提供了一些控制功能,使得系统管理员能够对nanny以及它所照看的服务进行运行时操作。

选项
...

BUGS
有个服务在nanny中做分离fork(detaching fork)。nanny会错误地认为这个服务死掉了,不断重启它。

到目前为止,nanny还不能容忍配置文件的错误,如果配置文件的路径不对或者内容有错误,nanny必死无疑。

不是所有的选项都被实现了。

Nanny倚赖系统提供的网络功能进行进程间通讯。如果网络代码有错误,nanny将无法处理这些错误,可能僵死或是死循环。

对不稳定软件经常重启,这已经成了MIT雅典娜计划(Project Athena)的日常工作,现在他们每星期天的凌晨4点都会重启AFS(Andrew File System, 一种网络文件系统)服务器。但愿没有人周末熬夜赶写下周一要交的作业...

怎么样,Unix编程很有趣吧?惊险,刺激,痛并快乐!该回家了,休息一下,大麻没劲了,有海洛英;C用腻了,我们还有C++!放心,离死不远了。

第十章 C++
90年代的COBOL

问:"C"和"C++"的名字是怎么来的?
答:这是他们的成绩

——Jerry Leichter

再没有比C++更能体现Unix“绝不给用户好脸”的哲学思想的了。

面向对象编程可以追溯到60年代的Simula语言,在70年代的Smalltalk语言上得到极大发展。许多书会告诉你面向对象语言如何能提高编程效率,使代码更健壮,和减少维护费用。不过你甭想在C++里得到这些。

这是因为C++根本就没理解面向对象的实质。非但没有简化什么,反而增加了更多的复杂性。和Unix一样,C++从没被好好设计过,它从一个错误走向另一个错误,是件打满补丁的破衣服。连自己的语法都没有严格定义(没一个语言敢这样),所以你甚至无法知道一行代码是不是合法。

把C++比做COBOL,其实是对COBOL的污辱。COBOL在那个时代的技术条件下,是做出了很不同凡响的贡献的。如果有谁用C++做成过什么事,那就算是很不同凡响了。幸运的是,很多不错的程序员知道必须尽量避免C++的伤害,他们只用C,对那些荒唐费解的功能敬而远之。通常,这意味着他们必须自己写个非面向对象的工具,以获得自己想要的功能。当然,他们的代码会显得极为怪异,失去兼容性,难于理解和重用。不过只要有一点儿C++的味道,就足够说服头头批准他们的项目。

许多公司已经被多年遗留下来的混乱难懂的COBOL代码搞得焦头烂额了。那些转而使用C++的公司刚刚意识到自己上了当。当然,这已经太晚了。软件灾难的种子已经播下了,浇水施肥,得到悉心照料,就等着十几年后长成参天大树了。等着瞧吧!

面向对象的汇编语言

C++没有一丝一毫高层次语言的特性。为什么这么说?让我们看看高层次语言应该具备那些特性:

优雅:在表示方式及其所表达的概念之间有着简单易懂的关系
抽象:高层次语言的每个表达式只表示一个概念。概念能够被独立表达并能自由使用
强大:高层次语言的能够对任何精确完整的程序行为进行提供直接了当的表述方式
高层次语言使程序员能够采用问题空间的方式描述解决方案。高层次的程序很容易维护,因为它们的目的性(intent)十分明确。根据一行高层次程序代码,现代编译器能够为各种平台生成高效的代码,所以高层次程序的可移植性和可重用性自然会很强。

使用低层次语言则需要对考虑无数细节,其中大部分是和机器内部操作有关的东西,而不是要解决的问题本身。这不但造成代码难于理解,而且很容易过时。现在几乎每隔今年就要更新系统,过时的必须花费很高代价修改低层代码或者彻底重写。

对不起,你的内存泄漏了

高层次语言对于常见问题有内置解决方案。例如,众所周知内存管理是产生错误最多的地方。在使用一个对象之前,你必须为它分配内存,适当进行初始化,小心跟踪使用,并正确释放。当然,每件事儿都异常乏味而且很容易出错,极小的一个错误可能会导致灾难性后果。定位和修改这类错误是臭名昭著的困难,因为它们对于配置或使用方式的变化极其敏感。

使用未分配内存的结构指针会造成程序崩溃。使用未正确初始化的结构也会使你的程序崩溃,不过不一定立刻完蛋。如果未能好好跟踪结构的使用情况,则很可能释放一块还在使用中的内存。还是崩溃。最好再分配一些结构用来跟踪那些结构对象。不过如果你太保守,不去释放那些不很肯定未在使用的内存,那么你可要小心了。内存中很快就会充斥着无用的对象,直到内存耗尽,程序崩溃。这就是恐怖的“内存泄漏”。

如果你的内存空间碎片太多,那该怎么办呢?解决办法是通过移动对象对内存重新归整,不过在C++里没戏——如果你忘了更新对象的所有引用(reference),那么你就会搞乱程序,结果还是崩溃。

很多真正的高层次语言提供了解决办法——那就是垃圾回收(garbage collector)。它记录跟踪所有的对象,如果对象用完了会加以回收,永远不会出错。如果你使用有垃圾回收功能的语言,会得到不少好处:

大量的bug立马无影无踪。是不是很爽呀?

代码会变得更短小更易读,因为它不必为内存管理的细节操心。

代码更有可能在不同平台和不同配置下高效运行。

唉,C++用户必须自己动手去拣垃圾。他们中的许多人被洗了脑子,认为这样会比那些专家提供的垃圾回收工具更为高效,如果要建立磁盘文件,他们估计不会使用文件名,而更愿意和磁道扇区打交道。手动回收垃圾可能会对一两中配置显得更高效些,不过你当然不会这么去使用字处理软件。

你不必相信我们这里说的。可以去读一下B. Zorn的《保守垃圾回收的代价测量》(科罗拉多大学Boulder分校,技术报告CU-CS-573-92),文中对程序员用C手动优化的垃圾回收技术和标准垃圾回收器进行了性能比较,结果表明C程序员自己写的垃圾回收器性能要差一些。

OK,假设你是个幡然醒悟的C++程序员,想使用垃圾回收。你并不孤单,很多人认为这是个好主意,决定写一个。老天爷,猜猜怎么着?你会发现根本没法在C ++中提供其他语言内置的那样好的垃圾回收。其中一个原因是,(惊讶!)C++里的对象在编译后和运行时就不再是对象了。它们只是一块十六进制的烂泥巴。没有动态类型信息——垃圾回收器(还有调试器)没法知道任何一块内存里的对象究竟是什么,类型是什么,以及是否有人此时正在使用它。

另一个原因是,即使你能写个垃圾回收器,如果你用了其他未使用垃圾回收功能的代码,你还是会被干掉。因为C++没有标准的垃圾回收器,而且很有可能永远也不会有。假设我写了一个使用了我的垃圾回收功能的数据库程序,你写了一个使用你自己的垃圾回收功能的窗口系统。但你关闭一个装有我的数据记录的窗口,你的窗口不会去通知我的数据记录,告诉它已经没有人引用它了。这个对象将不会被释放,直到内存耗尽——内存泄漏,老朋友又见面了。

学起来困难?这就对了

C++和汇编语言很相象——难学难用,要想学好用好就更难了。

日期: Mon, 8 Apr 91 11:29:56 PDT
发信人: Daniel Weise <daniel@mojave.stanford.edu>
收信人: UNIX-HATERS
主题: From their cradle to our grave (从他们的摇篮到我们的坟墓)

造成Unix程序如此脆弱的一个原因是C程序员从启蒙时期就是这么被教育的。例如,Stroustrup(C++之父)的《C++编程语言》第一个完整程序(就是那个300K大小的"hello world"程序之后的那个)是一个英制/公制转换程序。用户用结尾"i"表示英制输入,用结尾"c"表示公制输入。下面是这个程序的概要,是用真正的Unix/C风格写的:

#include <stream.h>

main() {
[变量声明]
cin >> x >> ch;
;; A design abortion.
;; 读入x,然后读入ch。

if (ch == 'i') [handle "i" case]
else if (ch == 'c') [handle "c" case]
else in = cm = 0;
;; 好样的,决不报告错误。
;; 随便做点儿什么就成了。

[进行转换]

往后翻13页(第31页),给了一个索引范围从n到m的数组(而不是从0到m)的实现例子。如果程序员使用了超出范围的索引,这个程序只是笑嬉嬉地返回数组的第一个元素。Unix的终极脑死亡。

语法的吐根糖浆(Syrup of Ipecac,一种毒药)

语法糖蜜(Syntactic sugar)是分号癌症的罪魁祸首。

——Alan Perlis

在使用C编程语言中所能遇到的所有语法错误几乎都能被C++接受,成功编译。不幸的是,这些语法错误并不总能生成正确的代码,这是因为人不是完美的,他们总是敲错键盘。C一般总能在编译是发现这些错误。C++则不然,它让你顺利通过编译,不过如果真的运行起来,就等着头痛吧。

C++的语法形成也和它自身的发展密不可分。C++从来没有被好好设计过:它只是逐步进化。在进化过程中,一些结构的加入造成了语言的二义性。特别的规则被用于解决这些二义性,这些难懂的规则使得C++复杂难学。于是不少程序员把它们抄在卡片上以供不时之需,或者根本就不去使用这些功能。

例如,C++有个规则说如果一个字符串既可以被解析为声明也可以被解析为语句,那么它将被当做声明。解析器专家看到这个规则往往会浑身发冷,他们知道很难能正确实现它。AT&T自己甚至都搞不对。比如,当Jim Roskind想理解一个结构的意思时(他觉得正常人会对它有不同的理解),他写了段测试代码,把它交给AT&T的"cfront"编译器。Cfront崩溃了。

事实上,如果你从ics.uci.edu上下载Jim Roskind的开放C++语法,你会发现ftp/pub目录里的c++grammar2.0.tar.Z有这样的说明:“注意我的语法和cfront不一定保持一致,因为 a) 我的语法内部是一致的(这源于它的规范性以及yacc的确证。b) yacc生成的解析器不会吐核(core dump)。(这条可能会招来不少臭鸡蛋,不过...每次当我想知道某种结构的语法含义是,如果ARM(Annotated C++ Reference Manual, 带注释的C++参考手册)对它的表述不清楚,我就会拿cfront来编译它,cfront这时总是吐核(core dump))”

日期: Sun, 21 May 89 18:02:14 PDT
发信人: tiemann (Michael Tiemann)
收信人:
sdm@cs.brown.edu
抄送: UNIX-HATERS
主题: C++ Comments (C++注释)

日期: 21 May 89 23:59:37 GMT
发信人:
sdm@cs.brown.edu (Scott Meyers)
新闻组: comp.lang.c++
组织: 布朗大学计算机系

看看下面这行C++代码:

//**********************

C++编译器该如何处理它呢?GNU g++编译器认为这是一行由一堆星星(*)组成的注释,然而AT&T编译器认为这是一个斜杠加上一个注释开始符(/*)。我想知道哪个是正确解析方式,可是Stroustrup的书(《C++编程语言》)里面却找不到答案。

实际上如果使用-E选项进行编译,就会发现是预处理器(preprocessor)搞的鬼,我的问题是:

这是否AT&T预处理器的bug?如果不是,为什么?如果是bug,2.0版是否会得到修正?还是只能这么下去了?

这是否GNU预处理器的bug?如果是,为什么?

Scott Meyers

sdm@cs.brown.edu

UNIX解析中有个古老的规则,尽量接受最长的语法单元(token)。这样'foo'就不会被看成三个变量名('f', 'o'和'o'),而只被当成一个变量'foo'。看看这个规则在下面这个程序中是多么的有用(还有选择'/*'作为注释开始符是多么的明智):

double qdiv (p, q)
double *p, *q;
{
return *p/*q;
}

为什么这个规则没有被应用到C++中呢?很简单,这是个bug。

Michael

糟糕的还在后头,C++最大的问题是它的代码难读难理解,即使对于每天都用它的人也是如此。把另一个程序员的C++的代码拿来看看,不晕才怪。C++没有一丝品位,是个乱七八糟的丑八怪。C++自称为面向对象语言,却不愿意承担任何面向对象的责任。C++认为如果有谁的程序复杂到需要垃圾回收,动态加载或其他功能,那么说明他有足够的能力自己写一个,并且有足够的时间进行调试。

C++操作符重载(operator overloading)的强大功能在于,你可以把一段明显直白的代码变成能和最糟糕的APL, ADA或FORTH代码相媲美的东西。每个C++程序员都能创建自己的方言(dialect),把别的C++程序员彻底搞晕。

不过——嘿——在C++里甚至标准的方言也是私有的(private)。

抽象些什么?

你可能会觉得C++语法是它最糟糕的部分,不过当你开始学习C++时,就会知道你错了。一旦你开始用C++编写一个正式的大型软件,你会发现C++的抽象机制从根儿上就烂了。每本计算机科学教材都会这样告诉你,抽象是良好设计之源。

系统各个部分的关联会产生复杂性。如果你有一个100,000行的程序,其中每一行都和其他行代码的细节相关,那你就必须照应着 10,000,000,000种不同的关联。抽象能够通过建立清晰的接口来减少这种关联。一段实现某种功能的代码被隐藏在模块化墙壁之后发挥作用。

类(class)是C++的核心,然而类的实现却反而阻碍着程序的模块化。类暴露了如此多的内部实现,以至于类的用户强烈倚赖着类的具体实现。许多情况下,对类做一点儿改变,就不得不重新编译所有使用它的代码,这常常造成开发的停滞。你的软件将不再“柔软”和“可塑”了,而成了一大块混凝土。

你将不得不把一半代码放到头文件里面,以对类进行声明。当然,类声明所提供的public/private的区分是没有什么用的,因为“私有” (private)信息就放在了头文件里,所以成了公开(public)信息。一旦放到头文件里,你就不大愿意去修改它,因为这会导致烦人的重编译。程序员于是通过修补实现机制,以避免修改头文件。当然还有其他一些保护机制,不过它们就象是减速障碍一样,可以被心急的家伙任意绕过。只要把所有对象都转换 (cast)成void*,再也没有了讨厌的类型检查,这下世界清净了。

其他许多语言都各自提供了设计良好的抽象机制。C++丢掉了其中一些最为重要的部分,对于那些提供的部分也叫人迷惑不解。你是否遇到过真正喜欢模板 (template)的人?模板使得类的实现根据上下文不同而不同。许多重要的概念无法通过这种简单的方式加以表达;即使表达出来了,也没法给它一个直接的名字供以后调用。

例如,名空间(namespace)能够避免你一部分代码的名字和其他部分发生冲突。一个服装制造软件可能有个对象叫做"Button"(钮扣),它可能会和一个用户界面库进行链接,那里面也有个类叫做"Button"(按钮)。如果使用了名空间,就不会有问题了,因为用法和每个概念的意思都很明确,没有歧义。

C++里则并非如此。你无法保证不会去使用那些已经在其他地方被定义了的名字,这往往会导致灾难性后果。你唯一的希望是给名称都加上前缀,比如ZjxButton,并但愿其他人不会用同一个名字。

日期: Fri, 18 Mar 94 10:52:58 PST
发信人: Scott L. Burson <gyro@zeta-soft.com>
主题: preprocessor (预处理器)

C语言迷们会告诉你C的一个最好的功能是预处理器。可事实上,它可能一个最蹩脚的功能。许多C程序由一堆蜘蛛网似的#ifdef组成 (如果各个Unix之间能够互相兼容,就几乎不会弄成这样)。不过这仅仅是开始。

C预处理器的最大问题是它把Unix锁在了文本文件的监牢里,然后扔掉了牢 旁砍 。这样除了文本文件以外,C源代码不可能以任何其他方式存储。为什么?因为未被预处理的C代码不可能被解析。例如:

#ifdef BSD
int foo() {
#else
void foo() {
#endif
/* ... */
}

这里函数foo有两种不同的开头,根据宏'BSD'是否被定义而不同。直接对它进行解析几乎是不可能的 (就我们所知,从来没实现过)。

这为什么如此可恶?因为这阻碍了我们为编程环境加入更多智能。许多Unix程序员从没见过这样的环境,不知道自己被剥夺了什么。可是如果能够对代码进行自动分析,那么就能提供很多非常有用的功能。

让我们再看一个例子。在C语言当道的时代,预处理器被认为是唯一能提供开码(open-coded,是指直接把代码嵌入到指令流中,而不是通过函数调用)的方式。对于每个简单常用的表达式,开码是一个很高效的技术。比如,取小函数min可以使用宏实现:

#define min(x,y) ((x) < (y) ? (x) : (y))

假设你想写个工具打印一个程序中所有调用了min的函数。听上去不是很难,是不是?但是你如果不解析这个程序就无法知道函数的边界,你如果不做经过预处理器就无法进行解析,可是,一旦经过了预处理,所有的min就不复存在了!所以,你的只能去用grep了。

使用预处理器实现开码还有其他问题。例如,在上面的min宏里你一定注意到了那些多余的括号。事实上,这些括号是必不可少的,否则当min在另一个表达式中被展开时,结果可能不是你想要的。(老实说,这些括号不都是必需的——至于那些括号是可以省略的,这留做给读者的练习吧)。

min宏最险恶的问题是,虽然它用起来象是个函数调用,它并不真是函数。看这个例子:

a = min(b++, c);

预处理器做了替换之后,变成了:

a = ((b++) < (c) ? (b++) : (c))

如果'b'小于'c','b'会被增加两次而不是一次,返回的将是'b'的原始值加一。

如果min真是函数,那么'b'将只会被增加一次,返回值将是'b'的原始值。

C++对于C来说,就如同是肺癌对于肺

“如果说C语言给了你足够的绳子吊死自己,那么C++给的绳子除了够你上吊之外,还够绑上你所有的邻居,并提供一艘帆船所需的绳索。”

——匿名

悲哀的是,学习C++成了每个计算机科学家和严肃程序最为有利可图的投资。它迅速成为简历中必不可少的一行。在过去的今年中,我们见过不少C++程序员,他们能够用C++写出不错的代码,不过...

...他们憎恶它。

程序员进化史

初中/高中

10 PRINT "HELLO WORLD"
20 END

大学一年级

program Hello(input, output);
begin
 writeln('Hello world');
end.

大学四年级

(defun hello ()
 (print (list 'HELLO 'WORLD)))

刚参加工作

#include <stdio.h>

main (argc, argv)
int argc;
char **argv; {
 printf ("Hello World!n");
}

老手

#include <stream.h>

const int MAXLEN = 80;

class outstring;
class outstring {
private:
 int size;
 char str[MAXLEN];

public:
 outstring() { size=0; }
 ~outstring() { size=0; }
 void print();
 void assign(char *chrs);
};

void outstring::print() {
 int in;
 for (i=0; i<size; i++)
   cout << str[i];
 cout << "n";
}

void outstring::assign(char* chrs) {
 int i;
 for (i=0; chars[i]!=''; i++)
   str[i] = chrs[i];
 size=i;
}

main (int argc, char **argv) {
 outstring string;
 string.assign("Hello World!");
 string.print();
}

老板

“乔治,我需要一个能打印'Hello World!'的程序”

好了,换个角度想想,C++可能是你最好的朋友,C++之父Stroustrup之所以设计C++,其实http: //www.chunder.com/text/ididit.html正是为了我们这些程序员啊,当然如果你真的发誓不当C++程序员了,而且一时半会儿也当不了老板,你还可以考虑做系统管理员,叫人羡慕的sysadmin。


15 04, 2005
Unix痛恨者手册.3[转贴]
作者 xzh2000 19:49 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
半年前的上回书说到你如何去玩shell游戏,估计现在你已经玩腻了,不过不要着急,下面,该轮到shell玩你了。

欢迎来到元语法(metasyntacitic)动物园

C Shell的元语法操作符带来了大量和引用有关的问题和混乱。元操作符在一个命令被执行前对其进行转换。我们把这些操作符叫做元操作符是因为它们不属于命令的语法成分,它们作用于命令本身。大多数程序员对元操作符(有时也叫做escape operators)并不陌生。比如,C字符串中的反斜杠()就是一个元语法操作符;它不代表自己,而是对其后的字符的说明。如果你不希望如此,你必须使用引用机制来告诉系统把元操作符当做一般字符来处理。回到刚才C字符串的例子,如果想得到反斜杠字符,你必须写成。

简单的引用机制在C Shell中很难工作,这是因为Shell和它执行的程序之间各执一词,无法统一。例如,下面是个简单的命令:

grep string filename;

参数string包含了grep定义的字符,比如?, [, 和]等等,但这些字符是shell的元操作符。这意味着必须对它们进行引用。然而,有些时候可能不需要如此,这和你使用什么样的shell以及环境变量有关。

如果想在字符串中寻找包含点(.)或其他以横杠(-)开头的模式,这就更为复杂了。

一定要记住对元字符进行正确引用。不幸的是,和模式识别一样,操作系统的各个部分都充斥着互不兼容的引用标准。

C Shell的元语法动物园里饲养着七种不同的元操作符家族。斗转星移,转眼间动物园里已经人满为患了,笼子使用的不再是钢铁,而是用锡了。动物间的小磨擦不断。这七种针对shell命令行的转换方式是:

别名 alias, unalias

命令输出替代 `

文件名替代 *, ?, []

历史替代 !, ^

变量替代 $, set, unset

进程替代 %

引用 ',"

这一“设计”的结果是,问号(?)永远被shell当成单字符匹配符,它永远无法被作为命令行参数传给用户程序,所以别想使用问号来作为帮助选项。

如果这七种元字符有着清晰的逻辑顺序和定义,那么情况也不会太糟糕。可事实并非如此:

日期: Mon, 7 May 90 18:00:27 - 0700
发信人: Andy Beals <bandy@lll-crg.llnl.gov>
主题: Re: today's gripe: fg %3 (今天之不爽事:fg %3)
收信人: UNIX-HATERS

你可以使用%emacs或者%e来恢复一个任务(如果唯一的话),也可以使用%?foo,如果"foo"出现在命令行中。

当然,!ema和!?foo也可以用于历史命令替换上。

但是,UCB的猪头(pinheads)们没有想到!?foo后面可能伴随的编辑命令:

!?foo:s/foo/bar&/:p

多向前扫描一个编辑字符真的这么困难么?

哪怕是Unix“专家”,也要晕菜了。下面再来看看Milt Epstein的这个例子,他想写个shell脚本获得实际被敲入的命令行,而不是那个经shell处理后的结果。他最后发现这并不容易,因为shell 为命令做了太多的“好事”。要做到这一点,需要各种稀奇古怪的变形技术,连Unix专家也会望而却步。这就是Unix的典型做法:把简单的东西搞得异常复杂,这只是因为这些东西在Unix诞生之时从没被仔细考虑过:

日期: 19 Aug 91 15:26:00 GMT
发信人:
Dan_Jacobson@att.com
主题: ${1+"$@"} in /bin/sh family of shells shell scripts
收信人: comp.emacs.gnu.emacs.help, comp.unix.shell

>>>>> On Sun, 19 Arg 91 18:21:58 - 0500
>>>>> Milt Epstein <esptein@suna0.cs.uiuc.edu>
写到:

Milt> "${1+"$@"}"究竟是什么意思?我估计这是用来
Milt> 读取其余的命令行参数,但我不敢肯定。

这是/bin/sh里用来完整复制命令行参数的一种方法。

它的意思是:如果有至少一个参数(${1+),那么用所有参数("$@")来替代以保留所有的空白字符。

如果我们只使用"$@",那么在没有参数的情形下会得到""而不是我们想要的空参数。

那么,为什么不使用"$*"呢?sh(1)的man手册是这样说的:

双引号之间的参数和命令会被替换,shell会对结果加上引用,以避免解析空格或生成文件名。如果$*出现在双引号之中,各个参数之间的空格会被加上引用("$1 $2 ..."),而如果$@出现在双引号之中,各个参数之间的空格不会被加上引用("$1""$2" ...)。

我认为${1+"$@"}一直可以兼容到“版本7”的shell。

老天!一直兼容到“版本7”。

听"chdir"的还是听"cd"的?

Unix在漫长的演化过程中几经易手,这些Unix系统开发者把Unix引向了不同方向,他们之中没有一个人停下来考虑一下自己的做法会不会对和其他人发生冲突。

日期: Mon, 7 May 90 22:58:58 EDT
发信人: Alan Bawden <alan@ai.mit.edu>
主题: cd ..: I am not making this up (cd ..: 这不是我编造出来的)
收信人: UNIX-HATERS

有什么命令能比"cd"更直接了当的呢?让我们看这个简单的例子:"cd ftp"。如果我的当前目录/home/ar/alan中有个子目录叫做"ftp",那么它就变成了我新的当前目录,现在我在/home/ar/alan/ftp下了。简单吧?

现在,你们知不知道"."和".."?每个目录都会有两个记录:"."是指该目录自己,".."是指父目录。在上面的例子中,如果我想回到/home/ar/alan,只要敲"cd .."就可以了。

现在假设"ftp"是一个符号链接。假设它指向的是目录/com/ftp/pub/alan。如果执行"cd ftp",我的当前目录将是/com/ftp/pub/alan。

和其他所有目录一样,/com/ftp/pub/alan也有一个叫".."的记录,它指的是父目录:/com/ftp/pub。如果我想进入那个目录,我敲入命令:

% cd ..

猜一下我现在在哪儿呢?我又回到了/home/ar/alan!shell(准确的说是人工智能实验室里用的tcsh)认为我其实是想回到那个装有符号链接的目录。现在我必须使用"cd ./.."才能进入/com/ftp/pub。

Shell编程

Shell程序员和《侏罗纪公园》里的恐龙制造者有些类似。他们手上没有所需的完整材料,所以不得不用一些乱七八糟的材料填充。尽管有着无穷的自信和能力,他们似乎并不是总能控制住造出来的那些玩意。

理论上说,使用Shell编程比用C语言要有很多好处:Shell程序移植容易。这指的是使用shell“编程语言”写的程序能够在不同的体系结构和不同的Unix变种上运行,因为shell会解析这些程序,而不是把这些程序编译成机器码运行。而且,标准Unix Shell sh 自从1977年以来就成为Unix中不可或缺的一部分,所以你可以在许多机器上找到它。

让我们来验证一下这个理论,写个脚本列举目录下的所有文件,并使用file命令来显示文件的类型:

日期: Fri, 24 Apr 92 14:45:48 EDT
发信人: Stephen Gildea <gildea@expo.lcs.mit.edu>
主题: Simple Shell Programming (简单Shell编程)
收信人: UNIX-HATERS

同学们好。今天我们将学习"sh"编程。"sh" 是个简单,用途广泛的程序,让我们先看个基本的例子:

打印一个目录下所有文件的类型

(我听到你们在后面说什么了!那些已经会了的同学可以写个脚本在远程启动一个X11客户端,不要吵吵!)

我们学习sh编程的同时,当然也希望自己的程序是健壮,可移植和优雅的。我假设你们都读过了相应的man手册,所以下面这个实现应该很简单:

file *

很不错,是不是?简单的答案给简单的问题;符号 * 用来匹配目录下的所有文件。嗯,不一定。以点(.)开头的文件会被忽略,*不会匹配它们。也许这种情况很少发生,但既然要写健壮的程序,我们将使用"ls"的一个特殊选项:

for file in `ls -A`

do

flie $file

done

多么优雅,多么健壮!不过,唉,一些系统上的"ls"不接受"-A"选项。没问题,我们使用"-a"选项,然后再去掉"."和"..":

for file in `ls -a`

do

if [ $file != . -a $file != ..] then

file $file

fi

done

不是那么优雅,但至少是健壮的和可移植的。你说什么?"ls -a"也不是哪里都能用的?没问题,我们用"ls -f"好啦。它还快一点呢。我希望你们能从man手册中看到所有这些东西。

唔,可能不是那么健壮。Unix文件名中除了斜杠(/)以外可以使用任何字符。如果文件名中有个空格的话,这个脚本就完蛋了,这是因为shell会把它当成两个文件名传给"file"命令。不过这也不是太难对付。我们只要把它放到引用中就可以了:

for file in `ls -f`

do

if [ "$file" != . -a "$file" != ..]

then

file "$file"

fi

done

你们中可能已经有人看出来了,我们只是减少了问题,但还是没有完全解决。因为换行符也能用在文件名中。

我们的脚本不是那么简单了,看来得重新评估一下我们用的方法了。如果我们不使用"ls"就不用费劲去处理它的输出了。这个怎么样:

for file in * .*

do

if [ "$file" != . -a "$file" != ..]

then

file "$file"

fi

done

看起来不错。能够处理点(.)文件和有非打印字符的文件名。我们不断把一些稀奇古怪的文件名加入到测试目录下,这个脚本始终工作得很好。然而有个家伙用它测一个空目录,这时候 * 产生了"No such file"(没有这个文件)的输出。不过,我们当然可以继续处理这种情况...

....到了这一步uucp可能会嫌我的这封邮件可能,看来我只能到此为止了,请读者去自己解决剩下的bug吧。

Stephen

还有一个更大的问题Stephen没有想到,我们从一开始就有意隐藏着:Unix file 命令不工作。

日期: Sat, 25 Apr 92 17:33:12 EDT
发信人: Alan Bawden <Alan@lcs.mit.edu>
主题: Simple Shell Programming (简单Shell编程)
收信人: UNIX-HATERS

喔!别忙。再仔细看看。你真的想用'file'命令?如果谁想开心大笑一场可以马上去找一台Unix机器,在有各种各样文件的目录下敲命令"file *"。

例如,我在有各种C源代码文件的目录下运行"file"——这是一些结果:

arith.c: c program text

binshow.c: c program text

bintxt.c: c program text

看起来还不错。不过这个就不太对了:

crc.c: ascii text

看到了么?'file'并不是根据后缀".c"去判断的,它对文件的内容采用了一些启发式(heuristics)算法。很明显crc.c看起来不那么象C代码——尽管对我来说它就是。

gencrc.c.~4~: ascii text

gencrc.c: c program text

估计我在第4版本以后做了一些修改,使得gencrc.c更象是C代码了...

tcfs.h.~1~: c program text

tcfs.h: ascii text

很明显第1版本以后的tcfs.h不太象是C代码了。

time.h: English text

没错,time.h看起来更象英语,而不是一般的ascii码。我不知道'file'是不是还能判断出西班牙语或法语。(顺便说一下,你的TeX文档会被当成"ascii text"而不是"English text",不过这有点儿跑题了)

words.h.~1~: ascii text

words.h: English text

这可能是因为我在第1版本以后在words.h中加入了一些注释。

我把最精采的留在最后:

arc.h: shell commands

Makefile: [nt]roff, tbl, or eqn input text

都错得一塌糊涂。我不知道如果根据'file'的判断结果去使用这些文件会造成什么结果。

—Alan

Shell变量

当然Alan还不算最倒霉的,至少他没试过shell变量。

我们前面说过,sh和csh对shell变量的实现不太一样。这本来没有什么,可是一些shell变量的语义(比如定义的时刻,改变的原子性等)没有被好好说明或定义。总会遇到一些奇怪反常规的shell变量,只有反复试验以后才能明白。

日期: Thu, 14 Nov 1991 11:46:21 PST
发信人: Stanley's Tool Works <lanning@parc.xerox.com)
主题: You learn something new every day (每天都有新发现)
收信人: UNIX-HATERS

运行一下这个脚本:

#!/bin/csh
unset foo
if ( ! $?foo ) hen
echo foo was unset
else if ("$foo" = "You lose") then
echo $foo
endif

会产生如下错误:

foo: Undefined variable.

如果要让这个脚本"正确工作",你必须求助于以下这个脚本:

#!/bin/csh
unset foo
if ( ! $?foo ) hen
echo foo was unset
set foo
else if ("$foo" = "You lose") then
echo $foo
endif

[注意,我们必须在发现foo没有被定义的时候'set foo'.] 清楚了么?

错误码和错误检查

我们上面的例子没有指出file命令如何将错误返回给脚本。事实上,它根本就没有返回错误。错误被忽略了。这不是因为我们粗心大意:许多Unix shell脚本(以及其他程序)忽略所调用程序所返回的错误码。这个做法是可取的,这是因为没有标准的错误码。

也许之所以错误码被广泛地忽略,是因为当用户敲命令的时候这些错误码很少被显示出来。错误码和错误检查在Unix阵营中是如此少见,以至于有些程序甚至根本就不费劲去报告错误。

日期: The, 6 Oct 92 08:44:17 PDT
发信人: Bjorn Freeman-Benson <bnfb@ursamajor.uvic.ca>
主题: It's always good news in Unix land (Unix世界里都是好消息)
收信人: UNIX-HATERS

看看这个tar程序。和所有的Unix"工具"(似乎不太准确)一样,tar的工作方式非常奇怪和特别。例如,tar是一个极为乐观向上的程序,它认为从不会有什么坏事,所以太从来不返回错误状态。事实上,哪怕是在屏幕上打出了错误信息,它返回的仍然是"好消息" (状态0)。运行一下这个脚本:

tar cf temp.tar no.such.file

if ( $status == 0 ) echo "good news! No error."

你将得到如下结果:

tar: no.such.file: No such file or directory
Good news! No error.

我明白了——我从一开始就不应该奢望什么一致,有用,帮助良好,快速,甚至是正确的结果...

Bjorn

OK, 被shell折腾得很爽吧?还没过足瘾?不要紧,下回书我们换个地方,钻进Unix下水道(pipe)里体验无穷的痛苦和快乐

管道

Unix受虐狂们,欢迎来到Unix下水道。

“在我们这个世纪,巴黎下水道仍是一个神秘的场所。如果知道自己的下面是个可怕的大窖,巴黎会感到不安。” —— 雨果 《悲惨世界》

下面只是我自己对Unix的看法。大约六年前(当我有了第一台工作站的时候),我用了很多时间学习Unix。应该学得算是不错的。幸运的是,脑子里的这些垃圾正随着时间的推移慢慢降解。可是,自从这个讨论开始以来,不少Unix支持者发给我例子来“证明”Unix的强大。这些例子当然唤起了我许多美好的回忆:他们都是用一种最怪异的方式去实现一些简单而无用的功能。

有个家伙发了篇贴子讲述一个shell脚本是如何让他获得“圆满”的(这个脚本使用了四个噪声一样的命令把他所有的'.pas'后缀的文件改名为'.p' 文件)。可我还是想把自己的宗教热情留给比改几个文件名更重要的事情上。是的,这就是Unix工具留给我的记忆:你用大量的时间去学那些复杂奇特的花架子,可到头来却是一场空。我还是去学些有用的真功夫吧。

——Jim Giles
Los Alamos国家实验室

Unix迷们拜倒在管道(pipe)的真善美之下。他们他们歌唱管道:没有管道就没有Unix。他们异口同声地颂扬管道:“管道能够让你用简单的程序去构造更复杂的程序。管道能够以意想不到的方式去使用命令,管道使得实现更为简单。”不幸的是,颂歌对Unix的作用并不比对伟大旗手的要好多少。

管道并不是一无是处。模块化和抽象化是建立复杂系统中所必需的,这是计算机科学的基本原则。基本工具越是优秀,用其建立的复杂系统就会更为成功,可维护性也越高。管道作为构造工具还是有价值的。

以下是个管道的例子:

egrep '^To:|^Cc:' /var/spool/mail/$USER |

cut -c5- |

awk '{ for (i = 1; i <= NF; i++) print $i}' |

sed 's/,//g' | grep -v $USER | sort | uniq

看明白了么?这个程序通过读取用户的邮箱,得到用户所在的邮件列表(差不多是这个意思)。和你家里的水管一样,这个Unix管道也会在特定情况下神秘地破裂。

管道有时的确很有用,但它通过连接标准输入输出的方式进行进程间通讯,这个机制限制了它的应用。首先,信息只能单向流动。进程无法通过管道进行双向通讯。其次,管道不支持任何形式的抽象。发送方和接收方只能使用字符流传输信息。比字符稍微复杂一点的对象是不能通过管道直接传输的,必须串行化为字符流以后才成,当然接收方必须对得到的字符流进行重新组装。这意味着你无法传输一个对象以及用于建立这个对象的定义代码。你无法传输指针到另一个进程的地址空间。你无法传输文件句柄或socket句柄或文件权限属性。

冒着被骂做自以为是的风险,我们认为正确的模型应该是过程调用(本地的或是远程的),用以传递第一类结构(first-class structures)(这是C语言从一开始就支持的)和函数组合(functional composition)。

管道对简单任务是不错的,比如文本流处理,但用它来建立健壮软件就显得有些捉襟见肘了。例如,早期关于管道的一篇论文中说明了如何使用管道把一些小程序组合在一起来构成一个拼写检查程序。这是体现简单性的经典之作,但如果真的用来检查拼写错误就再糟糕没有了。

管道在shell脚本中有经常能露一小手。程序员用它实现一些简单而脆弱的解决方案。这是因为管道使得两个程序之间产生了倚赖关系,如果你修改了一个程序的输出格式,就必须同时修改另一个程序的输入处理。

大多数程序是一步步建立起来的:首先制定程序的需求规范,然后程序的内部逐渐成型,最后写一个输出处理函数。管道则不把这一套放在眼里:只要有人把一个半生不熟的程序放到了管道中,其输出格式就定死了,不管是多么不一致,不标准和低效,你都只能认命了。

管道不是程序间通讯的唯一选择。Macintosh就没有管道,我们最喜欢的Unix宣传手册是这样写的:

但是,Macintosh采用的则是截然相反的一种模型。系统不和字符流打交道。数据文件具有更高的层次,总是和特定的程序相关的。你什么时候把一个 Mac程序的输出传给另一个过?(如果能找到管道符都算你运气)程序自成一体,你必须彻底明白自己在干嘛呢。你无法把MacFoo和MacBar搞到一起。-— 摘自 《Unix生活》 Libes和ressler著

是呀,这些可怜的Mac用户。如果无法把字符流通过管道四处乱传,他们怎么能在文档中插入绘画程序制作的图片?怎么能插入一个表格文档?怎么能把这个东拼西凑成的用电子邮件发出去?接到以后又怎么能无缝地对它进行浏览和编辑,再回复回去?没有管道,我们不能想像这一切在过去的十年中是如何被 Macintosh做到的。

上次你的Unix工作站和Macintosh一样有用是什么时候?上次你能在它上面跑不同公司(甚至是同一公司的不同部门)的软件是什么时候?更不用说这些软件能互相通信。如果Unix真做到了这一点,那是因为Mac软件开发商拼了老命把他们的软件移植到了Unix上,寄希望于让Unix看起来象Mac一些。

Unix和Macintosh操作系统的根本区别是,Unix是为取悦程序员而设计的,而Mac是为了取悦用户。(Windows一门心思想取悦的则是会计,不过这有些跑题了)。

研究表明管道和重定向是难于使用的,不是因为想法本身,而是由于其随意和不直观的限制。Unix自己的文档早就指明了只有Unix死党才能体会管道的妙处。

日期: thu, 31 Jan 91 14:29:42 EST
发信人: Jim Davis <jrd@media-lib.media.mit.edu>
收信人: UNIX-HATERS
主题: Expertise (专业知识)

今天早上我读到《人机接口杂志》上的一篇文章《计算机操作系统专业知识》,是Stephanie M. Doane和其他两位作者写的。猜猜他们研究的是什么操作系统?Doane对Unix新手、中手和专家的知识和表现进行了研究,下面是一些摘要:

“只有专家能够使用Unix特有的一些功能(例如管道和重定向)来构造命令组合”

换句话说,Unix的每个新功能(除了那些从其他系统上生搬硬套过来的)都是如此怪异,以至于必须经过多年同样怪异的学习和实践才能掌握。

“这个发现有些出乎意料,因为这些正是Unix的基础功能,而且这些功能是所有初级课程都会涉及的”

她还引用了S. W. Draper的一些文章,Draper相信:

“世上根本没有什么Unix专家,如果专家指的是这样一些人,他们穷尽了某专业的所有知识,无需再学习什么了。”

这一点我不能苟同。在学习Unix各种荒谬技术的征途上,已经有无数人被“穷尽”了。

有些程序甚至吃饱了撑的,把管道和文件重定向区别对待了:

发信人: Leigh L. Klotz <klotz@adoc.xerox.com>
收信人: UNIX-HATERS
主题: | vs. < (|对<)
日期: Thu, 8 Oct 1992 11:37:14 PDT

collard% xtpanel -file xtpanel.out < .login
unmatched braces
unmatched braces
unmatched braces
3 unmatched right braces present

collard% cat .login | xtpanel -file xtpanel.out
collard%

你自己琢磨琢磨吧。

Find

Unix最为恐怖的是,不管你被它开过多少次瓢,你总是没法失去知觉。它就这么开来开去,没完没了。

——Patrick Sobalvarro

在一个庞大的文件系统中遗失个把文件是常有的事(想像一下大海捞针)。现在由于更大更便宜的磁盘的出现,PC和Apple用户也遇到了这样的问题。为了解决这个问题,系统往往提供一个搜索程序,根据各种条件(比如文件名称,类型,创建时间等等)进行文件搜索。Apple Macintosh和微软Windows都提供强大、方便、稳定的文件搜索程序。这些搜索程序的设计中考虑到了用户习惯和现代网络。Unix的搜索程序 find考虑的则不是用户,而是cpio,一个Unix备份工具。Find没能预见到网络的存在和文件系统的新功能(如符号链接),即使是经历了反复修改,它还是无法很好工作。于是,尽管它对于遗失文件的用户意义重大,find还是不能稳定、正常的工作。

Unix的作者们努力是find跟上系统其他部分的发展,但这并不容易。今天的find有各种特殊的选项用于处理NFS文件系统,符号链接,执行程序,交互式地执行程序,甚至直接使用cpio或cpio-c格式对找到的文件进行归档。Sun公司修改了find,添加了一个后台程序建立系统上每个文件的索引数据库,由于一些奇怪的理由,当你不加任何参数执行"find filename"时,这个数据库被用于进行搜索,(够安全的,是吧?) 即使有个这么多修修补补,find还是不能正常工作。

例如,csh见到符号链接会顺着走下去,但find不会:csh是伯克利(符号链接的发源地)的家伙们写的,可是find是从AT&T的原始时代开始就有了。就这样,东西方的文化差异激烈地碰撞了,造成了巨大的混乱:

日期: Thu, 28 Jun 1990 18:14 EDT
发信人:
pgs@crl.dec.com
主题: more things to hate about Unix (更多恨的理由,就在Unix)
收信人: UNIX-HATERS

这个是我的最爱。我在一个目录下工作,想用find去找另一个目录里的文件,我是这么做的:

po> pwd
/ath/u1/pgs
po> find ~halstead -name "*.trace" -print
po>

看来没有找到。不过别忙,看看这个:

po> cd ~halsead
po> find . -name "*.trace" -print
../learnX/fib-3.trace
../learnX/p20xp20.trace
../learnX/fib-3i.trace
../learnX/fib-5.trace
../learnX/p10xp10.trace
po>

嘿!文件就在那里呀!下次如果你想找一个文件,记住随机到各个目录下转转,说不定你要的文件就藏在那里呢。Unix这个废物。

可怜的Halstead同志的/etc/passwd记录一定是使用了符号链接去指向了真正的目录,所以有的命令工作,有的不工作。

为什么不改改find,也让它顺着符号链接呢?这是因为任何一个指向高一级目录的符号链接都会把find引入死循环。要处理这种情况需要精心的设计和小心的实现,以保证系统不会重复搜索同一个目录。Unix采用了最简单的做法:索性不处理符号链接,让用户自己去看着办吧。

联网系统变得越来越复杂,问题也越来越难以解决了:

日期: Wed, 2 Jan 1991 16:14:27 PST
发信人: Ken Harrenstien <klh@nisc.sri.com>
主题: Why find doesn't find anything (为什么find什么也找不到?)
收信人: UNIX-HATERS

我刚刚发现为什么"find"不再工作了。

尽管"find"的语法非常恶心怪异,我还在勉强用它,以免几小时泡在在迷宫似的文件目录中去寻找文件。

在这个有NFS和符号链接存在的勇敢新世界里,"find"没用了。我们这里的所谓文件系统是由众多文件服务器和符号链接组成的一团乱麻,"find"哪个也不想去处理,甚至连选项也不提供... 结果是大量的搜索路径被无声无息地忽略了。我注意到了这个,是在一个很大的目录下搜索时结果一无所获,最后发现是因为那个目录是个符号链接。

我不想自己去检查每一个交给find的搜索目录——这他妈应该是find的工作。我不想去每次这类情况发生时都要去调查一下系统软件。我不想浪费时间来和SUN或者整个Unix党徒们做斗争。我不想用Unix。恨,恨,恨,恨,恨,恨,恨,恨。

——Ken (感觉好些了,可还是有点恼)

如果想写个复杂一点的shell脚本对找到的文件进行处理,结果往往会很奇怪。这是shell传递参数方式所产生的悲惨后果。

日期: Sat, 12 Dec 92 01:15:52 PST
发信人: Jamie Zawinski <jwz@lucid.com>
主题: Q: what's the opposite of 'find?' A: 'lose'
(问题:'find'的反义词是什么? 答案:丢失)
收信人: UNIX-HATERS

我想找出一个目录下的所有的没有对应.elc文件存在的.el文件。这应该不太难,我用的是find.

不过我错了。

我先是这么干的:

% find . -name '*.el' -exec 'test -f {}c'
find: incomplete statement

噢,我记起来了,它需要个分号。

% find . -name '*.el' -exec 'test -f {}c';
find: Can't execute test -f {}c:
No such file or directory

真有你的,竟然没去解析这个命令。

% find . -name '*.el' -exec test -f {}c ;

咦,似乎什么也没做...

% find . -name '*.el' -exec echo test -f {}c ;
test -f c
test -f c
test -f c
test -f c
....

明白了。是shell把大括号给展开了。

% find . -name '*.el' -exec test -f '{}'c ;
test -f {}c
test -f {}c
test -f {}c
test -f {}c

嗯?也许我记错了,{}并不是find使用的那个“替换成这个文件名”的符号。真的么?...

% find . -name '*.el'
-exec test -f '{}' c ;
test -f ./bytecomp/bytecomp-runtime.el c
test -f ./bytecomp/disass.el c
test -f ./bytecomp/bytecomp.el c
test -f ./bytecomp/byte-optimize.el c
....

喔,原来如此。下面该怎么办呢?我想,我似乎可以试试"sed..."

可我忘记了一个深刻的哲理:“当遇到一个Unix问题的时候,有的人会想‘我懂,我可以试试sed.’这下他们有两个问题去对付了。”

试验了五次,阅读了sed手册两遍,我得到了这个:

% echo foo.el | sed 's/$/c/'

于是:

% find . -name '*.el'
-exec echo test -f `echo '{}'
| sed 's/$/c'` ;
test -f c
test -f c
test -f c
....

OK, 看来只能去试试所有shell引用的排列组合了,总会有一款和我意吧?

% find . -name '*.el'
-exec echo test -f "`echo '{}'
| sed 's/$/c'`" ;
Variable syntax.
% find . -name '*.el'
-exec echo test -f '`echo "{}"
| sed "s/$/c"`' ;
test -f `echo "{}" | sed "s/$/c"`
test -f `echo "{}" | sed "s/$/c"`
test -f `echo "{}" | sed "s/$/c"`
....

嗨,最后一个似乎有戏。我只需要这么干一下:

% find . -name '*.el'
-exec echo test -f '`echo {}
| sed "s/$/c"`' ;
test -f `echo {} | sed "s/$/c"`
test -f `echo {} | sed "s/$/c"`
test -f `echo {} | sed "s/$/c"`
....

别急,这是我想要的,可是你为什么不把{}替换成文件名呢?你再仔细瞅瞅,{}两边不是有空格么?你究竟想要什么?

哦,等等。那个反单引号间的引用被当成了一个元素。

或许我能用sed把这个反单引号过滤掉。嗯,没戏。

于是我用了半分钟去想如何能运行"-exec sh -c..."之类的东西,终于出现了曙光,写了一段emcas-lisp代码去做这件事。这不困难,挺快的,而且工作了。

我真高兴。我以为一切都过去了。

今天早上我洗澡的时候突然想到了另一种做法。我试了一次又一次,深深坠入了她的情网,意乱情迷,无法自拔。醉了。只有罕诺塔的Scribe实现曾给过我这样的快感。我仅试了12次就找到了解法。对于每个遍历到的文件它只产生两个进程。这才是Unix之道!

% find . -name '*.el' -print
| sed 's/^/FOO-/'|
sed 's/$/; if [ ! -f ${FOO}c]; then
echo $FOO; fi/' | sh

BWAAAAAHH HAAAAHH HAAAAHH HAAAAHH HAAAAHH HAAAAHH HAAAAHH HAAAAHH!!!!

—Jamie

OK, 在下水道里玩捉迷藏挺有意思的吧?第8章就在欢声笑语中这么结束了。下回书我们就要开始编程了,还记得小时候那个可爱迷人的护士阿姨是怎么对你说的么?

“牛牛别怕,不疼的。”


15 04, 2005
Unix痛恨者手册.2[转贴]
作者 xzh2000 19:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
UNIX Ohne Worter (不会翻 – me)

我被这里散步的文档无用论观点深深折服了。事实上,我进一步认为文档就是毒品,我对于它的依赖性是人为造成的。在专业人士的帮助下,我想我能够戒掉它。

而且,我的良心告诉我不能再靠贩卖这种毒品为生了。我决定回到数学研究院脱胎换骨,彻底从这个寄生虫一样的职业中脱身。

虽然下面这份文档似乎表明了我中毒有多么深,可我还是觉得下一版SGI中应该把它提供给用户。这不过是暂时之举,以后会把它搞掉的。

这是我的建议:

标题:“无言UNIX”

对象:UNIX新手

简介:提供在没有文档条件下使用UNIX的通用策略。展示在没有文档条件下摸清任何操作系统的通用原则。

内容:

介绍:“无文档”哲学简介
为什么手册是恶魔
为什么man手册是恶魔
为什么你还是应该读这份文档
“这将是你读的最后一份文档!”

第一章:如何猜测可能存在哪些命令

第二章:如何猜测命令名

UNIX的怪异缩略命名法
案例:grep

第三章:如何猜测命令选项

如何破解怪异的使用说明
案例:tar
如何知道什么时候顺序是重要的
案例:fine

第四章:如何知道运行正确:没有消息就是好消息

从错误中恢复

第五章:口头传统:你的朋友

第六章:如何获得和维持一个活生生的UNIX高手

如何喂饱你的高手
如何让高手高兴
提供全部新闻组连接的重要性
为什么你的高手需要最快的计算机
免费可乐:高手的长生不老药
如何保持高手身体健康
高手什么时候睡觉?

第七章:常见疑难:你的高手不理你了

识别愚蠢的问题
如何安全地提出愚蠢问题

第八章:如何承受压力

如何对待失败

注:可能只有6、7章才是真正需要的。是的,这才是正路:我把它称为“UNIX高手驯养指南”。

OK, 再也没有文档了。下回书将带你进入sendmail的美好世界,为什么“使用sendmail的感觉和得了花柳病一样。”?下回分解。

标题: 第八章 csh, pipes和find (part 1)

UNIX演义又开始了,本来这回书要表一表sendmail和花柳病的关系,不过sendmail似乎已经从良了,从良妓女比贞节烈女对我们民族的贡献要大得多,所以不想再找她麻烦了,对妓女发展史和性病斗争史感兴趣的,我们可以私下交流。

作为程序员而不是妓女的你,可能对UNIX的编程环境更感兴趣,所以这一节中介绍一下UNIX Shell的历史。我GPL,你没花钱,所以只能任我摆布,我上什么你就吃什么,不要废话。

GPL的好处在于你不必为自己的工作负责,也不必对用户负责,所以sourseforge上充斥着良莠不齐的自由项目。我希望我的心上人也能理解这一点,这一切的开始并不是为了什么价值、责任、过去或是未来,这一切甚至不是为了现在,这一切只是源于passion。

在大海吐出的每个泡沫中
在上班路上吸入的每一粒尘埃中
在过去岁月的每一次阵痛中
在一次一次睡去和醒来中
在天气预报和新闻联播中
在七月流火和九月授衣中
在七月长生殿七日中
在矢车菊和芙蓉中
在长绳纪日中
在天长地久中
在你身边
在我心里
无须寻求意义

第八章 csh, pipes和find

强有力的工具给强有力的傻瓜

“有些操作系统从没有被好好计划,以至于只好用反刍的噪音来命名它的命令(awk, grep, fsck, norff),我想到这个就反胃。”

—— 无名氏

UNIX所谓的“强大工具”是个骗局。这不过是UNIX为了那些东拼西凑的命令和工具所打的幌子。真正的强大工具不需要用户付出太多努力就能提供强大的功能。任何会使改锥和钻头的人都会用电动改锥和电钻。他们不需要搞懂电学、电机、转矩、电磁学、散热或维护。他们只需要把它通上电,带上安全眼镜,然后打开开关。许多人连安全眼镜也不省了。你在五金商店里找不到有致命缺陷的工具:它们不是根本没能投放市场,就是被诉讼搞得焦头烂额。

UNIX设计者的最初目标是提供简单的工具,然而现在的工具则充满了过分的设计和臃肿的功能。比如ls这个列文件的命令竟然有18个选项,提供从排序到指定显示列数的种种功能,而这些功能如果用其他程序实现会更好些(以前正是这样的)。find命令除了查找文件以外还输出cpio格式的文件(而这个功能其实用UNIX名声狼藉的管道很好地实现)。今天,和UNIX类似的电钻将有20个旋钮,连着不标准的电源线,不匹配3/8英寸和7/8英寸的钻头(而这一点会在手册的BUG一章中说明)。

和五金店里的工具不同,许多UNIX强大工具是有缺陷的(有时对文件是致命的):比如tar的不接受超过100个字符的文件名;又比如UNIX调试器总是垮掉,这还不够,它的core文件将覆盖你自己的core,让你下次可以用调试器去调试调试器在调试调试器中生成的core。

Shell游戏

UNIX的发明人有个伟大的想法: 把命令解析器作为一个用户程序实现。如果用户不喜欢缺省的命令解析器,他可以自己写一个。更重要的是,shell能够进化,这样shell将不断进步,变得越来越强大,灵活和易用,至少理论上是这样。

这真是个伟大的想法,不过弄巧成拙了。功能的逐渐增加带来的是一团糟。因为这些功能没有经过设计,只是在不断演化。和所有编程语言所遭到过的诅咒一样,那些利用这些功能的既存shell脚本成为了shell的最大敌人。只要有新的功能加入shell,就会有人在自己的脚本中使用它,这样这个功能就从此长生不老了。坏主意和臭功能往往怎么也死不掉。

于是,你得到了一个不完整、不兼容的shell的大杂烩 (以下每个shell的描述都来自于他们各自的man pages):

sh 是个命令编程语言,用于执行来自终端或文件的命令。
Jsh 和sh一样,但具有csh风味的工作控制 (job control)
Csh C类型语法的shell
Tcsh emacs编辑口味的csh
Ksh KornShell,你的另一个命令和编程语言
Zsh Z Shell
Bash GUN Bourne-Again Shell (GNU Bourne复出Shell)

五金商店里的螺丝刀和锯子,尽管可能来自3、4个不同的厂商,但操作方法都差不多。典型的UNIX在/bin或/usr/bin下存了成百个程序,它们来自众多自以为是的程序员,有着自己的语法、操作范例、使用规则(这一个可以当成管道,而那一个则操作临时文件),不同的命令行参数习惯,以及不同的限制。拿grep和它的变种fgrep, egrep来说,哪一个是最快的?为什么它们接受的参数都不一样,甚至对正则表达式的理解也不尽相同?为什么不能有一个程序提供所有功能?负责的家伙在哪儿啊?

当把命令之间的种种不同都深深烙在脑海中后,你还不能避免被惊着。

Shell Crash

下面这条消息来自哥伦比亚大学编译原理课程的BBS。

Subject: Relevant UNIX bug
October 11, 1991

W4115x课程的同学们:

我们刚学习了活动记录(activation record),参数传递(argument passing)和函数调用规则(calling conventions),你们是否知道下面的输入将让任何一个cshell立刻崩溃?

:!xxx%s%s%s%s%s%s%s%s

你们知道为什么么?

以下的问题供你们思考:

Shell遇到 “!xxx”会做什么?

Shell遇到 “!xxx%s%s%s%s%s%s%s%s”会做什么?

为什么cshell会崩溃?

你将如何修改有关代码来解决这个问题?

最重要的一点:

当你(是的,就是你)将这个前途远大的操作系统用21个字符治服的时候,你觉得天理能容么?

你可以自己试一试。根据UNIX的设计,如果shell垮掉了,你的所有进程将被杀死,你也会被踢出系统。其他操作系统在遇到非法内存访问错误时会弹出调试器,但不是UNIX。

可能这就是为什么UNIX shells不让你在shell的地址空间里动态加载自己的模块,或者直接调用其他程序中的函数。如果这样就太危险了。一步走错,唉哟,你已经被踢出门外了。愚蠢的用户是应该被惩罚的,程序员的错误更是不可容忍。

下回书里我们将进入色彩斑斓的UNIX语法世界。


15 04, 2005
Unix痛恨者手册.1[转贴]
作者 xzh2000 19:45 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流
转载自:Simson Garfinkel, Daniel Weise, Steven Strassmann

一本很有趣的书, 是那些用惯UNIX的人对UNIX的各种指责,诋毁,谩骂和嘲笑. 是由爱而生的恨. 即使当成一本高级笑话书,也是很有价值的.

UNIX痛恨者手册

By Simson Garfinkel, Daniel Weise, Steven Strassmann

第一章 UNIX

世界上第一个电脑病毒

“伯克利的两项最著名的产品是UNIX和LSD (一种毒品),我想这不是巧合”

病毒依赖于微小的个体和强大的适应性得以生存。它们并不复杂:它们没有为呼吸,新陈代谢,肌体活动等功能提供什么,只有足够的DNA或RNA以供繁衍。比如,肺炎病毒比起它们入侵的细胞要小得多,但它们在每个肺炎流行季节都能够产生新的变种,造成无数人死亡。

一个好病毒的特点是:

* 个头小
病毒做的事情不多,所以不需要很大。有人认为病毒不是生物,只是一些有破坏性的酸和蛋白质。
* 可移植性
病毒经常变异,以便以不同的方式攻击不同的细胞。据说AIDS就是由猴子身上的病毒变异而成的。
* 耗尽寄主的资源
* 快速变异

UNIX具有以上所有优点。在它刚诞生时,很小,功能不多,缺乏真正操作系统所需要的功能(如文件映射,告诉IO,健壮的文件系统,设备锁,合理的进程间通讯),它的移植性很好。UNIX耗尽主机的资源,没有系统管理员的时时呵护,UNIX会不断恐慌(panic),core dump,挂起。UNIX不断变异:同一个补丁在一个版本上工作,在另一个版本上就不行。

UNIX是有用户界面的计算机病毒。

标准化那些不一致的

“标准的伟大之处在于它可以有很多” --- Grace Murray Hopper

自从UNIX 80年代开始流行以来,UNIX厂商一直在努力进行UNIX标准化工作。SUN, IBM,HP和DEC在这个他们自己制造的难题上倾注了数百万美元。

为什么UNIX厂商不喜欢UNIX标准化?

许多用户受够了复杂繁多的UNIX,最终只好使用Windows,因为他们的这个UNIX无法支持那个UNIX上的应用程序。

如果UNIX标准化了,谁还会买SUN的机器呢

标题: 第二章 欢迎新用户

欢迎新用户如同用一把上了六颗子弹的左轮枪玩俄罗斯轮盘赌Ken Thompson 自己设计过一辆汽车。和其他车不同,它没有速度计、汽油计,也没有那些愚蠢的指示灯讨司机的厌。如果司机犯了什么错误,仪表盘上就会出现一个大大的“?”。“有经验的司机,”Thompson说,“应该知道哪儿搞错了。”

计算机系统的新手需要一个友好的系统。至少,一个得体的系统会这样招待自己的客人:

与功能有逻辑关系的命令名
对危险命令的小心处理
一致的命令行为和命令行参数解析
易得和易读的在线文档
当命令失败时,给出可理解和有用的错误反馈

在建造UNIX的过程中,从没邀请过住户。来访的都是些戴着安全帽的建筑工人,被安插在这个破木板房子的各个角落。不幸的是,不仅没有人性因素(human factors)工程师的参与,而且住户的需要就从来没有被考虑过。所以抽水马桶、中央供暖、窗户等这些方便设施在后期就很难再添加了。但是建筑师们仍然为UNIX的设计而骄傲,似乎他们并不介意在一个没有烟火探测器的屋子里睡觉。

在其发展的大部分历史中,UNIX只是大学和工业研究人员的研究工具。随着大批便宜工作站的出现,UNIX作为平台软件进入了新时代。这一变化大约发生在 1990年,其标志就是工作站厂商把C编译器从UNIX发布中剔除出去,以降低成本满足非开发用户的需求。可见,只是最近几年中UNIX厂商才开始考虑非程序员用户的需要,开始为他们提供shell以外的图形界面。

含糊的命令名

UNIX新手总是对UNIX对命令的命名表示惊讶。在DOS和Mac上受的教育不足以让他们体会到cp、rm、ls这类两字母命令的简洁和优美。

像我们这样用过70年代早期的IO设备的人都能理解,ASR-33 Teletype这类设备的速度、可靠性,以及它的键盘是万恶之源。和今天这种基于反馈原理、只需要关闭一个微开关的键盘不同,你必须用足力气揿下Teletype的键至少半英寸,以发动一个类似自行车上用的小型发电机,在上面操作要冒指骨骨折的危险。

如果当时Dennis和Ken用的是Selectric而不是Teletype,可能今天我们敲的将不是”cp”和”rm”而是”copy”和”remove”了。(Ken Thompson曾被问道如果他能重新设计UNIX他将做什么修改,他回答说:“我会在creat命令后加上个e。”),科技在拓宽我们的选择的同时,也能限制我们的选择,此一例也。

20多年过去了,还有什么理由延续这一传统呢?理由就是“历史的无可替代的力量”,历史就是那些存在的代码和教科书。如果一个厂商用remove替代了rm,那么所有UNIX教科书就不适用于这一系统了,每个使用rm的shell脚本都需要被修改。而且这也不合POSIX标准。

一个世纪前,打字高手由于击键过快,经常把打字键柄搅在一起,工程师设计了QWERTY键盘,于是问题得到了解决,因为没人能在这样的键盘上打得快。计算机的键盘不再有机械键柄,但QWERTY的键盘布局仍然在使用。同理,在未来的一个世纪中,我们仍然会继续使用rm。

事故会发生

用户十分关心自己的数据和文件。他们使用计算机来产生、分析和存储重要信息。他们相信计算机能够保护他们的重要财产。如果没有了这种信任,他们和计算机的关系就会蒙上阴影。UNIX辜负了我们的信任,它拒绝对使用危险命令的用户提供保护。比如rm就是以删除文件为目的的危险命令。

所有UNIX新手都有不小心无可挽回地删除重要文件的经历,即使是专家和系统管理员也遇到过。因此而每年损失的时间、精力可能价值几百万美元。这是个值得解决的问题;我们不理解为何UNIX一直拒绝解决这一问题。难道结果还不够悲惨么?

UNIX比其他操作系统更需要提供恢复删除功能,原因是:

UNIX文件系统没有版本功能

自动的版本维护能保留文件的历史版本,防止新版本冲掉老版本。
UNIX程序员在错误处理方面臭名昭著许多程序不检查是否所有内容都被写入了磁盘,或被写入的文件是否存在。有些程序总是删除输入文件。

UNIX shell扩展“*”,而不是其子命令

于是rm这样的命令就无法检查“*”这些危险的参数。即使是DOS也对”del *.*”有些提示。但在UNIX下,rm * 和 rm file1 file2…是没有区别的。

删除是永久的

UNIX没有undelete命令。许多其他更安全的系统则只是标记被删除文件所用的块为“可被使用”,然后把它移到一个特殊目录下。如果磁盘满了,这些文件块才会被重新使用。这一技术不是什么火箭科学,Macintosh在1984年就提出了“回收站”的想法,而Tenex早在1974年就采用了这一技术。连DOS也提供了简单的undelete功能,虽然并不总有效。

这四个问题互相合作,制造了无数无法恢复的重要文件。解决的方法早就存在,但UNIX“标准”版中却从来没有提供。

欢迎来到未来世界。

“rm”就是终结

许多实际的恐怖故事说明了以上的这些原则。以下是alt.folklore.computers新闻组上流传的一系列故事中的一个:

Date: Wed, 10 Jan 90
X-Virus: 6
From:
djones@megatest.uucp (Dave Jones)
Subject: rm *
Newsgroups: alt.folklore.computers

是否有人曾想执行以下命令:

% rm *.o

结果却打成了:

% rm *>o

现在你得到了一个空文件o,以及大量的空间来存放它!

事实上,你可能连o也得不到,因为shell的文档并没有说o是在*被扩展前还是被扩展后被建立的。

上回书说到如何用rm获得一个空文件和很大的磁盘空间,下面是另一种用法:

Date: Wed, 10 Jan 90
X-Virus: 6
From:
ram@attcan.uucp
Subject: Re: rm *
Newsgroups: alt.folklore.computers

我也被rm搞过。有一次我想删除一些/usr/foo/下的东西,我在/usr/foo下敲了以下命令:

% rm –r ./etc
% rm –r ./adm

当我要删除./bin目录时,我忘敲了那个点。我的系统似乎不太喜欢这个。

当受了这一致命一击后,UNIX就彻底完蛋了。聪明的系统会给用户一个恢复的机会(或至少提醒用户这一操作会导致系统崩溃)。

UNIX迷认为偶尔的文件误删除是正常的。比如,可以参考以下下面这个comp.unix.questions上的FAQ:

6) 如何反删除一个文件?

也许有一天,你不小心执行了一下这个命令:

% rm * .foo

然后发现你把“*”删掉了。你应该把这当作人生的一课。

当然称职的系统管理员应该定时备份系统。所以你最好问问他们手中是不是有你的文件备份。

“人生的一课”?没有任何一个其他厂商用这样的态度对待一个有缺陷的产品。“大人,我知道您的油箱炸了,但这是人生的一课。”“陪审团的先生女士们,我们将证明电锯保险开关的失效不过是给用户上的人生的一课。”不错。

改变rm的行为也不是个办法

被rm咬了几次后,往往会想到用”rm -i”替换rm,或整个替换掉rm,把所有被删除的文件放到~/.deleted目录中。这些小技巧让用户有了错误的安全感。

Date: Mon,16 Apr 90 18:46:33 199
X-Virus: 6
From: Phil Agre <agre@gargoyle.uchicago.edu>
To: UNIX-HATERS
Subject: deletion

在我们的系统上,“rm”并不真正删除文件,而是给文件换了名,这样”undelete”(不是unrm)这样的工具就能恢复被删的文件。

这个功能让我不再对删除文件多加小心,反正删掉了也能找回来。可是,我错了。Emacs中的删除并不支持这个功能,Dired命令也是如此。这当然是因为文件恢复并不是操作系统的一个功能。

所以,现在我脑子里有两个概念,一个是”deleting”一个文件,一个是”rm’ing”一个文件。当我的手要我的脑子删除一个文件时,我总要把这两个概念区分一遍。

一些UNIX专家由此得出了荒谬的结论,他们认为最好别把rm搞得更友好。他们争辩说,让UNIX更友好的努力往往适得其反。不幸的是,他们是对的。

Date: Thu, 11 Jan 90 17:17 CST
X-Virus: 6
From:
merlyn@iwarp.intel.com (Randal L. Schwartz)
Subject: Don’t Overload commands! (was Re: rm *)
Newsgroups: alt.folklore.computers

请千万别让人用“安全”命令去替换标准命令。

(1) 许多shell程序会对多嘴的rm感到惊讶,而且也不会想到删除了的文件仍然占有磁盘空间。

(2) 并不是所有删除操作都是安全的,有户会因此产生一切都能恢复的错觉。

(3) 那些不标准的命令对系统管理员来说尤其可恨。如果你想有个有确认功能的”rm”,用下面的命令:

% alias del rm -i

千万别替换rm!

最近,comp.unix.questions上有过一次对系统管理员的调查,让他们说出最恐怖的系统管理故事。72小时内,就有了300多条回应。许多和我们上面描述的文件删除有关。可笑的是,这些可是UNIX高手。然而正是他们在对“UNIX对用户不友好”这类指责进行着辩护。

对用户不友好?UNIX对系统管理员又友好过么?请看

Date: Wed, 14 Sep 88 01:39 EDT
X-Virus: 6
From: Matthew P Wiener <weemba@garnet.berkeley.edu>
To:
RISKS-LIST@kl.sri.com
Subject: “Single Keystroke”

在UNIX上,即使是有经验的用户也会误用rm。我从来没有误删除过文件,可是有一天,我用!r重复执行一个历史命令,我惊讶地发现被运行的是”rm –r *”。

为什么不能有个没有history功能的shell?

我还听到过一个用户试图删除一个名叫”*”的文件,好在他没有权限。

这个用户还想修改shell来避免对*进行展开。不幸的是,这个补救如同是在渗水的墙上再刷一层漆,治标不治本。

在线帮助

用户读打印文档的次数比他们参加选举投票的次数还要少。只有触手可及的在线文档才是有用的。下面我们看看UNIX的man是如何让最需要它的新用户失望的。

不是每个命令都是平等的,有些是外部命令,有些是内部命令。有些有man page,有些没有。UNIX要求你能区分这些命令。比如,wc, cp和ls是外部命令,它们都有man page,而fg, jobs, set和alias(这些长文件名是从哪里来的?)是内部命令,它们没有man page。

UNIX告诉新手用”man command”命令获得帮助,他们可不知道并不是所有命令都是如此。另外,如果他们的shell设置得有些不标准,他们就只能请教高手来获得帮助了。

错误信息和错误检查?没门!

新手很容易犯错误,比如用错命令,或用错选项。系统应该能识别这些错误,并且反馈给用户。不幸的是,UNIX程序从来不麻烦自己。相反,UNIX往往把各种错误混在一起,直到产生致命的结果。

上面一节我们说明了rm如何容易造成误删除。但你可能不知道不用rm也能很容易地误删除文件。

想删除你的文件么?试试编译器

一些cc版本经常根本不考虑用户的可能输入错误,而删除一些源代码文件。一些本科生常常着了道。

Date: Thu, 26 Nov 1992 16:01:55 GMT
X-Virus: 6
From:
tk@dcs.ed.ac.uk (Tommy Kelly)
Subject: HELP!
Newsgroups: cs.questions
Organization: Lab for the Foundations of Computer Science, Edinburgh UK

我刚才想这么编译程序:

% cc –o doit doit.c

不小心敲成了:

% cc –o doit.c doit

不用说我的doit.c被冲掉了。有没有办法能恢复我的程序?(我干了整整一个上午)

其他一些程序也有同样的行为:

Date: Thu, 1 July 1993 09:10:50 - 0700
X-Virus: 6
From: Daniel Weise <Daniel@dolores.stanford.edu>
To: UNIX-HATERS
Subject: tarred and feathered

经过几次努力,我总算从欧洲的一个脆弱ftp站点上下载了了一个3.2M的文件。该untar它了。我敲了一下命令:

% tar –cf thesis.tar

…没有回应。

老天!

是不是该用x选项而不是c?

是的。

tar是不是给出了错误信息说没有指定输入文件?

没有。

tar是否感觉到有什么不对劲?

没有。

tar是不是真的什么也没有tar?

是的。

tar是否把thesis.tar用垃圾覆盖了?

当然,这就是UNIX。

我是不是需要再花 30分钟从欧洲下载这个文件?

当然,这就是UNIX。

我敢肯定有不少人遇到过这一不幸,有那么多的解决办法,比如:错误信息,文件版本化,确认用户是否想覆盖一个已有文件,等等等等。tar似乎在有意给用户找麻烦。

对于经常用tar备份的系统管理员来说,这个bug更是危险。不少系统管理员都曾经在备份脚本中错误地使用过“tar xf…”。在需要恢复备份的时候,才发现原来什么也没做。

欲知是否还有其他这样的恐怖命令,请听下回分解。

上回书说到cc、tar等命令是如何帮助你删除重要文件的。UNIX的强大当然不局限于此。

因为没有错误检查,在众多“UNIX 强大编程工具”的支持下,用户有各种选择来删除他们的重要文件。

Date: Sun, 4 Oct 1992 0:21:49 PDT
X-Virus: 6
From: Pavel Curtis <pavel@parc.xerox.com>
To: UNIX-HATERS
Subject: So many bastards to choose from…

我有一个总在运行的程序foo,用来提供网络服务,并且每隔24小时检查系统内部状态。

一天,我cd到foo所在的目录,因为这不是开发目录,我想看看foo的版本是多少。代码是由RCS来维护的,所以我自然而然地使用了以下命令:

% ident foo

先别管RCS的种种劣迹,也别管ident如何原始疯狂。我这次的麻烦是,我的手指自行其是地选择了更像一个词的indent而不是ident:

% indent foo

indent是UNIX的一个愚蠢的C代码风格转换工具。那个写indent的混蛋是否判断了一下输入文件真的为C程序么 (天哪,至少可以看看文件的后缀是否为.c吧)?我想你知道答案。而且,这个SB(Said Bastard)认为如果你只给了一个参数,那么你就是想要进行在线风格转换。不过别着急,这个SB 考虑到了可能带来的麻烦,他保存了一个备份foo.BAK。然而他是否只是简单地把foo换了个名字呢?没有,他选择了拷贝(毫无疑问,那个写 indent的程序员在准备备份的时候已经打开了foo,而且rename系统调用是后来才有的)。

现在,你可能知道发生了些什么了…

我那正在运行中的foo在准备页面扇出的时候,发现原来的可执行文件已经不在了,这可不是什么好事,于是我的foo崩溃了,我丢掉了20小时的系统状态信息。

自然那些设计(咳嗽)UNIX的混蛋们对复杂的文件版本化功能不感兴趣,而这一功能就能救我的命。当然,那些混蛋也从未想到过对准备进行页面扇出的文件加锁,是不是?

有那么多混蛋可供选择,为什么不把他们都宰了?

Pavel

想象一种散发氯气的油漆,按照说明,用在户外是不成问题的,但如果用它刷你卧室的墙壁,你的脑袋就要大了。这样的油漆能在市场上存活多久呢?当然不会超过20年。

错误信息笑话

当你看到饭馆跑堂的把一盘菜撒在顾客脑袋上时,你会笑么?UNIX迷会的。但那些无助的用户对着错误信息百思不得其解的时候,他们是最先发出笑声的。

有人整理了一些UNIX最为可笑的错误信息,把他发布在Usenet上。他们使用的是C shell.

% rm meese-ethics
rm: messe-ethics nonexistent

% ar m God
ar: God does not exist

% “How would you rate Dan Quayle’s incompetence?
Unmatched “.

% ^How did the sex change^ operation go?
Modifier failed.

% If I had a ( for every $ the Congress spent, what would I have?
Too many (‘s

% make love
Make: Don’t know how to make love. Stop.

% sleep with me
bad character

% got a light?
No match

% man: why did you get a divorce?
man:: Too many arguments.

% ^What is saccharine?
Bad substitute.

% %blow
%blow: No such job.

下面的这些幽默作品来自Bourne Shell:

$ PATH=pretending! /usr/ucb/which sense
no sense in pretending

$ drink <bottle; opener
bottle: cannot open
opener: not found

$ mkdir matter; cat >matter
matter: cannot create

UNIX态度

我们展现了一个非常惨淡的图景: 迷一般的命令名,不一致和无法预计的运行结果,危险命令没有保护,无法接受的在线文档以及在错误检查和容错性方面的稀松工作。那些参观UNIX的人不是为了得到热情款待,他们不是迪斯尼公园中的游客,更像是执行任务中的联合国维和部队。UNIX怎么会搞成这个样子?如我们曾指出的那样,其中有一些是历史原因造成的。但是还有其他的原因:那就是多年来形成的UNIX文化,这种文化被称为 “UNIX哲学”。

UNIX哲学不是来自Bell实验室或UNIX系统实验室的手册。他是自然形成的,其中包含了许多人的贡献。Don Libes和Sandy Ressler在《UNIX生活》(Life with UNIX)中对UNIX哲学作了很好的总结:

小即是美
用10%的工作解决90%的任务
如果必须作出选择,选择最简单的那个。

根据UNIX程序和工具的实际表现来看,对UNIX哲学更为精确的总结应该是:

小的程序比正确的程序更好
粗制滥造是可以接受的
如果必须作出选择,选择责任最小的那个。

UNIX没有哲学,UNIX只有态度。这个态度指出简单的做了一半的工作比复杂完整的工作更好。这个态度指出程序员的时间比用户的时间更为珍贵,即使用户比程序员要多得多。这个态度指出达到最低要求就足够了。

Date: Sun, 24 Dec 89 19:01:36 EST
X-Virus: 6
From: David Chapman <zvona@ai.mit.edu>
To: UNIX-HATERS
Subject: killing jobs; the Unix Design Paradigm

我最近学会了如何在UNIX上杀掉任务。在这个过程中我体会到了不少UNIX的强大和智慧,我想应该和大家分享一下。

你们中的大多数当然不用UNIX,所以知道如何UNIX上杀任务估计没什么用。但是,你们中的一些人,包括我,可能会经常运行一些TeX任务,那么学会杀任务就显得尤为重要了。“kill”命令继承了UNIX的设计原则,所以下面的一些体会有更为通用的意义。

在UNIX中你可以用^Z挂起一个任务,或者用^C终止一个任务。但是LaTex自己截获^C。结果是,我经常搞出一堆LaTex任务。我对此到不在乎,可还是觉得应该想办法除掉它们。

许多操作系统有“kill”这样的命令,UNIX也不例外。大多数操作系统上的“kill”仅仅用来杀死进程。但UNIX的设计更为通用:“kill”被用来向进程发送一个信号,这体现了UNIX的一个设计原则:

尽量使操作通用,给予用户强大力量(power)

“kill”命令功能很是强大;你能用它给进程发送各种各样的信号。比如,9这个信号用来杀死进程。注意到9是最大的一位数,这体现了UNIX的另一个设计原则:

使用能体现功能的最简单的名字

在其他我知道的操作系统上,不带参数的“kill”用于杀死当前任务。单UNIX的“kill”总是需要参数。这体现了UNIX的一个明智的设计原则:

尽量使用长参数或提示来防止用户不小心把自己**了(screwing himself)

这一设计原则在许多UNIX应用程序中得到了体现,我不想列举它们,但还是想提一下UNIX上logout和文件删除的实现,希望你知道我的意思。

在其他我知道的操作系统上,“kill”接受的参数是任务名。这不是好的选择,因为你可能有许多LaTex任务同时运行,它们都有同样的任务名“latex”。所以“kill –9 latex”可能会产生歧义。

和其他操作系统一样,UNIX提供一个列出任务的命令“jobs”,下面是一个例子:

zvona@rice-chex> jobs
[1] – Stopped latex
[1] – Stopped latex
[1] + Stopped latex

这样你可以用job号(表示在[]中)标识一个任务。

如果你受到那些未经精雕细刻的操作系统的影响,你会想用“kill –9 1”来杀掉第一个latex任务。但你会发现下面的错误信息:

zvona@rice-chex> kill -9 1
1: not owner

正确的做法是使用进程号,比如18517。你能用“ps”命令获得它。当找到了相应进程号后,你只要:

zvona@rice-chex> kill -9 18517
zvona@rice-chex>
[1] Killed latex

注意到UNIX在你的任务被真正杀掉之前就给了你提示符。这又体现了一个UNIX设计原则:

对于给用户的反馈,能少说绝不多说,能晚说绝不早说。以免过多信息所可能导致的用户脑损伤。

我希望这些体会能对大家有用。在这一学习过程中,我自己当然被UNIX设计哲学所深深吸引了。我们都应该从UNIX kill命令的雅致、强大和简洁中学到些东西。

第二章就这么完了,经历了这么多艰难困苦的你已经不是新手了,下回书将介绍UNIX之文档,或者说UNIX之没有文档.

标题: 第三章 文档

OK,不是新手的你可能想进一步学习了解UNIX。不错,UNIX文档正是你需要的。

文档
什么文档

“使用UNIX进行操作系统教学的一个好处是,学生的书包能装下所有的UNIX源代码和文档。”

—— John Lions, 新南威尔士大学,1976年在谈论UNIX版本6时说的一段话。

多年以来,有三个获得UNIX有关知识的简单途径:

阅读源代码
写一个自己的UNIX
给写UNIX的程序员打电话(或是发email)

和荷马史诗一样,UNIX被口头传诵着。如果不成为内核黑客,你就不可能是一个严肃的UNIX用户——或者至少应该在身边有个触手可及的内核黑客。那个确实存在的文档——man手册——不过是一些已经知道自己在做什么了的人所收集的一些备忘录。UNIX的文档是这么简洁,你能在一下午读完它。

在线文档

man工具是UNIX文档系统的基础。man接受你输入的参数,找到相应的文档文件,把它输出到nroff(还包括一些地球上没有其他地方使用的一些文本格式宏),最后结果被发送到pg或more。

起先,这些零碎文档被叫做”man页”(man pages),因为这些文档多为一页左右(多数情况是少于一页)。

man对于那个时代是个不错的玩意,但那个时代早已一去不复返了。

多年来,man系统不断发展成熟。值得称赞的是,它并没有像UNIX的其他部分一样搞得代码混乱程序难懂,可是它也没变得更有用。事实上,在过去的15年中,UNIX的文档系统只有了两处改进:

catman. 程序员曾“惊喜地”发现除了nroff格式以外,他们还能存储处理过的文档文件,这样文档调出的速度就更快了。 对于今天的快速处理器,catman似乎不那么需要了。

但是许多nroff处理过的文档文件仍然占据着用户的几兆磁盘空间。makewhatis, apropos和key (最终构成了man –k功能)是一个对man手册进行索引的系统,这样即使不知道程序的确切名字也能进行查询。

与此同时,电子出版的势头早已超过了man手册。使用今天的超文本系统你能用鼠标从一篇文章跳到另一篇文章;与之相比,man手册仅仅在末尾提供” SEE ALSO”一节,让用户自己再man下去。在线文档的索引功能又是如何呢?今天你可以买到CD-ROM上的牛津英语词典,它对其中的每一个词都加了索引;可是man手册还是仅仅对命令名和描述行进行索引。今天甚至连DOS都提供了有索引的超文本文档。可是man手册还是采用适合DEC打印终端的80列66 行的格式。

公平点说,有些厂商是在看不下去,提供了自己的超文本在线文档系统。在这些系统上,man手册走到了进化的尽头,常常不是过时了,就是根本不存在。

“我知道它就在这里,可就是找不到”

对于今天还在使用man手册的人来说,最大的问题是告诉man你要的man手册就在那里。在以前,查找man手册是很容易的:全都在/usr/man下头。后来man手册按章节分成了不同的目录:/usr/man/man1, /usr/man/man2,/usr/man/man3等等。有的系统甚至把“本地”man手册也放在/usr/man/man1下。

当AT&T发布系统V的时候,情况变得费解了。/usr/man/man1目录变成了/usr/man/c_man,似乎字母比数字更好记。在有些系统上,/usr/man/man1变成了/usr/local/man。那些销售UNIX应用程序的公司开始建立自己的man目录。

最终,伯克利修改了man程序使得它能对环境变量$MANPATH中指定的一系列目录进行查找。这是个伟大的想法,只有一个小毛病:它不工作。(以下省略100字, 因为我太懒了,内容也有些太过时了,Linux上的man还是不错的,除了无法获得shell内部命令的man手册,当然,man bash是一个选择 -- me)。

这个就是内部文档?

一些大的UNIX工具也提供自己的文档。许多程序的在线文档是一行叫人费解的 “使用”(usage)说明。下面是awk的“使用”说明:

% awk
awk: Usage: awk [-f source | ‘cmds’] [files]

是不是挺有用的?复杂一些的程序有着更深入的在线文档。不幸的是,它们有时候描述的似乎不是你正在运行的程序。

Date: 3 Jan 89 16:26:25 EST (Tuesday)
X-Virus: 6
From: Reverend Heiny <Heiny.henr@Xerox.COM>
To: UNIX-HATERS
Subject: A conspiracy uncovered (阴谋被揭露了)

经过几个小时的专心研究,我得出了一个重要的结论:

UNIX是狗屎 (UNIX sucks)

现在,你可能觉得很惊讶,但这是事实。这项研究已经被遍布全球的研究人员所证实了。

更为重要的是,这不仅仅是摊狗屎,而是又稀又粘的臭狗屎,是大写的臭狗屎。看看下面这个例子,你就知道了:

toolsun% mail
Mail version SMI 4.0 Sat Apr 9 01:54:23 PDT 1988 Type ? for help
“/usr/spool/mail/chris”: 3 messages 3 new
>N 1 chris Thu Dec 22 15:49 19/643 editor saved “trash1”
N 2 chris Tue Jan 3 10:35 19/636 editor saved “trash1”
N 3 chris Tue Jan 3 10:35 19/656 editor saved “/tmp/ma9”
& ?
Unknown command: “?”
&

什么样的系统环境(特别是这个到了能开车、投票、喝啤酒年龄的家伙)会拒绝一个它让使用的命令?

为什么用户手册是如此脱离现实?

为什么这些神秘的命令是这么和功能不符?

我们不知道Heiny的问题是什么;和我们上面提到的一些问题一样,这个bug似乎已经被修正了。或者说,它被转移到了其他程序中。

Date: Tuesday, September 29, 1992 7:47PM
X-Virus: 6
From: Mark Lottor <mkl@nw.com>
To: UNIX-HATERS
Subject: no comments needed (无需多说)

fs2# add_client
usage: add_client [options] clients
add_client -i | -p [options] clients
-i interactive mode – invoke full-screen mode

[还有一些选项,这里省略了]

fs2# add_client -i

Interactive mode uses no command line arguments

如何得到真正的文档

实际上,UNIX最好的文档是经常用strings处理程序二进制代码。使用strings你能得到所有程序中定死了的文件名,环境变量,未公开的选项,怪异的错误信息等等。比如,如果你想知道cpp是如何去查找头文件的,你最好使用strings而不是man:

next% man cpp

No manual entry for cpp.

next% strings /lib/cpp | grep /
/lib/cpp
/lib/
/usr/local/lib/
/cpp
next%

嗯…别着急

next% ls /lib
cpp* gcrt0.o libssy_s.a
cpp-precomp* i386/ m68k/
crt0.o libsys_p.a posixcrt0.o
next% strings /lib/cpp-precomp | grep /
/*%s*/
//%s
/usr/local/include
/NextDeveloper/Headers
/NextDeveloper/Headers/ansi
/NextDeveloper/Headers/bsd
/LocalDeveloper/Headers
/LocalDeveloper/Headers/ansi
/LocalDeveloper/Headers/bsd
/NextDeveloper/2.0CompatibleHeaders
%s/%s
/lib/%s/specs
next%

我真笨。NEXTSTEP的cpp使用了/lib/cpp-precomp。你不可能在man手册中发现这些。

next% man cpp-precomp

No manual entry for cpp-precomp.

OK. 这一切究竟是因为什么?这一切究竟是从何而来?下回分解。

上回书说到源代码是最好和唯一的文档,根本原因是因为UNIX是...

给程序员用的,不是用户

别因为UNIX蹩脚的文档而责怪Ken和Dennis。 UNIX刚开始建立文档时并没有遵守业界流行的文档标准,一些bug和潜在的陷阱,而不是程序的功能,被记录了下来,这是因为读这些文档的人往往就是 UNIX系统开发者。对于许多开发者来说,man手册不过是收集bug报告的地方。那些针对初级用户、程序员和系统管理员提供文档的观念是新玩意。可悲的是,由于70年代建立的UNIX文档系统,这一观念实现的并不是很成功。

UNIX世界认识到了这些文档方面的现状,但并不觉得有什么大不了的。《UNIX生活》很客观地说明了UNIX对于文档的态度:

UNIX源代码是最好的文档。毕竟,这是系统用以决定该如何运行时所参照的文档。文档用来解释代码,经常是一些不同的人在不同的时间写成的,而这些人往往不是写代码的人。你应该把这些文档看作是指南。有时候这些文档不过是些期望而已。

但是,更一般的做法是去源代码中寻找未被文档化使用方法和功能说明。有时候你会发现一些文档中记录的功能其实并没有被实现。

这还只是针对用户程序。对于内核,情况就更为糟糕了。直到最近,还没有厂商提供的设备驱动编写和内核级调用函数的文档资料。有人开玩笑说:“如果你觉得需要阅读关于内核函数的文档,那么很可能你本来就不配使用这些函数。”

真相恐怕更为邪恶。之所以没有内核文档是因为AT&T把它的代码看成是商业机密。如果你想写一本说明UNIX内核的书,那么你就等着入被告席吧。

源代码就是文档

命里注定,AT&T的计划弄巧成拙了。由于没有文档,了解内核和应用程序的唯一途径就是阅读源代码。结果是,UNIX源代码在在最初的20年中被疯狂的盗版。咨询人员,程序员和系统管理员去搞UNIX源代码并不是为了重新编译或制作出售自己的UNIX版本,他们需要文档,而源代码是唯一的选择。 UNIX源代码从大学流向周边的高科技公司。这当然是非法的,但是情有可原:UNIX厂商提供的文档不够用。

这并不是说源代码中有什么值钱的秘密。所有读过UNIX代码的人都被下面的一行粗暴注释惊呆过:

/* you are not expected to understand this */ (/* 没指望你能明白 */)

尽管这行注释最开始出现在UNIX V6内核中,但是几乎所有的原始AT&T代码都差不多,其中充满了内联手动优化和怪异的宏。寄存器变量被冠以p, pp和ppp这类的名字。“这个函数是递归的”这样的注释似乎表明递归调用是什么难理解的概念。事实上,AT&T在文档方面好为人师的态度只不过是其写代码的马虎态度的一个反映。

要识别一个蹩脚手艺人其实很简单:你会看到裂缝上的油漆,一个接一个的补丁,所有东西被胶带和口香糖勉强凑合在一块儿。必须承认:如果想从头建立和重新设计什么,必须要多思考,多下功夫。

Date: Thu,17 May 90 14:43:28 -0700
X-Virus: 6
From: David Chapman <zvona@gang-of-four.stanford.edu>
To: UNIX-HATERS

这是man man中的一段,挺有意思:

DIAGNOSITICS

如果你使用-M选项而且给出的路径并不存在,那么输出的错误信息可能有点儿不对。比如/usr/foo/目录不存在,如果你运行:

man –M /usr/foo ls

那么你得到的错误信息是“No manual entry for ls”(“没有ls的手册记录”)。正确的错误信息时告诉你目录/usr/foo不存在。

有写这段说明的功夫,恐怕足够修改这个bug了。

无言UNIX:课程设置建议

Date: Fri, 24 Apr 92 12:58:28 PT
X-Virus: 6
From:
cj@eno.corp.sgi.com (C J Silverio)
Organization: SGI TechPubs
Newsgroups: talk.bizarre
Subject: UNIX Without Words (无言UNIX)

[在一场关于文档无用论的激烈辩论中,我提出了下面这个建议。我胆子小,所以现在才敢公开,供大家参考。]

UNIX Ohne Worter (不会翻 – me)

我被这里散步的文档无用论观点深深折服了。事实上,我进一步认为文档就是毒品,我对于它的依赖性是人为造成的。在专业人士的帮助下,我想我能够戒掉它。

而且,我的良心告诉我不能再靠贩卖这种毒品为生了。我决定回到数学研究院脱胎换骨,彻底从这个寄生虫一样的职业中脱身。

虽然下面这份文档似乎表明了我中毒有多么深,可我还是觉得下一版SGI中应该把它提供给用户。这不过是暂时之举,以后会把它搞掉的。

这是我的建议:

标题:“无言UNIX”

对象:UNIX新手

简介:提供在没有文档条件下使用UNIX的通用策略。展示在没有文档条件下摸清任何操作系统的通用原则。

内容:

介绍:“无文档”哲学简介
为什么手册是恶魔
为什么man手册是恶魔
为什么你还是应该读这份文档
“这将是你读的最后一份文档!”

13 04, 2005
AIX资源监控与调制[转贴]
作者 xzh2000 19:35 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
性能优化以及确定系统中的性能瓶颈是系统管理员的主要任务之一。在一个计算机系统中,CPU、内存、硬盘和网络是影响系统性能的主要因素,因此系统性能调整也主要在于如何在这些资源中获得某种平衡,以满足人们对系统性能的期望。性能调制需要很多技巧,知识以及经验,不能仅靠分析统计数字,图表就可取得,性能调制有时是一件复杂甚至是非常困难的任务。
如同其它UNIX系统一样,AIX也给系统管理员剪裁系统提供了非常丰富的手段。这里我们简单介绍RS/6000 AIX系统中几个用于监控和调制多项系统资源的工具,每个工具的功能都很强,如想更透彻地了解这些命令的用法,请参考有关技术资料或手册。这里讲述的命令将不仅仅局限于CPU、硬盘、内存或网络资源的某个方面,它们可用于其中的一项或多项资源。
AIX监控工具
1、iostat
iostat命令主要通过观察物理磁盘的活跃时间以及他们的平均传输速度,监控系统输入/输出设备负载。根据iostat命令产生的报告,用户可确定一个系统配置是否平衡,并据此在物理磁盘与适配器之间更好地平衡输入/输出负载。
iostat工具的主要目的是通过监控磁盘的利用率(tm_act字段),而探测到系统中的I/O瓶颈。iostat还可用于确定CPU问题,辅助容量规划,并可以为最终解决I/O问题提供相关材料。vmstat和iostat联合使用,可捕获到确定与CPU,内存和I/O子系统有关的性能问题的必需数据。
iostat命令可产生下面四种类型的报告:
· tty和CPU利用情况
· 磁盘的利用情况
· 系统吞吐率
· 适配器吞吐率
2、netpmon
netpmon命令可以监控关于网络行为的系统事件和性能以及网络行为对CPU的消耗。netpmon命令在指定的监控周期报告网络行为。
netpmon启动后直至发布trcstop命令终止它之前,一直在后台运行。如果使用缺省设置,trace命令将会在netpmon命令之后立即自动启动。另外,netpmon中还可用trcon命令选择在后面的某个时间跟踪。当这种跟踪用trcstop命令终止后,netpmon命令就会输出它的报告并退出。缺省时报告会输出到标准输出,需要时也可以重定向到某个文件。
netpmon命令还可以在一次先前产生的跟踪中以脱机模式使用。在这样的情况下,需要用gennames命令产生一个文件。该文件必须在trace终止后立即产生。
所产生的报告中包括CPU使用情况、网络设备驱动器I/O情况、互联网络套接字调用,以及网络文件系统(NFS)I/O信息:
· CPU use:netpmon命令报告线程和中断处理器对CPU的使用情况。该命令将网络相关行为的CPU使用情况与其它行为的CPU使用情况区分开。
· Network Device Driver I/O:netpmon命令监控网络适配器上所通过的I/O统计。
· Internet Socket Calls:netpmon命令在互联网络套接字上监控read,recv,recvfrom,write,send以及sendto子程序。ICMP,TCP,UDP这几个协议的每个进程都会予以报告。
· NFS I/O:netpmon命令监控客户NFS文件上的read和write子程序,NFS客户上的RPC请求以及NFS服务器的read和write请求。
3、PDT(性能诊断工具)
PDT通过收集和集中各种性能、配置和可用数据自动找出性能问题。PDT评估系统的当前状态并跟踪系统在工作量和性能上的变化。PDT数据收集和报告很容易起用,不需要更多的管理行为。
虽然许多常见的系统性能问题都有特定性,但PDT还试图用一些被认为性能好的系统中的通用概念来帮助它查找问题。这些概念包括:
· 资源的平衡使用
· 在限定范围操作
· 确定的工作量趋势
· 无错误操作
· 系统参数得到适当设置。
4、ps
ps命令是UNIX系统中最常见的命令,它主要显示系统中关于进程的统计和状态信息,如进程ID,I/O行为以及CPU利用率等。利用ps命令提供的信息,可决定一个进程运行了多长时间,进程使用了多少CPU时间,以及进程是否受系统的惩罚。还可用ps命令确定进程使用了多少内存,完成多少I/O,进程的优先级以及是谁创建了进程。
下面这几个命令组合对于管理RS/6000 AIX系统有帮助:
(1)显示10个消耗CPU最多的进程:
# ps aux |head -1 ;ps aux |sort -rn +2 |head –10
(2)显示10个消耗存储空间最多的进程:
# ps aux |head -1 ;ps aux |sort -rn +3 |head -10
(3)按顺序显示系统中受罚的进程:
#ps -eakl |head -1 ;ps -eakl |sort -rn +5
(4)按优先级顺序显示系统中的进程:
#ps -eakl |sort -n +6 |head
(5)按处理时间为顺序显示系统中的前十个进程:
#ps vx |head -1 ;ps vx |grep -v PID |sort -rn +3 |head –10
(6)按实际内存使用的多少顺序显示系统中的前十个进程:
#ps vx |head -1 ;ps vx |grep -v PID |sort -rn +6 |head –10
(7)按换入页面的多少顺序显示系统中的前10个进程:
#ps vx |head -1 ;ps vx |grep -v PID |sort -rn +4 |head -10
5、vmstat
vmstat命令报告关于核心线程,虚拟内存,自陷(trap),磁盘以及CPU行为的统计。而且每种行为报告都被更细致地用百分比分别表示用户态、核态、空闲以及等待磁盘I/O等情况。
内核维持了对核心线程,换页以及中断行为的统计数据,而vmstat命令则通过使用knlist子程序和/dev/kmen伪设备驱动器访问这些数据。磁盘的输入/输出统计是通过设备驱动器维持的。对于磁盘,平均传输速度是通过使用活跃时间核传输信息数目决定的。而活跃时间百分比则是从报告期间驱动器忙的时间量计算出来的。
vmstat命令产生五种类型的报告:
· 虚存行为报告
· fork子进程情况报告
· 每个设备产生的中断情况报告
· 汇总报告
· 输入/输出行为报告
6、sar
sar命令报告CPU的使用情况,I/O以及其它系统行为。sar命令可以收集,报告以及保存系统行为信息。如果没有指定输入文件,则sar调用sarc命令访问系统数据。
用户可用让cron命令运行两个shell脚本(/usr/lib/sa/sa1和/usr/lib/sa2)以提供日统计和报表。在crontab文件 /var/spool/cron/crontabs/adm中包括了一些样本节,用于示范cron要在何时运行这些shell脚本。以这种方式收集到的数据对于确定系统的时间周期特征和决定峰值使用时间是有用的。
但要注意的是,sar命令自己运行时会产生相当数量的读写。因此最好在没有工作量的情况下运行sar统计,看看sar对总的统计数字有多大的影响。
7、topas
topas命令用于监控各种系统资源,如CPU的使用情况,CPU事件和队列,内存和换页空间的使用,磁盘性能,网络性能以及NFS统计等。它还会报告指派给不同WLM类的进程对系统资源的消耗情况。它还能报告系统中最热门的进程和工作量管理器(WLM)的热门类。有关WLM类信息只有在WLM激活时才会显示。topas命令将热门进程定义为那些使用大量CPU时间的进程。topas命令没有作日志的选项,所有信息都是实时的。
topas命令利用System Performance Measurement Interface(SPMI)API获得有关信息。正是因为通过SPMI API,使系统开销保持在最小程度。topas命令使用perfstat库调用访问perfstat内核扩展。
8、truss
truss命令跟踪一个进程的系统调用、所接收的信号以及招致的机器错。要检查的应用程序可在truss命令的命令行中指定,也可将truss命令挂在一个或多个已经在运行的进程上。
AIX调制工具
1、fdpr
fdpr命令改进用户级程序和库的执行时间和对实际内存的使用。fdr命令可以通过不同的操作,如删除不必要的指令和重组代码和数据,而实现这样的目标。fdr命令安装在目录/usr/bin下。
fdpr命令在三个不同阶段上,对原有的执行代码应用先进的优化技术从而为其构筑一个优化的可执行代码。这三个阶段分别是:
· 在阶段1,fdpr创建一个增加了某些装置(instrumented)的可执行程序。原有的可执行程序被保存为__ProgramFile.save,而新版本被命名为__ProgramFile.instr。
· 在阶段2,fdpr运行该增加了某些装置的可执行程序,并收集摘要(profiling)数据。该摘要数据被保存在一个叫__ProgramFile.prof的文件中。运行执行程序时需要为它提供典型的输入数据,以使fdpr命令能够找出代码中可优化的部分。
· 在阶段3,fdpr命令使用阶段2中收集到的重要信息对可执行代码重新排序。这些重新排序涉及到这样一些任务:
(1)将那些高频度执行代码序列包装在一起。
(2)对条件分之重新排序,以改进硬件对分之条件的预测。
(3)将较少使用的代码部分移出来。
(4)内嵌一些热门函数。
(5)从重排序后的代码中删除掉NOP(空操作)指令。
另外,编译器中还提供了一个-qfdpr标志,用它可使编译器在执行代码中增加一些额外的信息,以辅助fdpr对该执行代码重新排序。但是,如果使用这个-qfdpr标志,则fdpr也只对那些用-qfdpr标志编译的模块重新排序。
2、schedtune
schedtune命令可以给抖动、进程挂起、时间片以及线程在锁上所能轮询的时间长度等设置准则。
用schedtune,可调整AIX中所设立的一组影响其内存负载控制机制的参数。Schedtune命令用于显示和修改那些用于检测系统内存是否在过度使用以致造成抖动的参数。Schedtune命令还能用于修改运行在系统上的进程的惩罚和衰减因子。在root用户下,用schedtune命令可做下面的事情:
· 决定用于确定抖动的准则。
· 决定哪个准则用于挂起进程。
· 决定在抖动终止后要等待多长时间才重新激活那些先前被挂起的进程。
· 决定被挂起的进程的最小数目。
· 调制调度优先级公式。
· 更改时间片数值。
· 决定在一把锁上轮询多长时间。
· 将schedtune值复位到它的缺省值。
需要注意的是,所有用schedtune作的修改在系统重启后都将丢失。为了确保所需的schedtune值在引导时能够置上,可在 /etc/inittab文件中插入适当的schedtune命令。如:schedt:2:once: /usr/samples/kernel/schedtune -s 65536
3、vmtune
vmtune命令负责显示和调整虚存管理器(VMM)和其它AIX部件使用的参数。系统中的根用户可动态修改包括下面这些参数:
· VMM页替换
· 永久文件读写
· 文件系统缓冲区结构(bufstructs)
· LVM缓冲区
· 裸输入/输出
· 换页空间参数
· 页删除
· 内存固定参数
13 04, 2005
AIX系统日常管理[转贴]
作者 xzh2000 19:30 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
1. 文件系统是否满
方法: df –k 可以以K为单位检查文件系统的使用率。(90%以上,需要调整)
2. 检查系统出错日志 使用errpt |more来检查
清除现有的log: Errclear 0
3. 检查系统合法/非法登陆情况
使用Last命令来检查来自登陆的地方。
4. 检查系统是否有巨大的Core文件生成
使用 find / -name core –print来检查。对Core文件,一般直接删除就可以了。
5. 系统性能检查:
a) CPU性能:使用Vmstat, topas来检查
b) 内存使用情况:也是使用topas, vmstat来检查
c) 检查IO平衡使用情况:使用iostat来检查
d) 交换空间使用情况:使用lsps –a来检查
6. Mail检查
7. Diag 一个月一次
13 04, 2005
你敢用rhel4(2.6内核)吗?
作者 xzh2000 12:32 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

英特尔员工肯尼思·陈在公布Linux 2.6内核的不同版本的性能数据时引发了这一问题。

根据肯尼思·陈的测试数据,2.6.11、2.6.9、2.6.8和2.6.2版内核的性能分别比基于

Linux 2.4兼部分Linux 2.6功能Red Hat Enterprise Linux 3下降13%6%23%1%。


12 04, 2005
Stream Monitor Program
作者 xzh2000 10:02 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Streams Monitoring Program
Purpose
STRMMON is a monitoring tool focused on Oracle Streams.  Using this tool,
database administrators get a quick overview of the Streams activity occurring
within a database. The output format comes in two formats:  default and long. 
The default format reports the rate of activity occuring for Streams processes.  
The long format provides the detailed information that was available in previous
releases of STRMMON.  The reporting interval and number of iterations to 
display are configurable. 
 

STRMMON can also be used to report Streams activity on  two databases 
at a time within the same strmmon session. 
 

In releases 9i and 10G Release 1, STRMMON is not a supported tool by 
Oracle, as of Oracle 10g Release 2, STRMMON is distributed as in the demo
directory of the database distribution code.
Contents
Installation
Usage
Parameters
Output
LOG
CPxx
MEM%
Qx
PRxx
Apxx
Flow Control
Potential Bottleneck
Instance
Known Problems
Compilation/Liking errors while running make command
Execution errors while running strmmon utility
Related Documents
Installation
STRMMON is delivered as a tar file that includes an OCI program and make file.
Click here to download the STRMMON zip file. Change directory to a new
directory.  If necessary transfer the tar file in BINARY mode. Extract the files from
the tar file using the command   
 
    tar -xf strmmon.tar .
 

Before compiling and linking the strmmon program, make sure that the
ORACLE_HOME and LD_LIBRARY_PATH environmental variables are set up
appropriately.  To compile and link, use the command:
 
      make -f strmmon.mk strmmon
 
After the program has been compiled and linked, strmmon can be used for
monitoring a Streams environment.
Usage
There are 7 command line input parameters for STRMMON:  interval, count, user,
passwd, dbname, sysdba and long. The first 2 parameters (interval and count) control
the sampling rate and the amount of output.  The next 4 parameters specify the connect 
information to the particular Streams database. Use multiple occurrences of these 4 
parameters to monitor multiple databases within the same strmmon command.  
Specifying the last parameter (long) displays more detailed information about each process.
 
When the command strmmon is issued without any parameters, a usage message is
displayed:
 
    % strmmon
 
Usage: strmmon -interval -count [-user ]
               [-passwd ] [-dbname ] [-sysdba]
Parameters
Parameter Name
 Value Units
 Description
 
-interval seconds The interval at which STRMMON will monitor the database. 
To specify that the sampling rate to be every 3 seconds:

 -interval 3

 This is a required parameter for strmmon.
 
-count Number The number of iterations to monitor the Streams environment. 
To specify 5 iterations, use the following:  -count 5

This is a required parameter for strmmon.
 
-user Username The schema name for logging into the database. 
Any schema name can be specified.  If  the SYS schema is specified,
additional information is displayed.  To specify the SYSTEM schema,  use

  -user SYSTEM

This parameter should not be specified if logging in as / as sysdba is desired.

-user  is an optional parameter for strmmon.
 
-passwd password The login password for the schema identified with the -user clause. 
To specify the password for the SYSTEM schema, use

  -passwd  oracle

This parameter should not be specified if logging in as / as sysdba is desired

-passwd is an optional parameter for strmmon.
 
-dbname service name The connection information or service name from tnsnames.ora
for the specific database to be monitored.
To specify the connect information for the monitored database, use

  -dbname ORCL.WORLD

This is an optional parameter for strmmon.
 
-sysdba  This flag indicates that the login role is SYSDBA. 
This optional parameter is typically used with the SYS schema. 

When logging in as / as sysdba,  the -user and -passwd parameters are not required
 
-long  This flag indicates that the more detailed report is desired. 
This is an  optional parameter for STRMMON. 
By default, only the capture, apply and propagation rates are
displayed. 

  STRMMON have to be used with the Oracle release used for compilation or linking
although it can connect to a different release database by using -dbname parameter.
Output 
The strmmon output begins with a banner line identifying the program parameters
and database.  This information is followed with a brief description of the major
components of the output display.  
After this initial  information about the program, Strmmon produces a single
line of output representing the current status of Oracle Streams after the
requested interval for each iteration . For example, if strmmon is invoked with
'-interval 3 -count 5' ,  a line of output will be displayed every 3 seconds. 
After 5 lines have been displayed (15 seconds), the monitoring will end. .
 
Each line is composed of multiple blocks of information dependent on the
streams processes configured within the database.   These blocks are displayed
by a keyword to identify the component followed by the statistics for that
particular component.  The separator between the components is the '|' symbol. 
 
There are 5 components for Streams:  LOG, CPxx, Qx, PRxx, APxx.   Except
for the LOG component, multiple occurrences each component are possible
dependent on the streams processes configured at database. 
 
An example of this identifying output is shown below:
 
  % strmmon -interval 3 -count 5 -sysdba
 
STREAMS Monitor, v 2.0  Copyright Oracle Corp. 2002, 2003.
Interval = 3, Count=5 Logon= @ ORACLE 9.2.0.6.0
Streams Pool Size = 52M
LOG :
CPxx: t;lcrs enqueued per sec>
Qx :
PRxx:
APxx:
: flow control in effect
: potential bottleneck
xx->: database instance name

To connect to multiple databases, the following command can be issued.  inst1
and inst2 are the network service names (tnsnames.ora) for each database.  
An example of the identifying output  for the long  report is shown below 
  % strmmon -interval 1 -count 1 -user sys -passw change_on_install
      -dbname inst1 -user sys -passw change_on_install -dbname inst2
      -sysdba  -long
 
STREAMS Monitor, v 2.0 Copyright Oracle Corp. 2002, 2004.
Interval = 1, Count=1

Logon=sys@inst1 ORACLE 10.2.0.0.0

Streams Pool Size = 52M

LOG :
CPxx:  
         
MEM%:
Qx : /
PRxx: /
APxx:
          
: flow control in effect
: potential bottleneck
xx->: database instance name

STREAMS Monitor, v 2.0 Copyright Oracle Corp. 2002, 2004.
Interval = 1, Count=1

Logon=sys@inst2 ORACLE 10.2.0.0.0

Streams Pool Size = 52M

LOG :
CPxx:  
          
MEM%:
Qx : /
PRxx: /
APxx:  
         
: flow control in effect
: potential bottleneck
xx->: database instance name
 || lnx1-> | LOG 321427 24919 | MEM% 0 || lnx2-> | LOG 284557 46592 | MEM% 0
   
Note: The information about the Streams Pool Size is displayed only
        for database versions greater than or equal to 10gR1.
LOG
Information about the redo log activity is written in this block.  The first statistic
following the LOG: keyword is the current SCN that has been written to the
redo log.  This number represents the current activity within the database.  If
this number does not increase, no activity is occurring on the database.  The
second statistic is the last block number written in the redo log.  Redo blocks
are always 512 bytes, so this statistic can be used to calculate the amount of
redo generated between intervals.   The output for the LOG component is
always the first entry after the timestamp on the display and appears as
follows:
 
2004-07-21 14:02:49 | LOG 13103675 50465
2004-07-21 14:02:52 | LOG 13103675 50465
2004-07-21 14:02:55 | LOG 13103679 50466
2004-07-21 14:02:58 | LOG 13103679 50466
2004-07-21 14:03:01 | LOG 13103679 50466
 
In the above example, the current scn that written to the redo log is 13103675 and the last
block number is 50465.  Since the strmmon command was issued with '-interval 3 
-count 5',  5 lines of output are displayed with a 3 second interval between them.  The 
activity on this database is very low, as seen by the fact that the current scn increases
infrequently (note change between 14:02:52 and 14:02:55). 
CPxx
For each capture process configured in the database, a separate block will be
displayed. In each block, the total number of messages captured from the redo
log and the most recent scn captured from the redo log are shown.  In addition,
the number messages that match the rules specified for the capture process 
including the most recent message scn enqueued are shown along with the
capture latency. 
 
Use the difference between successive capture 'messages captured' statistics 
to determine the rate at which capture is mining the redo log.  The enqueue scn
of capture is an indicator of where the capture process will restart, if capture is
stopped and restarted while the database is running  This statistic can also be
used for comparison with the Apply process high-water mark scn.  If these
statistics, the capture and apply are caught up and the data is synchronized.
MEM%
If strmmon is run from the SYS schema connected as SYSDBA, and the
database version is 10gR1 or higher, then this displays the percentage of
Streams Pool memory currently in use.
Qx
For each streams queue in the database, a separate block will display the
queue identifier as well as the number of outstanding messages in the
buffered queue, the cumulative number of messages that have been in the
queue and the number of messages spilled from memory to disk. In version
9iR2, the number of messages currently spilled is displayed. In 10gR1,
the cumulative number of messages spilled is displayed.
 
The queue identifier (QID) can be used to identify the name of the queue.
Use the QID in queries against the DBA_QUEUES view to identify the 
particular queue in the database. In 9i, the number of outstanding messages
in the buffered queue is only displayed if strmmon is run from the SYS
schema as SYSDBA. In 9iR2, if the number of spilled messages becomes
non-zero, consider stopping capture temporarily to slow down the flow
of data.
PRxx
For each propagation, the total number of messages and the total number
of bytes propagated to the destination site and the total time needed to
propagate those messages is displayed.
Apxx
For each apply process in the database, a block is displayed indicating
the statistics for each apply process. In addition to the total messages
dequeued and the most recent scn dequeued by the apply reader, the
dequeue latency, the total number of transactions received, assigned and
applied by the coordinator are displayed. The apply high water mark scn
along with the apply high water mark latency is also shown. This statistic
records the most recent scn from the source site that has been applied at
the destination site.
Flow control
This flag indicates that the capture process is blocked due to flow control.

Potential Bottleneck
This indicates that the capture or apply process is currently a potential

bottleneck

Instance
This indicates the name of the database instance for which the data follows

Known problems
 
Compilation/Linking errors while running make command
Error: sh: cc: not found
Cause : C compiler can not be found in the path.
Solution: Include the path to the C compiler in the PATH environmental variable.

Error:
strmmon.c:1114: parse error before "ub8"
strmmon.c:1114: warning: no semicolon at end of struct or union
strmmon.c:1115: warning: data definition has no type or storage class
strmmon.c: In function `print_prop_stats':
Cause : strmmon make use of ub8 definition, sometimes the expansion for this
definition has failed.
Solution: Include the definition of ub8 in the strmmon file, just before the definition
of prop struct. Definition of ub8 is as follows:
 
  #define ub8 unsigned long long
Execution errors while running strmmon utility
Error: Strmmon dump a core or raise a Memory fault
Cause : Compilation parameters are not the best for this platform
Solution : Use -user and -passwd parameters with user SYSTEM
 
Error: Error while loading shared libraries
Cause: LD_LIBRARY_PATH not defined
Solution : Define LD_LIBRARY_PATH
 
Error: OCIEnvCreate() failed
Cause : strmmon has been compiled/linked with a release different to the one that
is being used now.
Solution : Use the right ORACLE_HOME and use -dbname parameter to access a different
database release


12 04, 2005
9i Streams Recommended Configuration
作者 xzh2000 09:58 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

PURPOSE
-------

Oracle Streams enables the sharing of data and events in a data stream,
either within a database or from one database to another.
This article is intended to assist Replication DBAs in configuring Oracle
Streams Replication.

 
SCOPE & APPLICATION
-------------------

To be used by Oracle support analysts and replication DBAs to setup
replication using Streams in Oracle 9.2.x or higher.
Below, are some of the key recommendations for successful configuration
of Streams in the 9.2 release of the Oracle database.

 
INTRODUCTION
-------------
Oracle 9.2 has introduced a more flexible and efficient way of implementing
replication using Streams. In the contrary to what it happens on Advanced
Replication, there is no a Master Definition Site and all the sites plays
the same role.

Every database involved in the Streams replication is in charge of capturing
those changes involved in the replication and propagating them to the other/s
sites. Also every database is in charge of applying those entries coming from
other/s sites.

Then in a bidireccional database we will have 2 Streams, one from site A to
site B and the other from Site B to Site A.

In a nutshell, replication using Streams is implemented in the following way.

1) A background capture process is configured to capture changes made to
   tables,schemas, or the entire database. The capture process captures
   changes from the redo log and formats each captured change into a logical
   change record (LCR). 
   The capture process uses logminer to mine the redo/archive logs to
   format LCRs.   

2) The capture process enqueues LCR events into a queue that is specified.

3) This queue is scheduled to Propagate events from one queue to another in
   a target database.
 
4) A background apply process dequeues the events and applies them at the
   destination database.


Streams Configuration
=====================

The Configuration is divided into the following 4 sections:

Section 1 : Software Version 
Section 2 : Initialization Parameters Relevant to Streams
Section 3 : Database Storage
Section 4 : Database Privileges
Section 5 : Streams site types: Source Configuration
Section 6 : Streams site types: Target Configuration


Section 1: Software Version
===========================

Use the most recent patch set for Oracle 9.2, currently 9.2.0.6, available
from http://Metalink.oracle.com as Patch 3948480

Patch 3023858 is for Oracle Enterprise Manager, and should be applied to
the Oracle Management Server database as well as to any local systems that
will use the Oracle Enterprise Manager software. 


Section 2: Initialization Parameters Relevant To Streams
========================================================

At each participating Streams site, confirm that the following required
init.ora parameters are set appropriately for each database:
   
2.1  COMPATIBLE
     To use Streams, Compatible must be set to 9.2.0 or higher.

2.2  GLOBAL_NAMES
     This parameter must be set to TRUE at each database if you want to
     use Streams to share information between databases.  Streams uses
     the GLOBAL_NAME of the database to identify changes from or to a
     particular database.  Do NOT modify the GLOBAL NAME of a Streams
     database after it has been configured.  For example, the
     system-generated rules for capture, propagation, and apply typically
     specify the global name of the source database.  In addition, changes
     captured by the Streams capture process automatically include the
     current global name of the source database.  If the global name must
     be modified on the database, do it at a time when NO user changes
     are possible on the database so that the Streams configuration can be
     recreated. 

2.3  JOB_QUEUE_PROCESSES
     This parameter specifies the number of processes that can handle
     requests created by DBMS_JOB.  Ensure that it is set to 2 or higher.

2.4  AQ_TM_PROCESSES
     Setting the parameter to 1 or more starts the specified number of
     queue monitor processes.

2.5  LOGMNR_MAX_PERSISTENT_SESSIONS
     This parameter specifies the maximum number of persistent LOGMINER
     mining sessions. Streams Capture Process uses LOGMINER to mine the
     redo logs.  If there is a need to run multiple Streams capture
     processes on a single database, then this parameter needs to be
     set equal to or higher than the number of planned capture processes.
 
2.6  LOG_PARALLELISM
     This parameter must be set to 1 at each database that captures events.

2.7  PARALLEL_MAX_SERVERS
     Each capture process and apply process may use multiple parallel
     execution servers. The apply process by default needs two parallel
     servers.  So this parameter needs to set to at least 2 even for a
     single non-parallel apply process.  Specify a value for this parameter
     to ensure that there are enough parallel execution servers.

2.8  SHARED_POOL_SIZE
     Each capture process needs 10MB of shared pool space, by default
     Streams is limited to using a maximum of 10% of the shared pool.
     The 10% of the shared_pool_size is in reference to the size of the
     buffer queue before spillover occurs.
     Shared_pool_size must be significantly larger if Streams capture
     is implemented, especially if there is a large workload.
     The typical recommendation is to double the existing
     shared_pool_size and set the _first_spare_parameter to 50.  

2.9  OPEN_LINKS 
     Specifies the maximum number of concurrent open connections to remote
     databases in one session. Ensure that it is set to 4 or higher.

2.10 PROCESSES
     Make sure the value of this parameter allows for all background
     processes, such as locks, job queue processes, and parallel execution
     processes.  In Streams, capture processes and apply processes use
     background processes and parallel execution processes, and
     propagation jobs use job queue processes.
    
2.11 SESSIONS
     If you plan to run one or more capture processes or apply processes
     in a database, then you may need to increase the size of this
     parameter. Each background process in a database requires a session.

2.12 SGA_MAX_SIZE
     If you plan to run multiple capture processes on a single database,
     then you may need to increase the size of this parameter.
     Note :_SGA_SIZE should only be increased if a logminer error is returned
     indicating a need for more memory.  Any memory allocated to logminer
     is used solely by logminer - it is not returned to the shared_pool
     after it has been allocated by capture until the capture process
     is restarted.

2.13 TIMED_STATISTICS
     If you want to collect elapsed time statistics in the data dictionary
     views related to Streams, then set this parameter to true. The views
     that include elapsed time statistics include:
     V$STREAMS_CAPTURE, V$STREAMS_APPLY_COORDINATOR, V$STREAMS_APPLY_READER,
     V$STREAMS_APPLY_SERVER.

2.14 Only databases that are capturing changes via Streams capture must
     be in archivelog mode

At each participating Streams site, configure the init.ora for each
database to include the following hidden parameters:

2.1  _first_spare_parameter=50   
     The threshold (percent) of shared_pool_size memory at which spillover
     to disk is triggered for captured messages.

2.2  _kghdsidx_count=1  
     This parameter prevents the shared_pool from being divided among CPUs

2.3  _job_queue_interval=1  
     Scan rate interval (seconds) of job queue


Section 3: Database Storage
===========================

   1. Tablespace for Streams Administrator queues
      ===========================================

    As an option, it is possible to create a separate tablespace
    for  each  streams administrator schema (STRMADMIN) at each
    participating Streams database.This tablespace will be used
    for any objects created in the streams administrator
    schema, including any spillover of messages from the in-memory queue.

    CREATE TABLESPACE &streams_tbs_name DATAFILE 
    '&db_file_directory/&db_file_name' 
    SIZE 25 M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

    ALTER USER strmadmin DEFAULT TABLESPACE &streams_tbs_name
    QUOTA UNLIMITED ON &streams_tbs_name;


   2. Tablespace for Streams/logminer dictionary tables
      =================================================

    Create a separate tablespace for the Streams/logminer dictionary
    tables at each participating Streams database.  Use the SET_TABLESPACE
    procedure to relocate the Streams/logminer dictionary tables away
    from the SYSTEM tablespace.  This step must be performed at every
    participating Streams database, independent of whether it is a source
    or target site.

    CREATE TABLESPACE &tspace_name
    DATAFILE '&db_file_directory/&db_file_name' 
    SIZE 25 M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;

    EXECUTE DBMS_LOGMNR_D.SET_TABLESPACE('&tspace_name');


   3. Separate queues for capture and apply
      =====================================

    Configure separate queues  for changes that are captured locally and 
    for receiving captured changes from remote sites.  This is especially
    important when configuring bi-directional replication between multiple
    databases.

    Example:  To configure a site (SITEA) that is capturing changes for
    distribution to another site, as well as receiving changes from that
    other site (SITEB), configure 2 queues at SITEA as follows:

    dbms_streams_adm.set_up_queue(queue_name=>'CAP_SITEA')
    dbms_streams_adm.set_up_queue(queue_name=>'APP_FROM_SITEB');

    Subsequently, use the queue CAP_SITEA when configuring capture at
    SITEA, and APP_FROM_SITEB as the queue when configuring the apply
    from SITEB on SITEA.


Section 4: Database Privileges
==============================

Grant the following privileges to the Streams Administrator schema
(strmadmin) on each participating Streams database:

    GRANT EXECUTE ON DBMS_AQADM TO strmadmin;
    GRANT EXECUTE ON DBMS_APPLY_ADM TO strmadmin;
    GRANT EXECUTE ON DBMS_CAPTURE_ADM TO strmadmin;
    GRANT EXECUTE ON DBMS_PROPAGATION_ADM TO strmadmin;
    GRANT EXECUTE ON DBMS_STREAMS TO strmadmin;
    GRANT EXECUTE ON DBMS_STREAMS_ADM TO strmadmin;

    BEGIN
    DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
    privilege => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ,
    grantee => 'strmadmin',
    grant_option => FALSE); END;
/

BEGIN
DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
privilege => DBMS_RULE_ADM.CREATE_RULE_OBJ,
grantee => 'strmadmin',
grant_option => FALSE);
END;
/

Section 5: Streams site types: Source Configuration
===================================================

 1. Supplemental logging
    ====================
    Move LogMiner tables from SYSTEM tablespace:
    Configure supplemental logging at each source site
    All target site indexed columns, including the primary key, unique
    index, and foreign key columns of a  table or database must be
    unconditionally logged at the source site.
 
    Any columns specified in rule-based transformations or used within
    DML Handlers at target site must be unconditionally logged at the
    source site.
 
    Supplemental logging can be specified at the source either at the
    database level or for the individual replicated table.

 2. Implement flow control
    ======================
    When the threshold for memory of the buffer queue is exceeded,
    Streams will write the messages to disk.  This is sometimes
    referred to as "spillover".  When spillover occurs, Streams can
    no longer take advantage of the in-memory queue optimization. 
    One technique to minimize this spillover is to implement a form
    of flow control.  See Metalink Note 259609.1 for the scripts
    and pre-requisites. 
   
 3. Implement a Heartbeat Table
    ===========================
    To ensure that the applied_scn of the DBA_CAPTURE view is updated
    periodically, implement a "heart beat" table.  A "heart beat"
    table is especially useful for databases that have a low activity
    rate.  The streams capture process requests a checkpoint after
    every 10Mb of generated redo.  During the checkpoint, the metadata
    for streams is maintained if there are active transactions. 
    Implementing a heartbeat table ensures that there are open
    transactions occurring regularly within the source database enabling
    additional opportunities for the  metadata to be updated frequently. 
    Additionally, the heartbeat table provides quick feedback to the
    database administrator as to the health of the streams replication. 
    To implement a heartbeat table:
    Create  a table at the source site that includes a date or
    timestamp column and the global name of the database. 
    Add a rule to capture changes to this table and propagate the
    changes to each target destination.
    Make sure that the target destination will apply changes to this
    table as well.
    Set up an automated job (dbms_job) to update this table at the
    source site periodically, for example every minute.
   
 4. Checkpoint periodically
    =======================
    Periodically force  capture to checkpoint.  This checkpoint is not
    the same as a  database checkpoint. To force capture to checkpoint,
    use the capture parameter _CHECKPOINT_FORCE and set the value to YES. 
    Forcing a checkpoint ensure that the DBA_CAPTURE view columns
    CAPTURED_SCN and APPLIED_SCN are maintained.

 5. Capture Process Configuration
    =============================

     A.  Rules

     Use the DBMS_STREAMS_ADM.ADD_*_RULES  procedures (ADD_TABLE_RULES,
     ADD_SCHEMA_RULES for DML and DDL, ADD_GLOBAL_RULES for DDL only). 
     These procedures minimize the number of steps required to configure
     Streams processes. 
     Also, it is possible to create rules for non-existent objects, so be
     sure to check the spelling of each object specified in a rule carefully. 
     CAPTURE requires a rule set with rules.The ADD_GLOBAL_RULES procedure
     cannot be used to capture DML changes for entire database.
     ADD_GLOBAL_RULES can be used to capture all DDL changes for the database.

     A single Streams capture can process rules for multiple tables or
     schemas.  For best performance, rules should be simple. 
     Rules that include NOT or LIKE clauses are not simple and will
     impact the performance of Streams. 

     Minimize the number of rules added into the process rule set. 
     A good rule of thumb is to keep the number of rules in the rule set
     to less than 100.  If more objects need to be included in the ruleset,
     consider constructing rules using the IN clause. For example, a rule
     for the 6 TB_M21* tables in the MYACCT schema would look like the
     following:
     (:dml.get_object_owner() = 'MYACCT' and :dml.is_null_tag() = 'Y' and
     :dml.get_object_name() IN ('TB_M21_1','TB_M21_2','TB_M21_3',
     'TB_M21_40','TB_M21_10','TB_M211B010'))
   
     B.  Parameters
   
     Set the following parameters after a capture process is created:

     PARALLELISM=3
     Ensure that the appropriate supplemental logging has been configured
     at the source database before setting this parallelism parameter.

     _CHECKPOINT_FREQUENCY=1
     Increase the frequency of logminer checkpoints especially in a
     database with significant LOB or DDL activity.  A logminer checkpoint
     is requested by default every 10Mb of redo mined.

     _SGA_SIZE
     Amount of  memory available from the shared pool for logminer
     processing.  The default amount of shared_pool memory allocated
     to logminer is 10Mb.  Increase this value especially in environments
     where large LOBs are processed.
 
     Capture parameters can be set using the SET_PARAMETER procedure
     from the DBMS_CAPTURE_ADM package.  For example, to set the checkpoint
     frequency of the streams capture process named CAPTURE_EX, use the
     following syntax while logged in as the Streams Administrator:
 
     execute dbms_capture_adm.set_parameter('capture_ex','_checkpoint_frequency','1');
   
 6. Propagation Configuration
    =========================

    A.  Rules

    Use the ADD_*__PROPAGATION_RULES  procedures (ADD_TABLE_PROPAGATION_RULES,
    ADD_SCHEMA__PROPAGATION_RULES, ADD_GLOBAL_PROPAGATION_RULES for both DML
    and DDL.  These procedures minimize the number of steps required to
    configure Streams processes. Also, it is possible to create rules for
    non-existent objects, so be sure to check the spelling of each object
    specified in a rule carefully.  The rules in the rule set for propagation
    can differ from the rules specified for the capture process.  For example,
    to configure that all captured changes be propagated to a target site, a
    single  ADD_GLOBAL_PROPAGATION_RULES procedure can be specified for the
    propagation even though multiple ADD_TABLE_RULES were configured for the
    capture process.


    B.  Parameters
   
    LATENCY=5
    Maximum wait, in seconds, in the propagation window for a message to be
    propagated after it is enqueued.  For example, if the latency is 60 seconds,
    then during the propagation window, if there are no messages to be
    propagated,then messages from that queue for the destination will not be
    propagated for at least 60 more seconds.  It will be at least 60 seconds
    before the queue will be checked again for messages to be propagated for
    the specified destination. If the latency is 600, then the queue will not
    be checked for 10 minutes and if the latency is 0, then a job queue process
    will be waiting for messages to be enqueued for the destination and as
    soon as a message is enqueued it will be propagated.
   
    Propagation parameters can be set using the ALTER_PROPAGATION_SCHEDULE
    procedure from the DBMS_AQADM package.  For example, to set the latency
    parameter of the streams propagation from the STREAMS_QUEUE owned by
    STRMADMIN to the target database whose global_name is DEST_DB, use the
    following syntax while logged in as the Streams Administrator:
    
    dbms_aqadm.alter_propagation_schedule('strmadmin.streams_queue',
    'DEST_DB',latency=>5);


Section 6: Streams site types: Target Configuration
===================================================

The following recommendations apply to target databases, ie, databases
in which Streams apply is configured.

   1. Grant the necessary privileges to the Streams Administrator.

   2. Apply Process Configuration

   A.  Rules

   Use the ADD_*_RULES  procedures (ADD_TABLE_RULES , ADD_SCHEMA_RULES ,
   ADD_GLOBAL_RULES (for DML and DDL), ADD_SUBSET_RULES (DML only). 
   These procedures minimize the number of steps required to configure
   Streams processes. Also, it is possible to create rules for non-existent
   objects, so be sure to check the spelling of each object specified in
   a rule carefully.

   APPLY can be configured with or without a ruleset.  The ADD_GLOBAL_RULES
   can be used to apply all changes in the queue for the database.

   A single Streams apply can process rules for multiple tables or schemas
   located in a single queue that are received from a single source database.
   For best performance, rules should be simple.  Rules that include NOT or
   LIKE clauses are not simple and will impact the performance of Streams. 
 
   Minimize the number of rules added into the process rule set. 
   A good rule of thumb is to keep the number of rules in the rule set to
   less than 100.  If more objects need to be included in the ruleset,
   consider constructing rules using the IN clause.  For example, a rule
   for the 6 TB_M21* tables in the MYACCT schema would look like the
   following
   (:dml.get_object_owner() = 'MYACCT' and :dml.is_null_tag() = 'Y'
   and :dml.get_object_name() IN ('TB_M21_1','TB_M21_2','TB_M21_3',
   'TB_M21_40','TB_M21_10','TB_M211B010'))  


   B.  Parameters

   Set the following parameters after a apply process is created:
 
   DISABLE_ON_ERROR=N

   If Y, then the apply process is disabled on the first unresolved error,
   even if the error is not fatal.  If N, then the apply process continues
   regardless of unresolved errors.

   PARALLELISM=3 * Number of CPU  

   Apply parameters can be set using the SET_PARAMETER procedure from the
   DBMS_APPLY_ADM package.  For example, to set the DISABLE_ON_ERROR
   parameter of the streams apply process named APPLY_EX, use the following
   syntax while logged in as the Streams Administrator:

   execute dbms_apply_adm.set_parameter('apply_ex','disable_on_error','n');  
   

The initial setup/configuration is now ready.
 

RELATED DOCUMENTS
-----------------
Oracle9i Streams Release 2 (9.2)
Note 298877.1 10g Streams Recommended Configuration
Note 259609.1 Script to Prevent Excessive Spill of Message From
                 the Streams Buffer Queue To Disk
Note 224255.1 Steps To Setup Replication Using Oracle Streams
Note 301431.1 How To Setup Schema Level Streams Replication
Note 273674.1 Streams Configuration Report and Health Check Script
Note 290605.1 Oracle Streams STRMMON Monitoring Utility
Note 238455.1 Streams Supported and Unsupported Datatypes
Note 265201.1 Troubleshooting Streams Error ORA-1403 No Data Found


11 04, 2005
判断远程归档是否到备用机
作者 xzh2000 19:43 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

想了一个笨方法来监控主用机的alter_sid.log文件.

$more alert_tbdb2in1.log|grep "Creating archive destination"

Creating archive destination LOG_ARCHIVE_DEST_2: 'db213'
Creating archive destination LOG_ARCHIVE_DEST_1: '/opt/oracle/archive/tbdb2/1_20146.dbf'
Creating archive destination LOG_ARCHIVE_DEST_2: 'db213'
Creating archive destination LOG_ARCHIVE_DEST_1: '/opt/oracle/archive/tbdb2/1_20147.dbf'
Creating archive destination LOG_ARCHIVE_DEST_2: 'db213'
Creating archive destination LOG_ARCHIVE_DEST_1: '/opt/oracle/archive/tbdb2/1_20148.dbf'
Creating archive destination LOG_ARCHIVE_DEST_1: '/opt/oracle/archive/tbdb2/1_20149.dbf'
Creating archive destination LOG_ARCHIVE_DEST_2: 'db213'
Creating archive destination LOG_ARCHIVE_DEST_2: 'db213'
Creating archive destination LOG_ARCHIVE_DEST_1: '/opt/oracle/archive/tbdb2/1_20150.dbf'

$more alert_tbdb2in1.log|grep "Creating archive destination"|wc -l

10

如果wc -l返回结果是双数就表示正确的,否则就是有问题,要发email或短信通知.

发现上面的方法太麻烦,想出一个简单的方法:
create or replace procedure up_check_remotearch
as
v_arch number(3);
begin
select count(*) into v_arch
from v$archived_log
where sequence# in (select max(sequence#) from v$archived_log);
if v_arch = 1 then
sys.dbms_system.ksdwrt(2,'ORA-99999 远程归档已经停止,请检查!');
else
sys.dbms_system.ksdwrt(2,'监控状态: 远程归档正常运行,请放心!');
end if;
end;

var job number;
exec dbms_job.submit(:job,'up_check_remotearch;',sysdate,'sysdate+5/1440');

这样只需要用shell监控ORA-99999这个自定义错误号却可.


10 04, 2005
星期六的悲惨遭遇
作者 xzh2000 17:29 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

星期六到公司,检查一下邮件,没有收到服务器的异常情况,然后就搜了一下租房信息,
打了几个电话,竟然有两个是中介,呜呜.......这时从旺旺上收到一些服务器报错信息,
看了一下,是关于dataguard的信息,然后查了一下,发现是有些归档在主库已经删除,
但备用库却需要.

晕,这种情况是比较麻烦的,轻则需要恢复已经删除的归档,重则需要重做dataguard,
然后仔细地检查了一下后台的警告日志,发现从4.9号晚上的7点钟左右远程归档莫名
其妙地停止了,而log_archive_log_dest_2设置也是正确的,然后打电话给七公与拖雷
看看是什么原因,远程归档停了竟然没有任何理由!

又仔细地检查了一下,还是没有发现远程归档停止的原因,就试着从备份集中恢复这部
分欠缺的日志(restore archivelog sequence between 20567 and 20625 thread 2;),
执行后发现只恢复了从586-625之间的归档,567-265之间的竟然是没法恢复啦,因为每晚
1点左右做全备,全备之前的归档已经删除.

看来只有重做归档啦,只是中间有两个问题比较奇怪:
1 为什么远程归档自动会停?
2 为什么备用机上的脚本没有检查出归档没有到达这种情况?

重做dataguard时,光拷贝数据文件就用了三个多小时,从4点多拷贝到7点半左右,拷贝完
毕之后,准备打开时,发现备用库已经被打开到mount状态啦,汗马上就出来,我拷贝数据文
件时明明数据库已经down下去啦;问了一下七公,得知在七点钟时会有个shell将数据库打
开发open read only状态.想想那时还没有拷贝完,如何才能打开呢?
看了一下参数文件,发现参数文件与我刚从主库拷贝过来的路径不同,然后把数据库当下
来,再重新打开一下,发现还是不对,还是要求567号归档,那个汗啊,不说啦,仔细地检查了
后台警告日志,终于发现控制文件中的路径与我拷贝过来的数据文件路径不对,错了,然后
重新定义了ln,再次打开就OK啦.

看来要熟悉一个新环境与改变自己的工作习惯真不是很容易的事.

所有的事情做完之后,又检查了一下各种需要的参数与现在的日志归档情况,确保没有问
题之后,就准备回去啦,该死的天,下了很大的雨,偏偏没有出租车,还好有人也在路口等车,
问了一下,发现我们住一个小区,他已经让他的朋友从丰谭路打开过来接他,就冒着生命危
险与他们一块回去啦.


09 04, 2005
AIX常见问题整理.2[转贴]
作者 xzh2000 19:41 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

前面已经提到过,我们是要用RedHat Package Manager(RPM)来管理应用,所以我们必须首先要安装RedHat Package Manager。
RedHat Package Manager从下面连接下载:
ftp://ftp.software.ibm.com/aix/freeSoftware/ aixtoolbox/INSTALLP/ppc/rpm.rte安装时,以root用户登录,运行installp -qacXgd rpm.rte rpm.rte安装过程会收集共享链接库的信息,将会持续几分钟。要耐心等候,不要中断。如果发生错误没有装完,那么在下次安装之前,记得要运行installp -C去清除上回不完全安装。(我在一台F50,4.3.3上共用时10min35sec.)

RedHat Package Manager安装完后,就可以安装其他 AIX Toolbox for Linux
基本使用和Linux上一样,详细使用及相关信息,可以到www.rpm.org上查看。
简单参数如下,

-i: install
-e: erase
-q: query
--help help

举例:要安装gcc 2.9,那么先到
http://www-1.ibm.com/servers/aix/products/aixos/linux/download.html
下载rpm包 gcc-2.9.aix43.010216-1.aix4.3.ppc.rpm
上传到机器后,运行rpm -ivh gcc-2.9.aix43.010216-1.aix4.3.ppc.rpm
其中参数v是要在安装过程中显示详细信息。
其中参数h是要在安装过程中显示安装进度。
一分钟过后,就已经可以享受gcc 2.9的强大功能了。
其余的就不用我赘述了,大家各自体会吧。

第四部分 对开发的建议

1。由于AIX是符合POSIX标准和UNIX98认证的,但Linux却没有通过认证,所以
我们要尽量在开发过程中使用标准的API,那么应用只要使用GCC,G++等编译器重新编译就可以在AIX中使用了。非常重要的是,检查哪些API是只被Linux支持,但却不被AIX支持,这样可以避免不必要的麻烦。

2。由于AIX 5L是同时支持 Power系列 CPU和 Itanium CPU, 所以我们在开发程序,另外要注意的是在处理一些和硬件底层打交道的代码。在这些程序中我们需要采用通用的字节处理调用来处理,以保证应用可以很快速在不同的平台间移植,比如从Power系列的CPU平台移植到以INTEL CPU的平台,这样就可以确保应用的更强的可用性。

3。如果你的应用与路径有关,而在AIX系统中没有程序中指定的路径存在,那么必须修改应用的源码并指向正确的路径。所以建议你在开发是确认你的代码是否是可行的并进行相应的测试。

IBM RS/6000 CPU 与IBM INFORMIX数据库CPU虚处理器的设置

环境 产品: IBM INFORMIX 7.x,9.x
平台: AIX
问题 目前在IBM RS/6000多数机型为对称多处理器结构, 而IBM INFORMIX数据库服务器的配置参数中有CPU VP(即CPU虚处理器)的设置, 那么在实际应用中如何对CPU与CPUVP进行设置以达到比较好的性能呢?
解答 CPU VP是多线索进程, 它一直在CPU上执行除非以下情况发生
1. 没有任务做, 例如就绪队列中没有等待执行的线索.
2. 操作系统强迫CPU VP让出CPU 给其它进程.

为优化吞吐量, 将NUMCPUVPS设置为能够处理承接任务的最小的数, 这个数目小于或等于系统中可利用的CPU数, 建议不要将CPU VP数设置成大于可用CPU数目. 通常对于OLTP应用: NUMCPUVPS=TOTAL CPUS-1 VP; 对于OLAP应用: NUMCPUVPS=TOTAL CPUS.

如果CPU VP不能承受要执行的任务, 这就表示需要提高CPU性能来解决问题. 只有存在另外的处理器, 才能通过增加CPU VP来解决问题. 也可以从系统上移走其它任务, 为虚处理器释放CPU周期, 从而改善性能.

增加CPU VP的数目而不增加CPU资源只会使问题更严重, 产生更多的CPU周期竞争, 这样操作系统要有更多的工作来做均衡, 争夺CPU时间的CPU VP使其负担增加. 结果, 上下文切换增加, 这不仅消耗时间而且要使用更多的CPU.

由于系统不光是CPU VP, 还有其它进程申请CPU周期, 在一些多处理器系统上, NUMCPUVPS应小于或等于全部CPU数. 当然, 我们应根据实际应用的状况, 在系统上进行试验和监测, 以检测吞吐量和CPU使用情况, 最终找到比较好的配置方案.

通过命令onstat ?g rea 来检测就绪队列, 确认CPU是否不能承担任务. 就绪队列的线索是将要执行的线索, 如果就绪队列线索数开始加速增长, 这就表示CPU VP已不能承接如此繁重的任务. 在调整好的系统上看到几个就绪线索, 或是在测试工作开始时有些线索增加是正常的. 每个CPU VP上有一个就绪线索是合理的.

另外, 查看CPU VP的使用情况, 如CPU VP跟不上任务的增长, 就会看到虚处理器处于饱和, 可以用onstat ?g glo监视虚处理器的使用情况. 如果系统和用户CPU VP时间之合接近于测试花费时间, 那么CPU VP就饱和了, 如果设置NUMCPUVPS低于系统中CPU数, 可以增加一个CPU VP, 但不要超出系统中的全部CPU数.

注意: 在多处理器系统中, 全部可利用CPU时间等于处理器数乘以测试时间, 一个CPU VP不能在某一时刻消耗多于一个处理器的能力, 因此一个CPU VP的全部CPU比率不会超过测试时间的100%.

如果整个系统中CPU资源已饱和, 而且不能再减轻工作负荷或增加资源, 可以通过减少NUMCPUVPS来改善性能. 但这种变化只有在CPU VP急需其它虚处理器或进程的CPU资源时才起作用.


09 04, 2005
AIX常见问题整理.1[转贴]
作者 xzh2000 19:30 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

提纲:
用feprom_update升级Firmware 2002-07-24
CHRPSystems系统启动过程的LEDE1DC报错提示 2002-07-24
怎样在AIX5.1中建立热后备(hotspare)磁盘? 2002-07-24
如何让非root用户有权限执行sar命令 2002-07-24
使用errpt命令,产生0315-171错误 2002-07-24
普通用户执行su命令时产生错误:Authenticationdenied. 2002-07-24
查找文件或命令对应的文件集 2002-07-24
AIX5L新特性(一):如何确认CPU的主频? 2002-07-24
如何记录ftplog? 2002-07-24
目前哪些RS/6000支持逻辑分区(LPAR)? 2002-07-11
在移植安装(Migrationinstallation)中都有那些文件和数据保留下来? 2002-07-11
如何在保留安装(Preservationinstallation)方式下自定义需要保留的文件? 2002-07-11
PTF与APAR的区别? 2002-07-11
将man命令查看的内容转换成普通文本文件 2002-07-11
查看bootlog 2002-07-11
inetd.conf文件的恢复 2002-07-11
如何立刻断掉一个已经login的用户? 2002-07-11
使用errdemon客户化系统错误日志文件 2002-07-11
什么版本的Oracle数据库支持AIX5.1 2002-07-11
IBMpSeries和RS/6000哪些型号可以安装SuSElinux? 2002-07-11
如何监控裸设备I/O? 2002-07-11
在AIX上安装RPM格式软件包 2002-07-11
gated 进程介绍和应用 2002-03-25
如何处理 mountd 和 nfsd 无法正常启动 2002-03-25
如何在图形登录和命令行登录方式见切换? 2002-01-29
如何阻止某些用户远程登录,telnet,rlogin? 2002-01-29
如何拒绝某些用户的ftp访问? 2002-01-29
如何查看某用户共启动了多少进程? 2002-01-29
如何在清理/tmp文件系统时找到过大的文件? 2002-01-29
如何限制某用户在特定 pty 的访问。 2002-01-28
如何打开锁死的帐户 2002-01-28
如何下载RS/6000相关的补丁(Fix,PTF),维护包及微码(Microcode) 2002-01-03
如果想将linux应用移植到pSeries和RS/6000上,哪里有参考资源? 2002-01-03
Aix 4.3上支持超过2GB的文件吗? 2002-01-03
IBM INFORMIX数据库级备份都备份了哪些内容? 2001-12-31
在RS6000系列机器上如何配置IBM INFORMIX数据库临时数据库空间? 2001-12-31
如何改变主机IP地址解析顺序 2001-12-30
AIX无线系统管理器 2001-12-30
不能增加用户,错误信息为3004-687 2001-12-20
如何改变上传ftp文件的缺省读写属性? 2001-12-19
AIX中的 rmss 命令的用途 2001-12-19
在AIX 4.x如何清除挂起的tty 2001-12-18
在AIX中扩展卡的逻辑名和它所在插槽的对应关系 2001-12-14
如何对系统做镜像以提高系统高可用性和性能 2001-12-11
Debug mode 引导AIX 2001-12-10
kdb command 2001-12-10
在AIX中如何为一块网卡,配多个IP地址? 2001-12-03
AIX内核参数调整之vmtune -p -P(2)? 2001-11-30
AIX内核参数调整之vmtune -f -F(3)? 2001-11-30
Linux 与 Pseries/RS6000 2001-11-30
AIX内核参数调整之vmtune -M(5)? 2001-11-30
AIX内核参数调整之vmtune -r -R(4)? 2001-11-30
如何在命令行下运行update_all? 2001-11-29
如何确定一文件系统是Large File Enabled的文件系统? 2001-11-29
手工删除smit菜单 2001-11-29
6230 SSA卡上快写缓存的设置? 2001-11-29
支持Xwindows最少需要安装那些文件集(Fileset)? 2001-11-29
如何改动IP地址 2001-11-27
启动sendmail 2001-11-27
如何显示格林威治时间 2001-11-27
看SSA逻辑盘与物理盘之间对应关系 2001-11-27
登录失败次数过多 2001-11-27
用户名长度问题 2001-11-27
如何判断引起core文件的应用程序 2001-11-27
inittab中引用的环境变量 2001-11-27
解锁卷组 2001-11-27
在一个磁带上备份多个文件 2001-11-27
夏时制问题 2001-11-27
passwd文件的备份 2001-11-27
如何限制某个用户使用FTP服务 2001-11-27
在AIX系统中,如何得到一些偏僻的汉字 2001-11-27
AIX 是否支持 ramdisk 2001-11-15
什么是 inline log 2001-11-15
什么是X-window 2001-09-29
如何增加文件系统中的inode数目 2001-09-28
如何为调试应用程序性能 定制系统内存环境 2001-09-28
关于AIX 4.3.3的内核问题。 2001-09-28
如何在AIX上实现象doskey一样的功能 2001-09-28
如何修改终端的属性以适应特殊需要 2001-09-28
另一种让vi编辑超大文本文件的方法 2001-09-28
如何利用grep的一些高级选项更好地管理系统 2001-09-28
IBM RS/6000 CPU 与IBM INFORMIX数据库CPU虚处理器的设置 2001-08-28
AIX 与 LINUX 的结盟 2001-08-17
哪里可以下载AIX上的JDK? 2001-08-02
如何在 AIX 中设置 tftp server 2001-07-31
为什么用CD-ROM有时不能引导AIX 5L 2001-07-16
AIX 5L 5.1中的64位内核 2001-07-12
怎样在AIX 5L 5.1中进行64位和32位内核的切换? 2001-07-12
何谓EtherChannel?在AIX 5L中,它有何增强? 2001-07-12
JFS2 与 JFS的比较 2001-07-11
AIX 5L V5.1介绍 2001-07-10
如何确定pSeries和RS/6000 CPU的主频? 2001-07-04
利用mksysb进行系统备份有什么好处 2001-07-01
如何平稳地停止AIX系统运行? 2001-07-01
如何解决AIX上不能增加新用户,错误讯息 3004-687 2001-07-01
/var/adm/wtmp档案太大怎么办 2001-07-01
在Korn Shell中要如何设定 prompt 才会显示出目前所在的目录? 2001-07-01
2001/06 AIX安全防范有关的补丁(APAR) 2001-06-26
当运行mksysb时,系统报错:“rootvg is locked”(根卷组被锁定) 2001-06-25
如何在Documentation Search Service中删除文档? 2001-06-25
CDE 不能启动解疑(一) 2001-06-25
只有root用户可以登录Xwindows,但普通用户不能登录, 如何处理? 2001-06-25
CDE 不能启动解疑(二) 2001-06-25
执行execd时出现错误0826-604 2001-06-12
如何配置AIX 5L 中的 Processor Entitlement 2001-06-12
AIX 5L 的特点 2001-06-12
怎样镜像rootvg 2001-06-08
AIX 5L v5.1在网络方面增加了那些新功能? 2001-06-08
什么是Dead Gateway Detection(DGD, 失效网关检测)? 2001-06-08
Virtual IP Address (VIPA)虚拟IP地址 2001-06-08
AIX支持的最大socket数 2001-06-08
建立第二个root用户 2001-06-05
如何查看系统的telnetd daemon已启动 2001-05-31
如何使用dd命令备份裸设备 2001-05-31
使用ls或mv *命令时, 产生"Arguments too long"或"Array list too long"的错误信息 2001-05-31
普通用户无法执行su命令 2001-05-31
Aix 版本号介绍 2001-05-31
在AIX4.3.3系统中,为什么oslevel命令的输出不是4.3.3.0 2001-05-31
如何查看CPU的时间片的大小 2001-05-30
恢复文件系统超级块 2001-05-30
tar备份链接文件 2001-05-30
在同网段内同步时间 2001-05-30
在RS6000上,当使用新的7210-025 DVD-RAM 来备份卷组时,可以跨多个CD写文件吗? 2001-05-29
运行iostat -d 命令系统返回警告提示" Disk history since boot not available. " 2001-05-23
设置以太网卡时选择全双工还是半双工? 2001-05-23
怎样确定当前系统是32位或64位? 2001-05-23
AIX Version 4.3 Bonus Pack - 2001年4月版 2001-05-23
AIX V4.3支持超过2GB大文件 2001-05-22
如何在AIX4.3.3中启动或停止dhcpcd 2001-05-22
编辑超大文本文件 2001-05-22
在根目录(/)下执行了rm *,如何恢复系统 2001-05-22
如何解决License Server 启动时的错误 GRL-2050: Fatal error from I4LLMD 2001-05-22
怎样创建固定大小的临时大文件 2001-05-22
smit.log 与 smit.script 文件 2001-05-21
如何减少文件系统中的碎块 2001-05-21
AIX中对软盘操作的DOS兼容命令 2001-05-21
查看系统启动信息(alog) 2001-05-21
如何查看多用户系统中其它终端的属性 2001-05-21
查看SSA磁盘中pdisk与hdisk的对应关系 2001-05-21
如何看机器内的卡及硬盘的微码级别(microcode level) 2001-05-21
如何在dtterm中使用PageUp/PageDown 上下翻页 2001-04-30
如何禁止动态路由 2001-04-30
无法删除文件系统 2001-04-30
如何限制某些用户无法ftp至RS/6000服务器 2001-04-30
如何增加文件系统的空间 2001-04-29
PCI 两口多协议卡(2-Port Multiprotocol PCI Adapter 9-L)的配置方法 2001-04-28
用户转换错误 2001-04-28
杀进程的shell程序 2001-04-25
怎样在AIX中Mount Redhat Linux上的nfs文件系统? 2001-04-25
如何限制用户改变密码 2001-04-24
AIX4.3 的维护包(Maintenance Level) 及推荐维护包(Recommended Maintenance) 2001-03-15
如何自动启动和关闭软件的运行 2001-01-18
光盘驱动器错误0514-062: 指定的设备忙. 2001-01-18
AIX4.3.2下安装显卡GXT130P 2001-01-15
/var/adm/wtmp文件太大 2001-01-15
显示设置启动引导顺序 2001-01-15
安装MAN 2001-01-15
改变主机IP地址解析顺序 2001-01-15
telnet提示"所有的网络端口已用" 2001-01-15
LED 223-229故障的解决 2001-01-05
LED 553故障的解决 2001-01-05
AIX版本号释疑 2001-01-05
/etc/preserve.list文件有什么用? 2001-01-05
LED 201故障的解决 2001-01-05
LED 551,555和557故障的解决 2001-01-05
LED 552,554和556故障的解决 2001-01-05
如何替换损坏的镜像卷组硬盘? 2001-01-05
RS/6000液晶显示屏上显示代码(LED)的含义 2001-01-02
不能增加新用户,错误信息 3004-687 2000-12-29
拨号访问RS/6000的快速配置方法 2000-12-29
解决 10/2000 和 11/2000版的 Update CDs引起的NFS及NIM 错误 2000-12-29
解决升级(Migration) 到 AIX 4.3.3时 可能会遇到的启动失败 2000-12-29
改变磁盘名顺序 2000-12-29
如何确定一个备份带的块大小(Block Size)和类型(Type)? 2000-12-29
如何创建/dev/null文件? 2000-12-28
Netscape Communicator无法正常启动 2000-12-28
如何查找系统中某个文件或命令所对应的文件集? 2000-12-28
从"卷组被锁定"的报错信息中恢复 2000-12-28
从LED C31中恢复 2000-12-28
查看操作系统中是否安装了某个补丁程序的简便方法 2000-12-28
.sh_history文件被破坏了怎么办? 2000-12-28
如何屏蔽某一用户的ftp访问? 2000-12-28
AIX的安装方法及其特点 2000-12-28
无单点故障的SSA卡及7133配置案例 2000-12-28
非root用户的登录问题 2000-12-28
怎样查看RS/6000的物理内存? 2000-12-27
关于2000年10、11月的UPDATE CD 中NFS和NIS的错误 2000-12-27
Communications Server无法启动 2000-12-27
如何在AIX 4.3中安装联机手册? 2000-12-27
何为AIX 5L 2000-12-27
AIX中如何解决不能释放光驱的问题 2000-12-27
使用ftp自动传输文件 2000-12-27
如何快速安装AIX补丁程序? 2000-12-27
如何监控AIX的单个file/lv/pv的繁忙程度? 2000-12-27
检查AIX上的病毒 2000-12-27
定制自己的AIX Login 画面 2000-12-27
系统停在 LED C33 2000-12-26
如何查看物理内存的大小 2000-12-12
使用命令行安装删除文件包 2000-12-12
远程客户可通过"login, ftp"登录, 但不可通过"telnet"登录 2000-12-12
AIX 的许可权限 2000-12-12
如何解决"device busy"问题 2000-12-12
IPCS Limitation(AIX 3.2.5 --- AIX 4.3.2) 2000-12-12
AIX 用户的系统资源使用限制 2000-12-12
AIX 4.3.3 监控系统活动的新命令--TOPAS 2000-12-05
在AIX中设置中文环境 2000-12-04
"Volume Group Locked" 恢复步骤 2000-11-30
如何在CDE中添加图标? 2000-11-28
如何创建 /dev/null 文件 2000-11-27
如何减小 /var/adm/wtmp 文件的大小? 2000-11-27
如何查找系统中的某个文件存在于哪个文件集中? 2000-11-27
怎样使用CDE环境? 2000-11-17
怎样保存当前的CDE环境 2000-11-17
如何使.profile文件在CDE中生效? 2000-11-17
怎样创建共享库? 2000-11-17
何谓COSE? 2000-11-16
进程kproc 2000-11-14
如何管理Paging Space 2000-11-14
异步I/O (aio) 2000-11-14
裸设备(Raw Device) 2000-11-14
在AIX4.3.3系统中,为什么oslevel命令的输出不是4.3.3.0? 2000-11-13
AIX 4.3.3 的中文输入 2000-11-13
libc.a 文件恢复 2000-11-13
何为AIX/Montery 2000-11-13
如何使用 IBM HTTP Server 支持AIX 联机文档? 2000-11-13
7133硬盘连接验证"good" 及"reserved" 2000-11-13
如何从 LED 553 恢复 2000-11-13
RAID 技术简介 2000-11-10
如何减小hd6页面空间 2000-11-09
在做RS/6000 AIX 订单配置时, 需要配置用户数么? 2000-08-04
如何下载 RS/6000 PTF(Fixes) 及 Firmware? 2000-06-13

FAQ:
怎样在AIX 5.1中建立热后备(hot spare)磁盘?
环境 AIX 5.1
问题 怎样在AIX 5.1中建立热后备(hot spare)磁盘?
解答 在AIX 5.1中可以在操作系统的级别上建立hot spare磁盘。
如需要在某一卷组(VG)中建立hot spare磁盘,必须满足如下条件:
1. 逻辑卷(LV)在此卷组中必须进行镜像(mirror)。
2. 作为hot spare的磁盘上不能有任何的逻辑卷或文件系统。
3. hot spare盘的容量应大于或等于此卷组中最大磁盘的容量。

当满足以上条件后,可采用以下步骤(此处假设卷组名为testvg,
磁盘为hdisk6):

1. # exptendvg testvg hdisk6
将hdisk6加入卷组testvg。

2. # chpv -hy hdisk6
将hdisk6标记为hot spare磁盘。

3. #chvg -hy -sy testvg
将testvg标记为使用hot spare盘的卷组,并且当发生磁盘失效
时自动进行磁盘的替换并同步。

用feprom_update升级 Firmware

环境 平台: RS/6000
问题 用feprom_update升级 Firmware
解答 在AIX 4.3,命令feprom_update会得到报错:
1734-009 cannot write in FEPROM

一旦得到此提示,表示firmware坏了,系统将无法启动。
此问题可能会在以604e为处理器的SMP系统上(也包括SP高结点)出现。在升级Firmware之前,应先检查APAR IX84560是否已装到系统中。
请从下面网址得到此补丁包:
http://techsupport.services.ibm.com/rs6k/fixes.html

CHRP Systems系统启动过程的LED E1DC 报错提示

环境 平台: RS/6000
版本: AIX 4.3
问题 CHRP Systems系统启动过程的LED E1DC 报错提示
解答 用比硬盘上安装的AIX版本还低的AIX 安装盘或诊断光盘启动CHRP结构的RS/6000机器,往往会遇到E1DC LED报错提示.

确定一个机器是否为CHRP结构,可用如下命令:
lslpp -L devices.chrp.base.rte

如果devices.chrp.base.rte文件包存在,则是CHRP结构;
如果没有此文件存在,此问题不会发生.
要防止此问题的办法是打补丁包:APAR IX79693.
它包含在AIX 4.3.2和4.3.2 diagnostics CD中(P/N 08L1427 or 08L1430)。
如果发生这个问题,唯一的方法是在系统下电后取下电池,10-15分钟后装回即可。

普通用户执行su命令时产生错误:Authentication denied.

环境 产品:AIX
平台:RS
软件版本:4.3
问题 当普通用户执行su命令su到root或其它普通用户时,产生错误:Authentication denied。
解答 使用命令 ls -l /usr/bin/su检查su文件的权限,正确的权限应为:-r-sr-xr-x root security ...
如果权限不正确,使用以下命令修改:
# cd /usr/bin
# chmod 4555 su

如何让非root用户有权限执行sar命令

环境 产品:AIX
平台:RS
软件版本:4.3
问题 如何让非root用户有权限执行sar命令
解答 可通过smit --> Security & Users --> Users --> Change/Show Characteristics of a User 修改用户的属性,将“adm”组加入该用户的Primary GROUP中即可。

使用errpt命令,产生0315-171错误

环境 产品:AIX
平台:RS
软件版本:4.3
问题 当使用命令errpt -a查看系统的错误报告时,产生错误:0315-171: 不能处理错误日志文件/var/adm/ras/errlog
解答 该错误的产生是由于/var/adm/ras/errlog文件被破坏导致的,可以用如下步骤删除现有文件,使系统自动生成一个新的/var/adm/ras/errlog文件:

1. /usr/lib/errstop
2. rm /var/adm/ras/errlog
3. /usr/lib/errdemon

如何记录ftp log?

环境 RS6000 & pSeries
AIX 4.3 和 AIX 5L
问题 如何记录ftp log?
解答 缺省情况下, 系统不会记录使用FTP连接和传输文件的日志(log). 这会对系统造成安全隐患,尤其在用户使用匿名ftp方式时。为了避免这种情况发生, 可用如下的步骤使系统记录FTP的日志:
1.修改/etc/syslog.conf文件,并加入一行:
daemon.info FileName
其中FileName是日志文件的名字, 它会跟踪FTP的活动,包括匿名和其他用户ID. FileName文件必须在做下一步骤前创建。

2.运行"refresh -s syslogd"命令刷新syslogd 后台程序。

3.修改/etc/inetd.conf文件,修改下面的数据行:
ftp stream tcp6 nowait root /usr/sbin/ftpd ftpd -l

4.运行“refresh -s inetd”命令刷新inetd后台程序。

查找文件或命令对应的文件集

环境 产品:AIX
平台:RS
软件版本:4.3
问题 查找文件或命令对应的文件集
解答 1. 确认系统中已安装了文件集:bos.content_list

2. 查找文件或命令所对应的文件集,使用命令:
# /usr/sbin/which_fileset
如:/usr/sbin/which_fileset iostat

3. 查看指定的文件集包含哪些文件,使用命令:
# lslpp -f
如:lslpp -f bos.acct

AIX 5L 新特性(一):如何确认CPU的主频?

环境 硬件平台:rs6000 & pSeries
操作系统:AIX 5L
问题 AIX 5L 新特性(一):如何确认CPU的主频?
解答 在AIX 5L中可以非常方便的确认CPU的主频,使用如下命令:
lsattr -El proc0
在命令输出的最后一行中"frequency"所指的值既为CPU的主频。
在AIX 4.3版本中无此功能。

目前哪些RS/6000支持逻辑分区(LPAR)?

环境 RS/6000 AIX 5L
问题 目前哪些RS/6000支持逻辑分区(LPAR)?
解答 支持逻辑分区的RS/6000型号:
P630(1,2,4-way CPU)
P670(4,8,16-way CPU)
P690(8,16,24,32-way CPU

PTF 与APAR的区别?

环境 产品: pSeries, RS6000
软件版本: AIX4.3 AIX 5L
问题 PTF 与APAR的区别?
解答 PTF是Program Temporary Fix的简称。 一个PTF是指一个升级的文件束(fileset)或着一个修正了以前操作系统问题的文件束。使用installp命令安装。

APAR是Authorized Program Analysis Report的简称。 一个APAR指的是一个特殊的或着紧急的fix、e-fix, 对操作系统而言是单一性的错误问题。APAR有可能经过测试和认证后成为PTT。 APAR使用instfix命令安装。

如何在保留安装(Preservation installation)方式下自定义需要保留的文件?

环境 产品: pSeries,RS6000
问题 如何在保留安装(Preservation installation)方式下自定义需要保留的文件?
解答 使用保留安装(Preservation installation)方式在安装了BOS时保留根(root)卷组的数据,但是/usr,/tmp 和/var及/(根)文件系统将被覆盖。因此在上面的文件系统下的数据将丢失。如果想保留这些文件系统,可以在/etc/preserve.list文件中加入想保留的文件系统。例如如果想保留/var下的文件,可以将/var目录加到/etc/preserve.list文件中。

查看boot log

环境 产品:AIX
平台:RS
软件版本:4.3
问题 如何查看系统上次启动的log?
解答 # alog -o -t boot

将man命令查看的内容转换成普通文本文件

环境 产品:AIX
平台:RS
软件版本:4.3
问题 如何将man命令查看的内容转换成普通文本文件,供打印或进一步查看?
解答 可使用下面的命令将用man查看的ls命令的内容转换为文本文件man.txt:
# man ls | col -b > man.txt

inetd.conf 文件的恢复

环境 产品:AIX
平台:RS
软件版本:4.3
问题 inetd.conf 文件的恢复
解答 有时由于某种原因, /ETC/INETD。CONF文件损坏。
会对机器带来TCP/IP方面问题: 如 FTP
可用以下步骤来恢复INETD。CONF 文件。

# vi /etc/inetd.conf
# stopsrc -s inetd
#mv /etc/inetd.conf /etc/inetd.conf.old
#cd /usr/lpp/bos.net/inst_root/etc
#cp inetd.conf /etc/inetd.conf
#startsrc -s inetd

如何立刻断掉一个已经login的用户?

环境 产品:AIX
平台:RS
软件版本:4.3
问题 如果想要立刻断掉一个已经login的用户,如何做
解答 可使用命令 fuser -k <用户的主目录>
如:fuser -k /home/guest

使用errdemon客户化系统错误日志文件

环境 产品: pSeries, RS/6000
软件版本: AIX 4.3, AIX 5L
问题 如何使用errdemon客户化系统错误日志文件?
解答 首先列出系统错误日志文件当前配置数据:

#/usr/lib/errdemon -l

Error Log Attributes
--------------------------------------------
Log File /var/adm/ras/errlog
Log Size 1048576 bytes
Memory Buffer Size 8192 bytes

如果希望改变系统错误日志文件的大小, 输入:

#/usr/lib/errdemon -s 2000000

如果希望改变系统错误日志文件buffer的大小, 输入:

#/usr/lib/errdemon -B 16384

什么版本的Oracle数据库支持AIX 5.1

环境 oracel, aix
问题 什么版本的Oracle数据库支持AIX 5.1
解答   AIX 4.3.3 AIX 5L
8.1.7 32-bit Yes Yes
  now (Production) now (Production)
     
8.1.7 64-bit Yes  
  now (Production)  
     
9.0.1 64-bit Yes Yes
  now (Production) now (Developer's Release)
     
9.2 64-bit Yes Yes
  now (Production) now (Production)

如何监控裸设备I/O?

环境 产品:pSeries,RS/6000
软件版本:AIX 4.3 AIX 5.1
问题 如何监控裸设备I/O?
解答 sar命令中的“-b”选项可以用于监控裸设备I/O。裸设备一般用于存放数据库数据。

# sar -b 1 3

AIX 6f1 3 4 00023A0F4C00 06/19/02

18:16:30 bread/s lread/s %rcache bwrit/s lwrit/s %wcache pread/s pwrit/s
18:16:31 0 0 0 0 0 0 0 0
18:16:32 0 0 0 0 0 0 0 0
18:16:33 0 0 0 0 0 0 0 0
                 
Average 0 0 0 0 0 0 0 0

其中bread/s 和bwrit/s显示了块裸设备(block raw device)I/O操作的数目。pread/s 和pwrit/s显示了字符裸设备(character raw device)I/O操作的数目

在AIX上安装RPM格式软件包

环境 AIX 4.3.3/5L
问题 在AIX上安装RPM格式软件包
解答 1.从Linux Application Toolbox CD安装Redhat Package Manager - rpm.rte

2.安装RPM格式软件
#rpm -ivh fileset_name

3.检查按装结果
#rpm -q fileset_name

gated 进程介绍和应用

内容
提要 我们知道在AIX操作系统中,gated 进程可以支持RIP, RIPng, EGP, BGP, OSPF等协议,甚至还支持SNMP协议。通常来讲,gated进程不能和routed进程同时使用,否则会导致不可预见的错误。
1.如何启动和停止gated
2.gated进程的工作模式
1) 配置 /etc/gated.conf 支持 RIP 协议
2)配置 /etc/gated.conf 支持 OSPF 协议

正文 我们知道在AIX操作系统中,gated 进程可以支持RIP, RIPng, EGP, BGP, OSPF等协议,甚至还支持SNMP协议。通常来讲,gated进程不能和routed进程同时使用,否则会导致不可预见的错误。

1. 如何启动和停止gated

gated进程是AIX中系统资源控制系统(SRC)的一个子系统,因此,我们可以用以下命令来启动和停止gated:
startsrc -s gated -- 启动
stopsrc -s gated -- 停止

top

2. gated进程的工作模式
当gated启动时,gated进程会自动查找 /etc/gated.conf 文件,根据 /etc/gated.conf 的配置启动相应的服务。因此,正确地配置 /etc/gated.conf 文件对于gated进程能否正常地启动和工作是至关重要的。

以下就本人的经验对如何配置 /etc/gated.conf 文件,从而启动最经常使用的 RIP 协议和 OSPF 协议,进行介绍:

top

1) 配置 /etc/gated.conf 支持 RIP 协议

# 该 gated.conf 文件将RIP信息的更新通知系统的所有网络接口。同时,当gated进程没有启动或路由信息没有更新时,保留路由表中的静态路由信息。

# /etc/gated.conf

traceoptions "/tmp/gated.trace" all ;

redirect yes ;

rip yes {
interface all ripin ripout;
};

static {
default gw 172.16.1.1 retain ;
};

top

2)配置 /etc/gated.conf 支持 OSPF 协议

# 该 gated.conf 文件使 gated 进程在ent0端口使用OSPF 协议。并从9.185.40.1(路由器端口)接收更新的路由信息。如果要侦听多个路由器端口,就把这些端口的地址放入 eligible 项中。

################# gated configuration for CLIENT ############

traceoptions "/var/tmp/gated.log" all ;
routerid 1
rip no ;
ripng no;
hello no;

ospf yes {
traceoptions state detail packets ;
area 0.0.0.1 {
interface ent0 nonbroadcast cost 1 {
pollinterval 10 ;
routers {
9.185.40.1 eligible;
} ;

retransmitinterval 5;
hellointerval 10;
priority 50;
routerdeadinterval 40;
};
};
};
export proto ospfase {
proto static;
proto kernel;
proto direct;
} ;

如何拒绝某些用户的ftp访问?

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 出于安全考虑,需要拒绝某些用户的ftp访问?
解答 请编辑
/etc/ftpusers
添加需要拒绝的用户,每用户一行 For example:
#more /etc/ftpusers
ql
当尝试 ftp 登录时,系统报错:
Name (localhost:root): ql
530 User ql access denied.
Login failed

如何查看某用户共启动了多少进程?

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 用户需要查看某个用户是否启动了过多的进程,影响了系统性能
解答 请用
#ps -ef|grep username|wc -l

备注:
这是利用wc -l统计行数的功能来对用户进程数的一个估计,并不是非常准确的值。
但完全可用于参考。

如何在清理/tmp文件系统时找到过大的文件?

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 /tmp文件系统已满,如何找到哪些文件过大,并释放空间。
解答 请用
For Example, 哪些文件大于5M字节.
#cd /tmp
#find . -size +10000 -exec ls -l {} ;
备注:
删除这些过大文件时,请确认其无用

如何限制某用户在特定 pty 的访问。

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 用户想限制某些端口的访问。
解答 用户可以编辑/etc/security/user. For example:

test:
admin = false
admgroups = system
ttys = !/dev/pts/0,ALL


结果是用户test可以在除了pts/0以外的所有端口登录,当test在pts/0登录时,
系统报错You are not allowed to access the system via this terminal.

IBM pSeries和 RS/6000 哪些型号可以安装SuSE linux?

环境 平台:RS
问题 IBM pSeries和 RS/6000 哪些型号可以安装SuSE linux?
解答 到2002年6月4日为止,RS6/6000 B50,150 和F50可以安装SuSE Linux for PowerPC Version 6.4 (支持32位内核);目前pSeries 和 RS/6000 中除p680外均可安装SuSE Linux Enterprise Server (SLES) Version 7(支持64位内核)。

更多信息可查看:

http://www.suse.com
http://www.suse.com/us/products/suse_business
/sles/sles_iSeries_pSeries/index.html

如何在图形登录和命令行登录方式间切换?

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 用户需要在 CDE 的两种登录方式中切换。
解答 请用
#/usr/dt/bin/dtconfig -e 激活图形登录方式
#/usr/dt/bin/dtconfig -d 激活命令行登录方式

如何处理 mountd 和 nfsd 无法正常启动

环境 S/390或zSeries;OS/390
问题 网络文件系统(NFS)是UNIX的通用网络协议,允许文件或打印机通过网络实现共享。在AIX操作系统中,对 NFS 的管理有5个进程,分别是biod, nfsd, rpc.mountd, rpc.statd 和rpc.lockd. 本文将就如何处理nfsd和mountd无法正常启动的问题加以简单介绍,因为在实际工作中,经常会遇到这类情况。
1. mountd 和 nfsd 进程的介绍
2. mountd 进程没有启动
3. nfsd 进程没有启动

解答 1. mountd 和 nfsd 进程的介绍

mountd 进程是一个远程过程调用 (RPC) ,其作用是对客户端要求安装(mount)文件系统的申请作出响应。mountd进程通过查找 /etc/xtab文件来获知哪些文件系统可以被远程客户端使用。另外,通过mountd进程,用户可以知道目前有哪些文件系统已被远程文件系统装配,并得知远程客户端的列表。

nfsd 进程运行在服务器端,负责处理远程客户端对本机文件系统的操作。每一个nfsd进程同时只处理一个客户端的操作申请,因此在一台NFS服务器上可能会启动多个 nfsd进程。

2. mountd 进程没有启动

如果mountd进程没有启动,我们需要检查以下内容: 1)99%的可能性是loopback的名字解析不正确所导致。换句话说,必须保证loopback所对应的 IP 地址是127.0.0.1;同时127.0.0.1所对应的名字是loopback,而不是localhost。我们可以用 "host 127.0.0.1"和 "host loopback"命令来检查。

以下输出结果是正确的:

#host 127.0.0.1
loopback is 127.0.0.1, Aliases: localhost
#host loopback
loopback is 127.0.0.1, Aliases: localhost

以下输出结果是错误的:

#host 127.0.0.1
loopback.cn.ibm.com is 127.0.0.1, Aliase: localhost.cn.ibm.com
#host loopback
loopback.cn.ibm.com is 127.0.0.1, Aliase: localhost.cn.ibm.com

如果 host 命令的输出结果是错误的,则需要检查 /etc/hosts 文件以及名字解析的顺序 -- 通常在 /etc/netsvc.conf 文件中加入 hosts=local,bind。

2)使用命令
lslpp -l bos.adt.lib
检查该文件集是否存在,否则需要安装。

3)安装最新的 bos.rte.tty, bos.rte.streams 和 bos.net.nfs.client 文件集。
运行 rpcinfo -p =>应当返回 portmap的注册进程列表。
若进程列表没有返回,则需要启动或重新启动 portmap 进程。
若进程列表返回,则运行 rpcinfo -u localhost mountd 命令,如果有错误,则运行 /usr/sbin/rpc.mountd,从返回的错误信息中获取可能的错误原因。

3. nfsd 进程没有启动

如果 nfsd 进程没有启动,我们需要检查以下内容:

1)首先要确认 NFS 输出列表存在,否则 nfsd 不会启动。可用 exportfs 命令来检查,如果 exportfs 命令没有结果返回或返回不正确,则需要检查 /etc/exports 文件。

2)运行 scls 命令,确保 timod 和 tirdwr 存在 --

#scls              
bufcal fi ptc sc sna_v5ro tcp6 tr udp6
echo ldterm pts sf snasxm timod ttyp unixdg
en lft0 ptyp sixp spx tioc udp unixst
et nuls sad slog tcp tirdwr    

否则需要检查 /etc/pse.conf 文件,并取消对它们的注释。

3) 检查名字解析,参见 “mountd 进程没有启动”的第一项。

4)确保以下输出数值不大于 "no -o sb_max"的数值 (尤其在SP系统中)。

# no -a
udp_sendspace
udp_recvspace
tcp_sendspace
tcp_recvspace

#nfso -a
nfs_soketsize
nfs_tcp_socketsize
 
在移植安装(Migration installation)中都有那些文件和数据保留下来?

环境 产品 pSeries,RS6000
问题 在移植安装(Migration installation)中都有那些文件和数据保留下来?
解答 操作系统使用移植安装(Migration installation)的方式升级AIX版本,例如: AIX 3.2, AIX 4.1, AIX 4.2, 或者 AIX 4.3 到 AIX 5L 5.1 。 除了/tmp目录将被覆盖外,此方式将保留所有文件系统,包括根(root)卷组的数据, 逻辑卷数据和系统配置文件。移值安装(Migration installation)的方式在AIX 3.2,AIX 4.1和 AIX 4.2 的机器上是缺省的安装方式。

如何阻止某些用户远程登录,telnet,rlogin?

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 出于安全考虑,需要使某些用户只能在控制台登录使用,而不允许远程使用
解答 请编辑
/etc/security/user
更改需要限制的用户属性 rlogin = false
当尝试远程登录时,系统报错:Remote logins are not allowed for this account

如果想将linux应用移植到pSeries和RS/6000上,哪里有参考资源?

环境 平台: pSeries, RS/6000
问题 如果想将linux应用移植到pSeries和RS/6000上,哪里有参考资源?
解答 用户如果想将linux应用移植到pSeries和RS/6000上,在Aix 4.3和Aix 5.1上都可以用AIX Toolbox for Linux Applications来重新编译应用。
书号为SG24-6033-00的红皮书对此有很好的阐述。
具体网址如下: http://www.redbooks.ibm.com/abstracts/sg246033.html


如何下载RS/6000相关的补丁(Fix,PTF),维护包及微码(Microcode)

环境 产品: pSeries, RS/6000
平台: Aix
问题 如何下载RS/6000相关的补丁(Fix,PTF),维护包及微码(Microcode)
解答 要下载RS/6000相关的补丁(Fix,PTF),维护包及微码(Microcode),可以先访问如下网址:

http://www-900.ibm.com/cn/support/r6download.shtml

先参考页面中的下载使用指南,然后点击相应的连接进行下载。
 
Aix 4.3上支持超过2GB的文件吗?

环境 平台: pSeries, RS/6000
版本: Aix 4.3
问题 Aix 4.3上支持超过2GB的文件吗?
解答 Aix 4.3上最大能支持64GB的文件尺寸,这需要在创建文件系统时(运行crfs)选中支持大文件(large file enabled)选项.
如果这一选项没有被选中,Aix 4.3支持的最大文件尺寸是2GB.

AIX无线系统管理器

内容
提要 本篇文章阐述了所有可能解决系统空间不足的方法,您并不需要按照所列的步骤全部执行,选取其中最有效的一种或几种方法即可。
说明 在今天的7X24小时不断运行的商业环境中,工作和生活的界限已变得越来越模糊。普及计算使得人们可以随时进行商务活动,与同事沟通,并接收有关信息----不论是在办公室还是在别的地方。
WSMA通过使用无线设备把移动服务器管理带进了一个新天地。使用标准的WAP手机,系统管理员可以通过使用AIX用户认证登录到AIX系统中,监视系统并执行一些关键业务的管理功能。用“推”技术实施的按条件进行的服务器报警功能把IT人员从控制台上解放出来。它也可以把短消息发送到管理员的手机上来通知他预先定义的条件已经被触发。
说明 背景
自从1994年Sprint 推出了个人通信系统(PCS)---电话服务以来,美国无线工业在北美的企业和消费市场上几乎无所不在。尽管在西欧和亚太地区有些滞后,无线数据通信的营业收入还是预计比无线话音通信的营业收入增长快。

移动Internet是需要基于标准的无线协议和数据表示的无线互联的网络。据Dataquest的预计,最通用的无线协议是WAP,到2002年,基于WAP的手机销量会达到2.5亿台。事实上,Gartner Group预计,到2004年,95%的新手机都会是能使用WAP的。

对WAP的支持并不限于无线手机。目前在市场上有许多可用的WAP浏览器,最著名的是那些基于Palm OS的PDA。也有的是基于LINUX 的无线嵌入式设备,作为通用的标准WAP浏览器在某些地方流行。随着对3G高速载运服务的承诺,将会把速度提高到每秒传递一百万比特信息,可以想象在将来,移动用户可以用手机连接到所有需要连接的移动设备上!在无线网络上将会有开放的基于标准的安全措施来保证完成可信的、保密的端到端的电子商务。

高速的可靠的移动网络使得移动用户或IT人员能够使用一个无线的构架来管理其应用和系统。AIX无线系统管理器(Wireless System Manager for AIX [WSMA])就是一个无线的系统服务,它允许对系统资源进行安全的和保密的管理(如 CPU, 磁盘, 设备和应用)。

AIX无线系统管理器---WSMA
在今天的7X24小时不断运行的商业环境中,工作和生活的界限已变得越来越模糊。普及计算使得人们可以随时进行商务活动,与同事沟通,并接收有关信息----不论是在办公室还是在别的地方。
WSMA通过使用无线设备把移动服务器管理带进了一个新天地。使用标准的WAP手机,系统管理员可以通过使用AIX用户认证登录到AIX系统中,监视系统并执行一些关键业务的管理功能。用“推”技术实施的按条件进行的服务器报警功能把IT人员从控制台上解放出来。它也可以把短消息发送到管理员的手机上来通知他预先定义的条件已经被触发。

与其他类型系统管理的关系
传统的企业管理软件(如Tivoli的TME)是从一个控制台上管理企业中的资源。监视、报告并执行对所管理资源的一些动作是由操作员在一个中央地点进行的。在企业管理系统中,服务器、网络和客户端(包括无线设备)都是被收集、分类和查看的管理工具。如果一个网络问题出现并报警,操作员是要出现场来排错并解决问题的。

WSMA只是帮助一次管理一个服务器。它假设无线网络或设备本身如果出错,仍要用现有的网络和企业管理工具来处理。

认证、保密、授权
WSMA与IBM Everyplace Wireless Gateway在网络上提供了如下的安全功能:

鉴别 ? 用户如何被识别和认证

保密 ? 通过Wireless Transport Layer Security(WTLS) 和 Secure Socket Layer (SSL)协议加密数据

授权 - 根据用户权限允许其相应的动作

这个安全的桥梁用在WTLS和SSL通道之间解密和加密数据的方式在基于WAP的客户端和HTTP服务器端之间提供了很大的灵活性。但是这也显出了一个潜在的敏感数据暴露问题:发送到数据网关本身的数据有安全隐患!因为数据的加解密是在数据网关上进行的。在进行总体网络安全规划和配置时把无线网关置于受保护的地点是一个很重要的考虑事项。

WSMA 组件
WSMA通过使用安全的WAP设备提供对服务器和应用的管理。它使用了一个标准的软件组件集合和无线设备:

一个WAP浏览器, 它必须被载入到一个手机或PDA中

在网络上的一个无线网关

WSMA 设备, 它作为一个标准的HTTP 服务器插件运行在被管理的服务器上

连接层的安全是通过利用PPP协议的Remote Access Service (RAS)来访问企业的intranet。请参考如下的示意图来理解不同的协议、安全组件、WAP手机间的关系、网关和在无线网络中的被管理的服务器。

无线网关
无线网关是一个用于在 WAP 客户端和WSMA间通讯的必需的组件。 它监听从客户端来的数据和消息并翻译 Wireless Session Protocol (WSP) 请求到 HTTP请求,然后再转发到HTTP 服务器。应答报头被从HTTP转换为WSP 应答报头, 内容从WML 和/或 WMLScript 转换成二进制 XML (wbxml),再转发到WAP客户端。 IBM Everyplace Wireless Gateway (EWG) 是一个强壮的、可扩展的 WAP 网关,它可以在企业的网络中配置。

由 WSMA管理的资源
分成以下三类:

查看 - 列出通用的系统信息如 Vital Product Data, 错误日志;

调查 - 通过查看各种系统资源条件确定问题所在;

修正 - 通过启/停系统资源和应用来管理系统和应用。

因为WAP手机的有限的屏幕尺寸,用户接口必须简明,集中。有了这样的意识,对于不同的类别和由WSMA执行的行动请参考下表:

系统信息 VPD/错误: 显示或清除系统错误日志
RAM/CPU/磁盘: CPU使用率,列出磁盘的总空间和空闲空间,列出总的和空闲的页交换空间
问题确定 Ping 主机: 用主机名或IP地址ping主机
进程管理: 通过所有者,所有CPU或当前CPU管理进程
设备管理: 列出在线或离线的设备
管理任务 对用户发wall命令: 发送标准的或客户化的信息给所有登录中的用户;
文件/文件系统/页交换空间:清除或扩展文件系统,mount/unmount 文件系统,查看页交换空间;
进程/子系统:列出或杀死进程,列出/查询/启动/停止/刷新/跟踪子系统;启动/停止/刷新/跟踪子服务器
应用/打印:启动/停止应用;启动/停止/取消打印作业;
重启/停机:重启/停止系统。

管理员通过预定义的通知或查看任何异常条件就知道需要做特定的行动,并通过预见某一场景(如计划停机等)来修正系统。
WSMA 的目的并不是替换系统管理控制台,而是在发生错误时帮助处理关键的系统和应用。如果需要,完全的错误诊断和改正可以以后在服务器上执行。

WSMA系统工作过程
以下场景描述了用WSMA的顺序的行动:
1. 管理员配置何种条件需要通知,并输入通知目的地的手机号码或短信息地址
2. 一个短信息出现在管理员的手机上,表示某种条件值得注意。
3. 管理员用WAP设备和密码登录服务器,这个设备跟是接收短信息的设备可能是同一个。.
4. 管理员会看到主菜单,他浏览并执行一个与收到的短信息有关的改正错误的动作。如果该信息是一个动作的通知,如一个作业完成了,管理员可以检查这个作业的状态。
5. 管理员退出,中断会话,挂断手机。

对服务器管理的发送通知赋予了管理员实时响应的能力。连接是安全的,而且是随时随地。这种管理对公共载体的依赖很小,在今天就已经可用的标准的安全协议可以保证我们获得安全的交易和操作,所以通过无线设备管理服务器是不仅可能的,也是现实的。

如何改变上传ftp文件的缺省读写属性?

环境 AIX 4
问题 如何改变上传ftp文件的缺省读写属性?
解答 在AIX环境中,当用户从Windows上传文件到AIX服务器时
所传文件的缺省读写属性为640(rw-r-----)。如想改变
缺省读写属性为644,首先用vi编辑器打开/etc/inetd.conf
文件,在"ftp"定义行的末尾加上"-u 033",然后刷新inetd进程:

refresh -s inetd

这就改变了ftp文件的缺省属性。

AIX中的 rmss 命令的用途

环境 产品,平台,机型, RS6000, Pseries
软件版本, AIX v4
问题 AIX中的 rmss 命令的用途是什么? 如何使用 rmss 命令?
解答 rmss 是在现有物理内存大小的基础上模拟服务器的物理内存大小的命令, 而无需拔出或替换内存芯片. 通过在不同的内存下运行同一应用,可以确定应用在正常运行时所需内存的尺寸.
例如:

#rmss -c 2048 :模拟2GB的内存
#rmss -p :显示当前模拟内存的大小
#rmss -r :重置内存,使之恢复到实际内存尺寸

在AIX 4.x如何清除挂起的tty(-)

环境 RS6000, AIX 4.x
问题 在AIX 4.x如何清除挂起的tty
解答 为了说明方便,下面的例子假设挂起的tty端口为tty0.

1.确定当前挂起的tty正在操作的进程:

ps -ef | grep tty0

该命令假设返回内容如下:

root 12345 1 0 Aug 29 0 /path/program_name

进程ID (PID) 是"12345". 杀掉该进程:

kill -9 12345

再次运行ps -ef | grep tty0 命令去查看该进程是否被杀掉。

不要使用“-9”的选项去杀掉slattach进程,因为它可能导致AIX操作系统挂起。
注意:如果进程是“getty”, 使用下面命令去杀掉进程:
pdisable tty0
如果上面命令不能成功的杀掉进程,而tty仍然是挂起的,可以使用第二步。

2. 执行下面的命令:
fuser -k /dev/tty0

该命令将杀掉运行在此端口的所有进程,并且显示其PID (进程 ID).
如果上面命令不能成功的杀掉进程,而tty仍然是挂起的,可以使用第三步。

3. 在被挂起的终端的键盘上,键入“Ctrl+Q”. 如果tty仍然挂起,使用第四步。
4. 物理的断开连接端口的设备(连线). 在某些情况下可以释放端口.

注意:前面的一些命令也许不会生效并且报”设备忙“的错误。这是由于一些进程正运行在tty上。如果上面的步骤仍不能释放挂起的tty,最后可以通过重起AIX释放内核去清除此进程。

在AIX中扩展卡的逻辑名和它所在插槽的对应关系

环境 产品, Pseries, RS6000
软件版本, AIX
问题 在IBM的Pseries 服务器中,相同类型的扩展卡可以插多块,但是AIX如何确定每一块卡所在的插槽?
解答 可用以下步骤来确定它们的关系:

1. 检查相同类型的卡的逻辑名及个数.

例如确定服务器中以太网卡的名称:
# lsdev -Cc adapter |grep en
ent0 Available 1A-08 IBM 10/100 Mbps Ethernet PCI Adapter (23100020)
ent1 Available 21-08 IBM 10/100 Mbps Ethernet PCI Adapter (23100020)

2. 通过查看Device Specific. 的值,确定其所对应的插槽.
如:
# lscfg -vl ent0 DEVICE LOCATION DESCRIPTION ent0 1A-08 IBM 10/100 Mbps Ethernet PCI Adapter (23100020) Serial Number...............22010344 FRU Number..................091H0397 Part Number.................091H0397 Network Address.............000629DC698C Displayable Message.........PCI Ethernet Adapter (23100020) Device Specific.(YL)........P1-I3/E1 I3 表示此网卡插在第三槽上.# lscfg -vl ent1 DEVICE LOCATION DESCRIPTION ent1 10-80 IBM 10/100 Mbps Ethernet PCI Adapter (23100020) Network Address.............0004ACE4AF6D Displayable Message.........PCI Ethernet Adapter (23100020) Device Specific.(YL)........P2/E1 是集成在主板上的网卡.
 
如何对系统做镜像以提高系统高可用性和性能

环境 RS6000
问题 如何对系统做镜像以提高系统高可用性和性能
解答 通常情况下, 对系统做镜像会提高系统的高可用性, 即当其中一块盘损坏或数据区不可用时,系统会自动使用其镜像盘或镜像数据区进行正常的业务操作. 在以RS/6000系统为基础的数据库应用中做镜像有三种方式, 第一种方式是通过做RAID10直接对硬盘做镜像, 需要增加相应的适配卡支持. 可以对裸设备或文件系统做镜像. 第二种方式是通过AIX操作系统做RAID1, 只能对文件系统做镜像. 第三种方式是通过数据库系统做镜像,可以对裸设备或文件系统做镜像. 对于这三种方式一般建议大家采取前两种方式会取得比较好的系统性能和高可用性.本文主要讨论使用RAID1做镜像时系统拥有的盘数对性能的影响.

做RAID1镜像时,可以对卷组中指定的逻辑卷单独做镜像, 也可以对整个卷组做镜像. 对卷组中指定的逻辑卷做镜像时, 最好要求该卷组有三块或三块以上的硬盘以保证数据高可用性. 若对整个卷组做镜像则没有对卷组内硬盘个数的限制.此外要求镜像最好位于不同的硬盘, 当其中某块硬盘损坏时其镜像盘仍可工作, 以提高系统的高可用性.

下面介绍为什么对卷组中指定的逻辑卷做镜像时, 最好要求该卷组有三块或三块以上的硬盘。

在RS/6000系统中, 每个在VG(卷组)中的物理硬盘都至少有一个VGDA(卷组描述区, 既对该硬盘上的物理和逻辑卷进行描述). VGDA在硬盘的数量有如下规则:

一个卷组只有一块硬盘: 该硬盘有两个VGDA.

一个卷组有两块硬盘: 第一块硬盘有两个VGDA, 第二块硬盘有一个VGDA.

一个卷组有三块或三块以上硬盘: 每块硬盘有一个VGDA.
在AIX系统中, quorum(一个卷组中的可用VGDA的比率)必须高于51%, 该卷组才可用. 对于只有两块硬盘的卷组, 若第一块硬盘损坏, 则只有33%的VGDA可用, 若第二块硬盘损坏, 则有66%的VGDA可用. 对于有三块或三块以上硬盘的卷组, 若损坏一块硬盘, 至少有66%的VGDA可用.

对卷组中指定的逻辑卷做镜像时, 若该卷组中只有两块硬盘, 当第一块硬盘损坏时, 其VGDA只有33%可用, 会导致该卷组不可用,这样就使得镜像失去保证硬盘高可用性的功能.

若该卷组只有两块硬盘又一定要做镜像时, 可以关掉quorum, 即使第一块硬盘损坏也不会使整个卷组不可用,此时系统使用第二块硬盘,但是第二块硬盘的数据将不能镜像. 由此有可能带来数据丢失的风险,第二块硬盘损坏时会导致该卷组不可
用从而引起数据丢失.

因此, 对卷组中指定的逻辑卷做镜像时, 最好要求该卷组有三块或三块以上的硬盘以保证数据高可用性.

Debug mode 引导AIX

环境 RS/6000 AIX V5.1
问题 Debug mode 引导AIX
解答 1. 系统要求配置有tty console
2. #bosbot -aI /dev/ipldevice
3. #shutdown -Fr

kdb command

环境 RS/6000 AIX 5L
问题 启动sendmail
解答 AIX 5L中kdb替代AIX V4的crash命令,作为系统debugger和dump分析工具

在AIX中如何为一块网卡,配多个IP地址?

环境 产品, Pseries, RS6000,
软件版本, AIX4.3.3
问题 由于应用的环境要求,需在一块网卡上配置多个IP地址,AIX中可以实现吗?
解答 可以。 使用命令ifconfig 即可.其语法为:
ifconfig network_interface second_ip_address netmask your_netmask alias
在ODM中未记录此定义,所以关机后该定义会丢失,若需要的话,可将该命令加在启动文件(/etc/rc.net)中.

如第二个IP地址是 9.185.43.135 可用
# ifconfig en0 9.185.43.135 netmask 255.255.255.0 alias

当该IP地址不再需要时,可从系统中删除.
#ifconfig en0 9.185.43.135 netmask 255.255.255.0 delete
或从/etc/rc.net文件中删除。

AIX内核参数调整之vmtune -p -P(2)?

环境 AIX 4
问题 AIX内核参数调整之vmtune -p -P(2)?
解答 -p minperm
如果在物理内存中的文件页面数量(file pages)低于此值,页面替换算法将替换文件页和程序页(computational pages),minperm的缺省值约为20%的物理内存。

-P maxperm
如果在物理内存中的文件页面数量(file pages)高于于此值,页面替换算法将只替换文件页,maxperm的缺省值约为80%的物理内存。

如果在物理内存中的文件页面数量在这两个值之间,页面替换算法通常只替换文件页,但是当文件页面的再替换率(repaging rate)高于程序页面时页面替换算法将同时替换文件页和程序页。

AIX内核参数调整之vmtune -f -F(3)?

环境 AIX 4
问题 AIX内核参数调整之vmtune -f -F(3)?
解答 -f minfree
指出内存在free list中内存页的最低值,此值的范围从8到204800。

-F maxfree
当系统中的空闲内存小于minfree时,系统进行换页操作增加空闲内存页,当空闲内存页的数量大于等于maxfree时,系统换页操作停止。

maxfree的缺省值为minfree+8。maxfree-minfree的差值应大于等于maxpgahead。

注:一个页面的大小为4K。

Linux 与 Pseries/RS6000

环境 产品, Pseries, RS6000
软件版本, AIX, linux
问题 RS6000/Pseries 服务器上可安装Linux 吗? 应用程序该如何移植?
解答 1. RS6000/Pseries 的低端服务器(B80,270,170,150)可以安装Linux 操作系统. 所使用的系统版本应为 XX Linux on Pseries (由不同的 Linux公司提供) . 其上编译的Linux 应用程序使用的是 Linux 核心.

2. Pseries中的中高端服务器目前不可安装Linux, 但可以安装 AIX Toolbox for Linux Applications for Power System, 该工具箱提供了Linux API 接口, 在其上编译的Linux 应用程序使用的是AIX核心.

3. 在 XX Linux on Pseries环境下编译的程序,移植到AIX Toolbox for Linux Applications 中需重新编译,反之亦然.

AIX内核参数调整之vmtune -M(5)?

环境 AIX 4
问题 AIX内核参数调整之vmtune -M(5)?
解答 -M maxpin
此值指出系统中能够常驻(pin)在内存中的最大的内存页的数量缺生值为80%的物理内存,应保证至少有4M的内存不被常驻,以供内核使用。

AIX内核参数调整之vmtune -r -R(4)?

环境 AIX 4
问题 AIX内核参数调整之vmtune -r -R(4)?
解答 -r minpgahead
指出何时启动提前读的功能,此值应为2的倍数,缺省值为2。

-R maxpgahead
指出最大的提前读的页数,此值应为2的倍数,缺省值为8,此值应大于minpgabead,最大值为512。maxfree-minfree的差值应大于等于maxpgahead。

如何确定一文件系统是Large File Enabled的文件系统?

环境 平台, Pseries, RS6000,
软件版本, AIX 4.3.3
问题 在AIX 4.3.3中既支持standard filesytem,也支持Large File Enabled file system, 如何确定一文件系统是Large File Enabled file system 还是 standard filesytem?
解答 可使用 lsfs -q filesystem_name 命令来查看.

例如:
#lsfs -q /home

Name Nodename Mount Pt VFS Size Options Auto Accounting
/dev/hd1 -- /home jfs 131072 -- yes no

(lv size: 131072, fs size: 131072, frag size: 512, nbpi: 4096, compress: no, bf: false, ag:

bf:false 表示是standard filesystem
bf:true 表示是Large File Enabled file system.

如何在命令行下运行update_all?

环境 AIX 4.3
问题 如何在命令行下运行update_all?
解答 在系统升级时可在SMIT中运行update_all,如果需要在命令行下运行
可用如下方法:
用lslpp -l命令产生一个系统中已安装文件集的列表,将此列表存入一个
文本文件,编辑此文件使其具有以下形式:

bos.rte.install
bos.sysmgt.sysbr
......

用以下命令安装:

installp -agXd /dev/cd0 -e /tmp/install.log -f //

其中位所生成的文本文件,所在的路径。

手工删除smit菜单

环境 AIX V4
问题 手工删除smit菜单
解答 手工删除smit菜单的步骤如下:

1、export ODMDIR=/usr/lib/objrepos
2、rm $HOME/smit.log
3、smit -D并执行想删除的一些菜单命令,查看smit.log中id的值
4、odmget -q id=*** sm_menu_opt >/tmp/smit
5、odmdelete -q id=*** -o sm_menu_opt
6、vi /tmp/smit
7、odmadd /tmp/smit

6230 SSA卡上快写缓存的设置?

环境 AIX 4.3
问题 6230 SSA卡上快写缓存的设置?
解答 对于使用SSA卡的用户,卡上的快写缓存可以极大的提高磁盘的I/O性能,用户应首先检查SSA卡上是否配置了快写缓存。

# lscfg -vl ssa0 DEVICE LOCATION DESCRIPTION ssa0 11-08 IBM SSA 160 SerialRAID Adapter (14109100) Part Number................. 27H1204 FRU Number.................. 34L5388 Serial Number...............S1072088 EC Level.................... E28793 Manufacturer................IBM053 ROS Level and ID............8300 0000 Loadable Microcode Level....05 Device Driver Level.........00 Displayable Message.........SSA-ADAPTER* Device Specific.(Z0)........SDRAM=128* Device Specific.(Z1)........CACHE=32 Device Specific.(Z2)........UID=006094BF00003CDC Device Specific.(YL)........U0.1-P1-I1/Q1 此卡配置了128MB的读缓存和32MB的快写缓存。如果配置了快写缓存,改变SSA磁盘的配置,使其使用快写缓存# smitty device SSA Disks SSA Logical Disks Change/Show Characteristics of an SSA Logical Disk hdisk? Available 11-08-L SSA Logical Disk Drive Enable Fast-Write yes 如果'Enable Fast-Write' 是no,将其改为yes。

支持Xwindows最少需要安装那些文件集(Fileset)?

环境 AIX 4.3 OR AIX 5.1
问题 支持Xwindows最少需要安装那些文件集(Fileset)?
解答 支持Xwindows需要以下文件集:

X11.apps.*
X11.base.*
X11.compat.*
X11.fnt.*
X11.motif.*

运行CDE, 需要安装
X11.Dt.*
如果希望远程使用CDE仿真,需要安装
X11.fnt.fontServer

如何改动IP地址

环境 RS6000,AIX V4
问题 如何改动IP地址
解答 如果用smit mktcpip去改动IP地址,就会在/etc/hosts中加一项,而且以前的地址仍保留,正确的做法是smit tcpip---Further configuration---Network interface----Network Interface Selection----Change/Show characteristics of a Network interface 去改动

启动sendmail

环境 RS6000,AIX V4
问题 启动sendmail
解答 如果用startsrc -s sendmail 启动,sendmail不会做为守护进程被启动,必须用startsrc -s sendmail -a "-bd"来启动
如何显示格林威治时间

环境 RS6000,AIX V4
问题 如何显示格林威治时间
解答 用date -u可以显示格林威治时间

如何打开锁死的帐户

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 用户设置某帐户如果连输3次错误的密码就把帐户锁死,但不知如何打开。
解答 用户错误登陆信息记录在/etc/security/lastlog文件中。
只要将 unsuccessful_login_count = 3 改为 unsuccessful_login_count = 0
即可打开锁死帐户。

IBM INFORMIX数据库级备份都备份了哪些内容?

环境 RS6000, IBM INFORMIX
问题 IBM INFORMIX数据库级备份都备份了哪些内容?
解答 在IBM RS6000系列机器上,系统管理员一般要定期做操作系统的备份和数据库系统的备份。那么做IBM INFORMIX数据库级备份时都备份了哪些内容呢?

一般IBM INFORMIX数据库备份分为系统备份和逻辑日志备份。有的客户认为在做系统备份时系统会将逻辑日志文件一起备份,这种理解是不正确的。

系统备份将备份数据库系统的数据,包括对根dbspace(rootdbs)和数据dbspace(datadbs)的数据的备份,它不会备份临时dbspace(tempdbs)、逻辑日志和未分配使用的根dbspace和数据dbspace的空间。

逻辑日志备份将备份系统的逻辑日志文件。

由此可见系统备份和逻辑日志备份是完全不同的,它们不可以相互替代。

在RS6000系列机器上如何配置IBM INFORMIX数据库临时数据库空间?

环境 RS6000, IBM INFORMIX
问题 在RS6000系列机器上如何配置IBM INFORMIX数据库临时数据库空间?
解答 在RS6000系列机器上安装IBM INFORMIX数据库时,一般会配置临时数据库空间以提高系统性能。那么为什么要配置及如何配置这些临时数据库空间呢?

例如在IBM INFORMIX数据库中若执行了下面的操作,将会产生临时文件或临时表:
1.建立索引或使用排序方式的连接时;
2.使用"order by"或“gruop by”语句时;
3.使用“select ...into temp...”语句创建临时表时;

这些临时表或文件最好放在临时数据库空间中以提高系统性能。
如果数据库系统频繁进行上面的操作,最好创建三个或三个以上大小相同临时数据库空间

如何改变主机IP地址解析顺序

环境 产品: RS/6000
软件: AIX
问题 如何改变主机IP地址解析顺序
解答 一般主机IP地址的解析顺序依次是DNS,NIS,本机host档案。
要改变这个顺序, 可以建立一个/etc/netsvc.conf文件,并在这个档案中加一行:
hosts=local,bind,nis

这样主机IP地址就先从本地档案(/etc/hosts)开始搜索,其次再去DNS server,最後是NIS server。
也可通过执行
export NSORDER=local,bind,nis
改变环境变量NSORDER 来改变顺序

不能增加用户,错误信息为3004-687

环境 RS6000, AIX 3.2 -- 4.x
问题 不能增加用户,错误信息为3004-687
解答
检查:

在/etc/passwd文件中是否有错误的语法.
丢失“nobody”用户条目或其格式有错误. 其条目应为:

nobody:!:4294967294:4294967294::/:

登录失败次数过多

环境 RS6000
问题 登录失败次数过多
解答 在用户登录失败次数过多时,超过了失败次数限制,用户将不能继续登录,需修改/etc/security/lastlog中的失败登录次数参数(unsuccessful_login_count)才可。
看SSA逻辑盘与物理盘之间对应关系

环境 RS6000
问题 看SSA逻辑盘与物理盘之间对应关系
解答 用ssaxlate -l hdisk#或ssaxlate -l pdisk#可以看SSA逻辑盘与物理盘之间对应关系

用户名长度问题

环境 RS6000
问题 用户名长度问题
解答 用户名长度最长为八位,这个限制无法改动

如何判断引起core文件的应用程序

环境 RS6000
问题 如何判断引起core文件的应用程序
解答 core文件是在应用崩溃时记录的内存影象,可以用命令lquerypv -h core 6b0 64可以看出是哪个应用引起了core文件的产生。

解锁卷组

环境 RS000
问题 解锁卷组
解答 当卷组被锁住时,可通过命令chvg -u vg#来解锁

inittab中引用的环境变量

环境 RS6000
问题 inittab中引用的环境变量
解答 问题产生原因是由于客户有很多几百k的小文件,将所有的文件系统inode用尽。
在inittab中启动的程序,只引用了/etc/environment中的环境变量,并不引用/etc/profile或/.profile中的变量,所以在用户自定义脚本中如需引用这些变量,需在脚本中加入对它们的引用

在一个磁带上备份多个文件

环境 RS6000
问题 在一个磁带上备份多个文件
解答 需要用到 tctl来卷带备份,例子如下:

1. dd if=/tmp1 of=/dev/rmt0.1
2. tctl -f /dev/rmt0 rewind
3. tctl fsf 1
4. dd if=/tmp2 of=/dev/rmt0.1
5. tctl -f /dev/rmt0 rewind
6. tctl fsf 2
7.......

恢复步骤相反。

夏时制问题

环境 RS6000
问题 夏时制问题
解答 每年四月到八月,AIX会缺省使用夏时制,可以用echo $TZ看时区来判断,时区以DT结尾的就使用了夏时制。如果不想用,可以通过smit--system environment--change show date and time---change time zone using system defined values来改变,在弹出的USE DAYTIME SAVING对话框中选择No,选好相应的时区后重启机器既可。

passwd文件的备份

环境 RS6000
问题 passwd文件的备份
解答 如果误删除了/etc/passwd文件,可以用/etc/opasswd文件恢复,/etc下o开头的文件是相应文件的备份文件。

如何限制某个用户使用FTP服务

环境 AIX
问题 在AIX中,如何限制某个用户使用FTP服务?
解答 编辑/etc/ftpusers文件,把要限制使用的用户名加进此文件里,这样就限制了此用户使用FTP服务。

在AIX系统中,如何得到一些偏僻的汉字

环境 AIX
问题 在AIX 系统中,如何得到一些比较偏僻的汉字?
解答 在AIX的中文汉字库中,zh_CN 中有6763个汉字,而ZH_CN中有20902个汉字。如果用户要用到一些比较偏僻的汉字,建议用户安装中文环境时选择ZH_CN。

AIX 是否支持 ramdisk

环境 RS6000, AIX
问题 AIX 是否支持 ramdisk? 可否将内存当硬盘来使用,以提高访问速度。
解答 可以. AIX 操作系统支持ramdisk. 可使用mkramdisk命令来创建一个ramdisk. 其文件名为 /dev/rramdisk. 通过命令mkfs在其上建立文件系统来使用它. 用rmramdisk 命令或重新开机来删除ramdisk.

什么是 inline log

环境 产品, AIX
平台, RS6000, Pseries
问题 什么是 inline log
解答 在AIX5L 中可以为JFS2的文件系统创建一种新的日志类型。 这就是JFS2所特有的 inline log -- 日志与文件系统在同一逻辑卷上。

通过使用 inline log , 每个JFS2的文件系统可有独立日志设备,而不是整个卷组共享一个日志设备。 在文件系统数量较多的环境下,能够提高系统的RAS(Reliability Availability Serviceability)特性:在系统共享日志设备时, 日志设备的损坏会影响与之相关的所有文件系统。而使用inline log , 则不会出现此种情况。

创建JFS2文件系统时,缺省日志是放在共享的日志设备上, 将 "inline log ? "选项设为 "YES", 则建立了使用inline log 的JFS2 文件系统。

如何增加文件系统中的inode数目

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 用户需要生成新的文件时,系统报告空间不够,但df -k输出显示空间使用为43%
解答 问题产生原因是由于客户有很多几百k的小文件,将所有的文件系统inode用尽。
解决方案

find / -size 0 -print 删除不必要的0字节文件

增加文件系统大小(鉴于客户的%used是43%,这样会浪费很多空间,不建议使用)

备份文件,重建文件系统,其中参数NBPI(number of bytes per inode)要尽量
小,这样就能在同样大小的文件系统中获得更多的inode
备注:

文件系统中inode的多少由文件系统大小和NBPI(number of bytes per inode)决定
文件系统越大,NBPI越小,那么inode越多,意味能产生的文件和目录越多。

什么是X-window

环境 产品, RS6000
平台, UNIX
问题 什么是X-window
解答 X-window 是UNIX中功能强大的图形用户接口(GUI),是基于客户-服务器的一种应用技术. 表现为应用可运行在一个功能强大,易与维护的服务器上,而屏幕的输出则显示在另一个工作站上. X-window 技术包括两个成员: X-server 和 Window Manager. X-server 控制图像和窗口的显示, 跟踪鼠标和键盘的操作.一个X-server可控制多个窗口.Window Manager 则用于显示窗口的菜单和边界,提供窗口的移动,转换,最大,最小化操作.

如何为调试应用程序性能 定制系统内存环境

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 用户需要为调试应用程序在不同的内存配置下的性能。
解答 操作系统提供了这样的应用来满足客户的需求。
rmss -c memsize (设置需要调试的内存)
rmss -p 显示当前的内存配置
rmss -r 重新恢复至系统的实际内存大小

举例:
#rmss -p
Simulated memory size is 512 Mb.
#rmss -c 128
Simulated memory size changed to 128 Mb.
#svmon -G

size inuse free pin virtual stolen
memory 131061 121681 9380 9417 31604 95584
pg space 264192 17306        

其中stolen的内存就是512Mb和128Mb的差。
当在128Mb内存下调试完程序后,恢复系统实际内存大小。
#rmss -r
#svmon -G

size inuse free pin virtual
memory 131061 26245 104816 9417 31604
pg space 264192 17306      

free的内存已经恢复如初。

关于AIX 4.3.3的内核问题。

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 1.我目前的操作系统运行在多少位的内核上?
2.我目前的机器能支持64bit应用吗?
解答 bootinfo -K
32 操作系统运行在32位内核
64 操作系统运行在64位内核

bootinfo -y
64 你的机器可以支持64位和32位应用
32 你的机器只支持32位应用
备注:

当bootinfo -K为32,bootinfo -y为64时,可以通过smit激活对64位应用的支持
SMIT
System Environments
Change / Show Characteristics of Operating System

如何在AIX上实现象doskey一样的功能

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 客户需要实现类似doskey一样的功能
解答 在AIX操作系统中可以利用 set -o vi来实现类似功能。
当用户想重复上一个很长的命令时,只需按ESC+k就行,再按k就上滚一条命令,
而按j就可以后滚一条命令,然后回车就可以完成了。更好的是,你可以利用类似
使用vi的方法来编辑你所看到的命令,来达到随意调整的目的。
只一条简单的命令,就节约了宝贵的时间。需要时可以把set -o vi加入到.profile中。

另一种让vi编辑超大文本文件的方法

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 vi缺省能编辑的最大文件不能超过1,048,560行
解答 在用户目录下生成文件.exrc其中写入
set linelimit=xx000000
这样,就不用每回启动vi时都敲入vi -y xx000000

如何修改终端的属性以适应特殊需要

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 客户有一个自己开发的应用,其中需要对ctrl+y的响应,来完成特定功能。
但当客户实现时,却发现一按ctrl+y程序就退出了。
解答 客户使用的是telnet终端,其中需要对pty的属性进行修改。
#smit pty
Change / Show Characteristics of the PTY
STATE to be configured at boot time ---------------available -----+
Maximum number of Pseudo-Terminals ---------[256]---------------- #
Maximum number of BSD Pseudo-Terminals -----[16]
其中并没有象tty一样的许多选项:
#smit tty
POSIX special control characters:

INTERRUPT character ------------------------[^c]
QUIT character -----------------------------[^]
ERASE character ----------------------------[^h]
KILL character -----------------------------[^u]
END OF FILE character ----------------------[^d]
END OF LINE character ----------------------[^@]
2nd END OF LINE character ------------------[^?]
DELAY SUSPEND PROCESS character ------------[^y]
SUSPEND PROCESS character ------------------[^z]
LITERAL NEXT character ---------------------[^v]
START character ----------------------------[^q]

解决办法:
将suspend process character ^y变成其他不需要的特殊按键
如:
#stty dsusp ^@
#stty -a
speed 9600 baud; 24 rows; 80 columns;
eucw 1:1:0:0, scrw 1:1:0:0:
intr = ^C; quit = ^; erase = ^H; kill = ^U; eof = ^D; eol = ^@
eol2 = ^@; start = ^Q; stop = ^S; susp = ^Z; dsusp = ^@; reprint = ^R
discard = ^O; werase = ^W; lnext = ^V
-parenb -parodd cs8 -cstopb hupcl cread -clocal -parext
-ignbrk brkint ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl -iuclc
-ixon -ixany -ixoff imaxbel
isig icanon -xcase echo echoe echok -echonl -noflsh
-tostop echoctl -echoprt echoke -flusho -pending iexten
opost -olcuc onlcr -ocrnl -onocr -onlret -ofill -ofdel tab3

这样当客户的应用再按ctrl+y时,程序就不会异常退出了。

如何利用grep的一些高级选项更好地管理系统

环境 产品: AIX
平台: RS
软件版本: AIX V4
问题 如何利用grep的一些高级选项更好地管理系统
解答 较下面两个命令的输出,我们不难发现grep -p的优秀功能。
它不止把我们要找的关键字的当前行列出来,还列出了相关信息。
#lscfg -vp|grep cpu
Device Type: cpu
Device Type: cpu
#lscfg -vp|grep -p cpu
Name: PowerPC,604
Node: PowerPC,604@0
Device Type: cpu
Physical Location: P1-C1

Name: PowerPC,604
Node: PowerPC,604@1
Device Type: cpu
Physical Location: P1-C1
另一个非常实用的功能grep -i
#lslpp -l|grep xlc
none
#lslpp -l|grep -i xlc

xlC.aix43.rte 4.0.2.1 COMMITTED C Set ++ Runtime for AIX 4.3
xlC.cpp 4.3.0.1 COMMITTED C for AIX Preprocessor
xlC.msg.en_US.cpp 4.3.0.1 COMMITTED C for AIX Preprocessor
xlC.msg.en_US.rte 4.0.2.0 COMMITTED C Set ++ Runtime
xlC.msg.zh_CN.rte 4.0.2.0 COMMITTED C Set ++ Runtime
xlC.rte COMMITTED 4.0.2.0 COMMITTED C Set ++ Runtime

这样,我们就不用再死记硬背很多大小写的内容,提高工作效率。
相信grep还有很多强大的功能等待我们去应用。

AIX 与 LINUX 的结盟

内容
提要 本文将就AIX Affinity with Linux的发展以及在AIX操作系统下如何进行Linux的开发和如何将自由开发的Linux应用移植到AIX操作系统做介绍,目的是让更多的朋友在AIX系统平台上使用Linux, 并同时感受到AIX操作系统在整体性能上的魅力。我们期待着有更多更好的Linux应用被移植到AIX操作平台,使AIX操作系统更加丰富多彩,让我们工作得更轻松自如。
第一部分 AIX Affinity with Linux 的发展情况
第二部分 AIX Affinity 的其本原理介绍
第三部分 AIX Toolbox for Linux 最新版的获得、安装、包含工具和基本使用
第四部分 对开发的建议
说明 任何机型,操作系统 AIX 4.3.3 or AIX 5L
正文
第一部分 AIX Affinity with Linux 的发展情况

IBM对AIX Affinity with Linux的发展分为以下两个阶段。

第一个阶段,发布AIX Toolbox for Linux Applications, 它主要包含GNU和其他一些常用开发工具,来帮助开发人员在AIX系统上编译程序,并在两种行业内开放性最好的操作系统平台,即AIX和Linux之间,进行平滑技术移植。由于应用程序运行于AIX环境中,因此客户可以同时得到Linux的灵活性和AIX操作系统的先进性能,包括工作负载管理、先进系统管理工具以及高安全性。

第二个阶段是,在最新发布的AIX 5L Version 5.1 操作系统中提供更多的兼容Linux的API和头文件,来支持源文件的兼容性,使两个不同操作系统有更强的互操作性,从而达到更高程度的兼容。

那么我们能用AIX Affinity for Linux做什么呢?

1。在AIX系统上使用众多Linux上开发的自由软件,例如,运行流行的 Gnome
and KDE 图形桌面,运行其他的多媒体工具,等等。
2。用功能强大的RedHat Package Manager包工具管理应用。
3。在AIX 系统上,使用GNU和Linux开发工具进行新应用的开发。

第二部分 AIX Affinity 的其本原理介绍
AIX Affinity with Linux的目的并不是在系统中提供一个模拟层供Linux应用来运行,它的意义在于通过重新编译Linux应用后,得到AIX的兼容的二进制本地代码,并能使用所有系统的特性,如可靠性、扩展性、以及可用性。这就是说,我们提供了一个强大的跨平台编译器以及众多的兼容API来保证Linux应用在AIX系统上的成功移植。

由于AIX的设计开发从网络、主机硬件系统,到操作系统完全遵守开放系统的原则,所以在目前的AIX 4.3.3 和 AIX 5L Version 5.0, 使用AIX Toolbox for Linux,只需通过简单的编译就能在AIX平台上实现Linux的很多应用。这样,我们就不用浪费许多人力、物力去重新开发很多已经很成熟的应用。我们不断地重用经典代码,就可以把我们有限的精力投入到更精彩、更需要的地方。 当使用AIX Affinity with Linux时,我们还会想到的它对性能的影响。AIX Affinity with Linux在设计阶段,就希望提供最优化的性能给应用,其中包括让Linux应用和本地应用享有同样访问资源的权利。尤其是AIX 5L Version 5.1操作系统,会提供更高级别的应用与操作系统间的兼容性。当我们考虑性能时,还应该想到我们要开发什么样的应用,前端的还是后台的。后台的大型应用还是比较适合AIX应用,但前端的人机界面用Linux则更能发挥其特长,也减少了可能的性能影响。

第三部分 AIX Toolbox for Linux 最新版的获得、安装和基本使用

许多GNU开发工具已经被移植到AIX 4.3.3 和 AIX 5L Version 5.0,而界在新的AIX 5L Verison 5.1 操作系统中有更多的开发工具被成功移植。
其中包括(并非全部):

应用开发类:gcc, g++, gdb, rpm, cvs, automake, autoconf, libtool

开发库:ncurses, readline, libtiff, libpng, libjpeg, slang, fnlib,
db, gtk+, qt

编程语言:guile, python, tcl/tk, rep-gtk

桌面环境类:Gnome and KDE

GNU 工具:gawk, m4, indent, sed, tar, diffutils, fileutils

系统Shell:bash2, tcsh, zsh

系统工具:emacs, vim, bzip2, gzip, git, elm, ncftp, rsync, wget,
lsof, less, samba, zip, unzip, zoo

图形应用:ImageMagick, transfig, xfig, xpdf, ghostscript, gv,
mpage,Gimp

这些工具为Linux开发者提供了非常棒的开发环境。值得一提的是,他们绝大多数使用了易于安装的文件格式,这就是RedHat发展的rpm包。它的主要作用就是架起了一座通畅的桥梁,把AIX和Linux两个不同的操作系统紧密地联合起来,发掘它们更大的潜力。

AIX Toolbox for Linux 的下载网址:
http://www-1.ibm.com/servers/aix/products/aixos/linux/download.html
此网页上有众多大家梦寐以求的工具等大家来使用。


07 04, 2005
恨不抗日死,请记住我们仇人的名字
作者 xzh2000 20:35 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

企业前会长、顾问、社长
  粕谷哲夫 商业咨询顾问
  小野泽知之 光企画顾问
  河野正三 高龄者住宅财团理事长
  小林乔 富国生命保险相互会社社长
    屿崎钦也 文教堂株式会社董事长
  铃木仙吉郎 北日本写字楼管理株式会社专务董事长
  高城申一郎 住友不动产株式会社董事长、会长
  相川贤太郎 三菱重工业会长
  秋山广昌 船和大洋财团会长
  朝仓龙夫 JRR株式会社代表
  浅野胜昭 东京映像制作株式会社董事长
  池田彰效 SMK株式会社会长
  石川六郎 鹿岛建设株式会社名誉会长
  石坂泰彦 松屋株式会社原会长
  伊地知重威 原朝日银行株式会社顾问
  淡河义正 大成建设株式会社顾问
  太田芳雄 银座阿斯塔食品株式会社社长
  冈本和也 东京三菱银行专务董事
  尾崎护 国民金融公库原总裁
  小野田宽郎 财团小野田自然塾理事长
  川村茂邦 大日本墨水化学工业株式会社顾问
  舆宽次郎 日本comsys株式会社顾问
  后藤达太 西日本银行株式会社董事、顾问
  坂野常隆 清水建设株式会社董事长、顾问
  樱井修 株式会社住友信托银行特别顾问
  里见泰男 大成建设株式会社原顾问
  杉原明 日商岩井株式会社顾问
  关根广文 神户制钢株式会社特别顾问
  濑岛龙三 亚洲大学理事长、NTT日本电话电报公司顾问
  高崎一郎 三越株式会社顾问
  田中利道 和平智囊团中心株式会社顾问
  德增须磨夫 住友海上火灾保险株式会社顾问
  友国八郎 大阪商船三井船舶株式会社顾问
  飞山一男 五十铃汽车株式会社顾问
  田中敬 横滨银行特别顾问
  牧冬彦 神户制钢所顾问
  原田滋 机械产业纪念事业财团顾问
  深野和夫 山银合同银行顾问
  村田良平 日本财团特别顾问
  宫田义二 铁钢劳动联盟顾问
  矢野次郎 殖产住宅相互株式会社顾问
  吉国一郎 内阁法制局原长官、NTT日本电话电报公司特别顾问
  渡边晴朗 丸红株式会社原常务顾问
  桥口收 广岛银行董事长顾问
  铃木三郎柱 味之素株式会社顾问、名誉会长
  后藤千秋 大林组株式会社专务董事长(建筑公司)
  酒井正晴 昭和飞机工业株式会社社长
  坂口美代子 坂口电热株式会社董事长
  须藤研一郎 朝日工业株式会社原董事长
  高桥铁郎 川崎重工株式会社原副社长
  种子岛经 BMW东京株式会社原会长
  富泽繁信 住友信托银行原常务董事长
  山本卓真 富士通株式会社名誉会长
  丸山利男 日本开发银行原理事
  迁熏 德山株式会社会长
  中村功 东日本房屋株式会社会长
  名须川浩 日本海石油株式会社董事长副社长
  西田昌男 帝人株式会社董事长副会长
  野口义和 大新东株式会社副社长
  长谷川忍 池袋机场管理株式会社社长
  土方武 日本烟草产业株式会社会长
  松多昭三 株式会社损保会馆原董事、社长
  广濑元夫 广濑建筑株式会社社长
  古馆康生 爪哇石油投资株式会社原社长
  梁濑次耶 株式会社YANASI董事长
  平野富国 藤泽小田急株式会社原董事长、社长
  林慧儿 日桥文化发行人
  山崎诚三 山种综合研究所株式会社董事长
  大和嘉章 商业首脑太田昭和株式会社董事会副会长
  村井信夫 小松建设工业株式会社原董事副会长
  石井公一郎 原普利斯通株式会社社长
  铃木久章 横滨橡胶株式会社代表
  角谷泰 加商株式会社董事长、社长
  高桥季义 kinden株式会社原社长
  杉山昭二 株式会社托普拉董事会会长
  大学教授
  爱知和男 关西大学客座教授
  阿曾村邦昭 丽泽大学客座教授
  荒木和博 拓殖大学海外事情研究所副教授
  石垣贵千代 原东洋大学教授
  石川迪夫 原北海道大学教授
  市村真一 京都大学名誉教授
  伊藤宪一 青山学院大学国际政治经济学部教授
  伊藤隆 东京大学名誉教授
  伊原吉之助 帝山大学名誉教授
  入江通雅 青山大学名誉教授
  印南一路 庆应大学综合政策学部教授
  内村刚介 原上智大学教授
  宇野精一 东京大学名誉教授
  梅泽升平 尚美学园大学教授
  大原康男 国学院大学教授
  冈田英弘 东京外国语大学名誉教授
  桶谷秀昭 文艺评论家、东洋大学教授
  小田晋 国际医疗福址大学教授
  小山和伸 神奈川大学教授
  加地伸行 同志社大学特别研究员、大阪大学名誉教授
  胜田吉太郎 东京大学名誉教授
  加藤淳平 常盘大学国际学部教授
  神谷不二 东洋英和女学院大学教授
  唐津一 东海大学教授
  川胜平太 国际日本文化研究中心教授
  日下公人 多摩大学名誉教授
  川口洋 学习院大学教授
  九里几久雄 浦和大学名誉教授
  泽田昭夫 东京纯心女子大学教授
  筱泽秀夫 学习院大学名誉教授
  岛田晴雄 庆应大学经济学部教授
  岛田洋一 福井县立大学教授
  清水磬八郎 千叶大学名誉教授
  尚树启太郎 东海大学名誉教授
  白井浩司 庆应大学名誉教授
  高木桂藏 静冈县立大学教授
  高桥正 千叶商科大学教授
  高森明敕 拓殖大学客座教授
  田久保忠卫 杏林大学客座教授
  中川八洋 筑波大学教授
  中岛千寻 京都大学教授
  小林道宪 福井大学教授
  小崛桂一郎 东京大学名誉教授
  小山常实 大月短期大学教授
  佐藤和男 青山学院大学名誉教授
  田中英道 美术史家、东北大学大学院教授
  迁村明 东京大学名誉教授
  西冈力 东京基督教大学教授
  中西辉政 京都大学教授
  中村桀 独协大学教授
  名越二荒之助 高千穗商科大学原教授
  西锐夫 丽泽大学教授
  东中野修道 亚细亚大学教授
  平川佑弘 福冈女学院大学教授
  吹浦忠正 琦玉县立大学教授
  福田逸 明智大学教授
  藤冈信胜 拓殖大学教授
  松本道介 中央大学文学部教授
  三重野康 杏林大学客座教授
  新田均 皇学馆大学教授
  丹羽春喜 大阪学院大学教授
  芳贺彻 东京大学名誉教授
  长谷川三千子 琦玉大学教授
  西部迈 评论家、秀明大学教授
  百地章 日本大学法学部教授
  八木秀次 高崎经济大学助教授
  安本美典 产能大学元教授
  横沟雅夫 明星大学经济学部原教授
  吉田和男 京都大学教授
  协会、组织负责人
  山川京子 “桃会”主宰
  藏原千秋 短期资金协会会长
  上村和男 社会团体 国民文化研究会理事长
  川濑一雄 凸版印刷协会朋友会会长
  矢野俊比古 东京中小企业投资育成株式会社监察役
  伊豫田敏雄 青山监察法人代表、会长
  山口康助 东京教育恳谈会代表干事
  浅野总一郎 大阪同盟OB友爱会会长
  天池清次 原同盟会长
  金杉秀信 同盟原副会长
  重枝琢巳 同盟原书记长
  寺岛泰三 社团、日本乡友联盟会会长
  中條高德社会团体日本国际青年文化协会会长
  德永洋一 BSC株式会社董事长、会长
  富田彻郎 FCG总研会长
  野口武利 静冈县劳动者福址协议会会长
  八田诚 社团法人日本交通协会副会长
  早矢仕不二夫 东京同盟原会长
  广濑静水 人类爱善会名誉会长
  船村彻 社团法人日本作曲家协会会长
  松本洋 财团法人国际文化会馆专务理事
  宫本四郎 财团法人世界经济情报服务前理事长
  广池干堂 财团法人道德科学研究所理事长
  役山明 社团法人偕行会会长
  吉田学 财团法人水交会会长
  原多喜三 财团法人偕行社原会长
  崛江正夫 回答英灵会会长
  前野彻 亚洲经纪人恳谈会会长
  茨木武雄 纸浆经营者恳谈会事务局局长
  竹尾治男 财团法人横滨工业会理事
  黑田真 财团法人安全保证贸易情报中心理事长
  大岛阳一 东银国际株式会社研究会社长
  绪方一夫 大阪台湾同乡会副会长
  加藤日出男 财团法人青年团体协会会会长
  远藤太嘉志 日本思想教育协会理事长
  学者、研究员
  牧野升 三菱综合研究所顾问
  小室直树 现代政治研究所政治学者
  佐藤胜巳 现代韩国研究所所长
  行德哲男 日本BE研究所主宰
  奥宫正武 PHP研究所顾问
  佐濑昌盛 拓殖大学海外事情研究所所长
  片冈铁哉 斯坦福大学胡佛研究所原上级研究员
  胜冈宽次 明星大学战后教育史研究中心专任研究员
  小田全宏 日本政策论坛代表
  宇佐美忠信 财团、福士社会教育中心理事长
  若月三喜雄 日本综合研究所株式会社理事长
  矢野弹 矢野经济研究所副会长
  阿罗健一 南京事件研究学者
  上杉千年 历史教科书研究家
  上田笃 建筑学学者
  大月隆宽 民俗学者
  伊藤哲夫 日本政策研究中心所长
  作家
  阿川佐和子 随笔作家
  阿川弘之 作家
  井泽元彦 作家
  石堂淑朗 剧本作家
  石原慎太郎 作家(在名单中是以作家出现的,但是实际上他是东京都知事,即东京市长)
  泉三郎 作家
  北方谦三 作家
  木村治美 随笔作家
  工藤美代子 虚构小说作家
  小岛直记 作家
  佐藤爱子 作家
  林四郎 随笔写作家
  林秀彦 作家
  林真理子 作家
  深田佑介 作家
  常磐新平 作家
  丰田有恒 作家
  百濑明智 著述业(应该是作家)
  涛川荣太 作家、新松下村塾塾长
  评论家
  井尻千男 评论家
  市田广美 服饰评论家
  入江隆则 文艺评论家
  远藤浩一 评论家
  大宅映子 评论家
  冈崎久彦 外交评论家
  小山内高行 外交评论家
  加濑英明 外交评论家
  上条俊昭 经济评论家
  黄文雄 评论家
  小岛千加子 文艺评论家
  佐伯彰一 文艺评论家
  远山一行 音乐评论家
  苫米地重亨 政治评论家
  西尾干二 评论家
  藤井严喜 国际问题评述家
  长谷川庆太郎 经济评论家
  三宅久之 政治评论家
  宫崎正弘 评论家、作家
  屋山太郎 政治评论家
  宗教人士
  宫西惟道 日枝神社宫司
  建内光仪 加茂别雷神社宫司
  白井永二 鹤冈八幡宫名誉宫司
  加藤隆久 生田神社宫司
  小串和夫 热田神宫宫司
  矢田部正巳 神社本厅总长
  田中恒清 神道政治联盟干事长
  宫崎义敬 神道政治联盟会长
  秋本协德 宗教团体 新生佛教教团代表
  稻山灵芳 念法真教灯主
  今井原明 中山寺宝藏院住持
  睿南觉范 建立院住持
  大泽自聚 西山兴隆寺名誉院家
  大角光彻 严王院住持
  桶屋良佑 念法真教教务总长
  高桥妙齐 欢喜院住持
  泷藤尊教 四天王寺原管长
  小崛光诠 三千院门迹门主
  藤田俊教 今熊野观音寺名誉山主
  关口孝 佛所护念会教团理事
  出口顺得 和宗四天王寺执事长
  中野玄光 净土宗真福寺住持
  森田禅朗 和宗四天王寺前管长
  山本孝圆 天台真盛宗管长
  丸山秀彦 大本山国分寺宗务总长
  吉田启堂 日本佛教徒协会理事长
  小林海畅 真言宗泉涌寺派前管长
  长谷川灵信 念法真教长老
  藤光贤 天台宗宗务总长
  体育界及其他
  稻尾和久 棒球解说者
  川上哲治 日本NHK电视台棒球解说者
  川廷荣一 亚洲网球联盟会长
  藤田元司 NHK职业棒球解说者
  川岛广守 原日本职业棒球委员会委员
  境川尚 财团法人日本相扑协会理事、原横冈相扑士佐田山
  西村胜巳 体育政策学会会长、日本武道学会顾问
  加藤芳郎 漫画家
  小林善纪 漫画家
  清家清 建筑家
  泷山养 交通研究家
  秦郁彦 现代史家
  富坚信子 会计师
  福田繁雄 平面设计师
  媒体
  稻垣武 记者
  井原甲二 月刊《MOKU》主要编辑
  医生
  稻垣直 医师、日本国防协会财团评议员
  今井通子 医师、登山家
  绪方嘉隆 医师
  土居健朗 精神科医生
  田下昌明 丰冈中央病院院长
  律师
  内田智 律师
  高池胜彦 律师
  中岛修三 律师
  政府官员
  佐佐淳行 内阁安全保障室原室长
  志贺学 日本专利厅原长官
  长冈实 原大藏省事务次官
  村伟次郎 原文部省主任教科书调查官
  亘理彰 原防务事务次官(副国防部长)、财团法人日本不动产研究会会长
  学校管理者
  漆邦臣 品川女子学院理事长、校长
  小川义男 狭山丘高等学校校长
  中村胜范 平成国际大学校长
  小田村四郎 原拓殖大学总长
  加藤宽 千叶商科大学校长
  立野有文 樱丘女子学园理事长
  喜悦克 嘉悦学园常务理事
  中堂元 北斗学院株式会社代表
  村田照子 村田学园理事长
  演艺界
  津川雅彦 男演员


07 04, 2005
射雕中最多情与最无情的人
作者 xzh2000 20:11 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

多情(男):完颜洪烈

多情(女):英姑

无情(男):王重阳

无情(女):空缺


04 04, 2005
本周参加公司企业文化培训
作者 xzh2000 20:07 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

从前还真没有遇到这么重视"企业文化"的公司,嘿嘿,别的倒没有记住,对公司的历史多多少少

也有了些了解,遗憾的是看不清PPT,可能眼睛太近视啦(没戴眼镜的习惯),但更气恼的是记忆

力也越来越差了......呜呜呜.

这一周大概能来灌水的时间不多啦,下周再见.


03 04, 2005
上周六去爬山啦
作者 xzh2000 18:54 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

上周六去爬山啦,嘿嘿嘿,阵容够强吧:

biti_rainy,rudolf,piner,fenng,gressball and me.

还有几个竟然不知他们在itpub上的ID......汗.

下山后去吃自助餐并K歌,

偶有朋自上海来,就早早地离开啦... ...


01 04, 2005
linux上ssh配置指南
作者 xzh2000 19:32 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
介绍SSH
什么是SSH?
传统的网络服务程序,如:ftp、pop和telnet在本质上都是不安全的,因为它们在网络上用明文传送口令和数据,别有用心的人非常容易就可以截获这些口令和数据。而且,这些服务程序的安全验证方式也是有其弱点的,就是很容易受到“中间人”(man-in-the-middle)这种方式的攻击。所谓“中间人”的攻击方式,就是“中间人”冒充真正的服务器接收你的传给服务器的数据,然后再冒充你把数据传给真正的服务器。服务器和你之间的数据传送被“中间人”一转手做了手脚之后,就会出现很严重的问题。

SSH的英文全称是Secure SHell。通过使用SSH,你可以把所有传输的数据进行加密,这样“中间人”这种攻击方式就不可能实现了,而且也能够防止DNS和IP欺骗。还有一个额外的好处就是传输的数据是经过压缩的,所以可以加快传输的速度。SSH有很多功能,它既可以代替telnet,又可以为ftp、pop、甚至ppp提供一个安全的“通道”。

最初SSH是由芬兰的一家公司开发的。但是因为受版权和加密算法的限制,现在很多人都转而使用OpenSSH。OpenSSH是SSH的替代软件,而且是免费的,可以预计将来会有越来越多的人使用它而不是SSH。

SSH是由客户端和服务端的软件组成的,有两个不兼容的版本分别是:1.x和2.x。用SSH 2.x的客户程序是不能连接到SSH 1.x的服务程序上去的。OpenSSH 2.x同时支持SSH 1.x和2.x。

SSH的安全验证是如何工作的
从客户端来看,SSH提供两种级别的安全验证。

第一种级别(基于口令的安全验证)只要你知道自己帐号和口令,就可以登录到远程主机。所有传输的数据都会被加密,但是不能保证你正在连接的服务器就是你想连接的服务器。可能会有别的服务器在冒充真正的服务器,也就是受到“中间人”这种方式的攻击。

第二种级别(基于密匙的安全验证)需要依靠密匙,也就是你必须为自己创建一对密匙,并把公用密匙放在需要访问的服务器上。如果你要连接到SSH服务器上,客户端软件就会向服务器发出请求,请求用你的密匙进行安全验证。服务器收到请求之后,先在你在该服务器的家目录下寻找你的公用密匙,然后把它和你发送过来的公用密匙进行比较。如果两个密匙一致,服务器就用公用密匙加密“质询”(challenge)并把它发送给客户端软件。客户端软件收到“质询”之后就可以用你的私人密匙解密再把它发送给服务器。

用这种方式,你必须知道自己密匙的口令。但是,与第一种级别相比,第二种级别不需要在网络上传送口令。

第二种级别不仅加密所有传送的数据,而且“中间人”这种攻击方式也是不可能的(因为他没有你的私人密匙)。但是整个登录的过程可能需要10秒。

安装并测试OpenSSH
因为受到美国法律的限制,在很多Linux的发行版中都没有包括OpenSSH。但是,可以从网络上下载并安装OpenSSH(有关OpenSSH的安装和配置请参考:http://www.linuxaid.com.cn/engineer/brimmer/html/OpenSSH.htm)。

安装完OpenSSH之后,用下面命令测试一下:

ssh -l [your accountname on the remote host] [address of the remote host]

如果OpenSSH工作正常,你会看到下面的提示信息:

The authenticity of host [hostname] can't be established.
Key fingerprint is 1024 5f:a0:0b:65:d3:82:df:ab:44:62:6d:98:9c:fe:e9:52.
Are you sure you want to continue connecting (yes/no)?

OpenSSH告诉你它不知道这台主机,但是你不用担心这个问题,因为你是第一次登录这台主机。键入“yes”。这将把这台主机的“识别标记”加到“~/.ssh/know_hosts”文件中。第二次访问这台主机的时候就不会再显示这条提示信息了。

然后,SSH提示你输入远程主机上你的帐号的口令。输入完口令之后,就建立了SSH连接,这之后就可以象使用telnet那样使用SSH了。

SSH的密匙
生成你自己的密匙对
生成并分发你自己的密匙有两个好处:

1) 可以防止“中间人”这种攻击方式

2) 可以只用一个口令就登录到所有你想登录的服务器上

用下面的命令可以生成密匙:

ssh-keygen

如果远程主机使用的是SSH 2.x就要用这个命令:

ssh-keygen –d

在同一台主机上同时有SSH1和SSH2的密匙是没有问题的,因为密匙是存成不同的文件的。

ssh-keygen命令运行之后会显示下面的信息:

Generating RSA keys: ............................ooooooO......ooooooO
Key generation complete.
Enter file in which to save the key (/home/[user]/.ssh/identity):
[按下ENTER就行了]
Created directory '/home/[user]/.ssh'.
Enter passphrase (empty for no passphrase):
[输入的口令不会显示在屏幕上]
Enter same passphrase again:
[重新输入一遍口令,如果忘记了口令就只能重新生成一次密匙了]
Your identification has been saved in /home/[user]/.ssh/identity.
[这是你的私人密匙]
Your public key has been saved in /home/[user]/.ssh/identity.pub.
The key fingerprint is: 2a:dc:71:2f:27:84:a2:e4:a1:1e:a9:63:e2:fa:a5:89 [user]@[local machine]

“ssh-keygen –d”做的是几乎同样的事,但是把一对密匙存为(默认情况下)“/home/[user]/.ssh/id_dsa”(私人密匙)和“/home/[user]/.ssh/id_dsa.pub”(公用密匙)。

现在你有一对密匙了:公用密匙要分发到所有你想用ssh登录的远程主机上去;私人密匙要好好地保管防止别人知道你的私人密匙。用“ls –l ~/.ssh/identity”或“ls –l ~/.ssh/id_dsa”所显示的文件的访问权限必须是“-rw-------”。

如果你怀疑自己的密匙已经被别人知道了,不要迟疑马上生成一对新的密匙。当然,你还要重新分发一次公用密匙。

分发公用密匙
在每一个你需要用SSH连接的远程服务器上,你要在自己的家目录下创建一个“.ssh”的子目录,把你的公用密匙“identity.pub” 拷贝到这个目录下并把它重命名为“authorized_keys”。然后执行:

chmod 644 .ssh/authorized_keys

这一步是必不可少的。如果除了你之外别人对“authorized_keys”文件也有写的权限,SSH就不会工作。

如果你想从不同的计算机登录到远程主机,“authorized_keys”文件也可以有多个公用密匙。在这种情况下,必须在新的计算机上重新生成一对密匙,然后把生成的“identify.pub”文件拷贝并粘贴到远程主机的“authorized_keys”文件里。当然在新的计算机上你必须有一个帐号,而且密匙是用口令保护的。有一点很重要,就是当你取消了这个帐号之后,别忘了把这一对密匙删掉。

配置SSH
配置客户端的软件
OpenSSH有三种配置方式:命令行参数、用户配置文件和系统级的配置文件(“/etc/ssh/ssh_config”)。命令行参数优先于配置文件,用户配置文件优先于系统配置文件。所有的命令行的参数都能在配置文件中设置。因为在安装的时候没有默认的用户配置文件,所以要把“/etc/ssh/ssh_config”拷贝并重新命名为“~/.ssh/config”。

标准的配置文件大概是这样的:

[lots of explanations and possible options listed]
# Be paranoid by default
Host *
ForwardAgent no
ForwardX11 no
FallBackToRsh no

还有很多选项的设置可以用“man ssh”查看“CONFIGURATION FILES”这一章。

配置文件是按顺序读取的。先设置的选项先生效。

假定你在www.foobar.com上有一个名为“bilbo”的帐号。而且你要把“ssh-agent”和“ssh-add”结合起来使用并且使用数据压缩来加快传输速度。因为主机名太长了,你懒得输入这么长的名字,用“fbc”作为“www.foobar.com”的简称。你的配置文件可以是这样的:

Host *fbc
HostName www.foobar.com
User bilbo
ForwardAgent yes
Compression yes
# Be paranoid by default
Host *
ForwardAgent no
ForwardX11 no
FallBackToRsh no

你输入“ssh fbc”之后,SSH会自动地从配置文件中找到主机的全名,用你的用户名登录并且用“ssh-agent”管理的密匙进行安全验证。这样很方便吧!

用SSH连接到其它远程计算机用的还是“paranoid(偏执)”默认设置。如果有些选项没有在配置文件或命令行中设置,那么还是使用默认的“paranoid”设置。

在我们上面举的那个例子中,对于到www.foobar.com的SSH连接:“ForwardAgent”和“Compression”被设置为“Yes”;其它的设置选项(如果没有用命令行参数)“ForwardX11”和“FallBackToRsh”都被设置成“No”。

其它还有一些需要仔细看一看的设置选项是:

l CheckHostIP yes

这个选项用来进行IP地址的检查以防止DNS欺骗。

l CompressionLevel

压缩的级别从“1”(最快)到“9”(压缩率最高)。默认值为“6”。

l ForwardX11 yes

为了在本地运行远程的X程序必须设置这个选项。

l LogLevel DEBUG

当SSH出现问题的时候,这选项就很有用了。默认值为“INFO”。

配置服务端的软件
SSH服务器的配置使用的是“/etc/ssh/sshd_config”配置文件,这些选项的设置在配置文件中已经有了一些说明而且用“man sshd”也可以查看帮助。请注意OpenSSH对于SSH 1.x和2.x没有不同的配置文件。

在默认的设置选项中需要注意的有:

l PermitRootLogin yes

最好把这个选项设置成“PermitRootLogin without-password”,这样“root”用户就不能从没有密匙的计算机上登录。把这个选项设置成“no”将禁止“root”用户登录,只能用“su”命令从普通用户转成“root”。

l X11Forwarding no

把这个选项设置成“yes”允许用户运行远程主机上的X程序。就算禁止这个选项也不能提高服务器的安全因为用户可以安装他们自己的转发器(forwarder),请参看“man sshd”。

l PasswordAuthentication yes

把这个选项设置为“no”只允许用户用基于密匙的方式登录。这当然会给那些经常需要从不同主机登录的用户带来麻烦,但是这能够在很大程度上提高系统的安全性。基于口令的登录方式有很大的弱点。

l # Subsystem /usr/local/sbin/sftpd

把最前面的#号去掉并且把路径名设置成“/usr/bin/sftpserv”,用户就能使用“sftp”(安全的FTP)了(sftpserv在sftp软件包中)。因为很多用户对FTP比较熟悉而且“scp”用起来也有一些麻烦,所以“sftp”还是很有用的。而且2.0.7版本以后的图形化的ftp工具“gftp”也支持“sftp”。

拷贝文件
用“scp”拷贝文件
SSH提供了一些命令和shell用来登录远程服务器。在默认情况下它不允许你拷贝文件,但是还是提供了一个“scp”命令。

假定你想把本地计算机当前目录下的一个名为“dumb”的文件拷贝到远程服务器www.foobar.com上你的家目录下。而且你在远程服务器上的帐号名为“bilbo”。可以用这个命令:

scp dumb bilbo@www.foobar.com:.

把文件拷贝回来用这个命令:

scp bilbo@www.foobar.com:dumb .

“scp”调用SSH进行登录,然后拷贝文件,最后调用SSH关闭这个连接。

如果在你的“~/.ssh/config”文件中已经为www.foobar.com做了这样的配置:

Host *fbc
HostName www.foobar.com
User bilbo
ForwardAgent yes

那么你就可以用“fbc”来代替“bilbo@www.foobar.com”,命令就简化为“scp dumb fbc:.”。

“scp”假定你在远程主机上的家目录为你的工作目录。如果你使用相对目录就要相对于家目录。

用“scp”命令的“-r”参数允许递归地拷贝目录。“scp”也可以在两个不同的远程主机之间拷贝文件。

有时候你可能会试图作这样的事:用SSH登录到www.foobar.com上之后,输入命令“scp [local machine]:dumb .”想用它把本地的“dumb”文件拷贝到你当前登录的远程服务器上。这时候你会看到下面的出错信息:

ssh: secure connection to [local machine] refused

之所以会出现这样的出错信息是因为你运行的是远程的“scp”命令,它试图登录到在你本地计算机上运行的SSH服务程序……所以最好在本地运行“scp”除非你的本地计算机也运行SSH服务程序。

用“sftp”拷贝文件
如果你习惯使用ftp的方式拷贝文件,可以试着用“sftp”。“sftp”建立用SSH加密的安全的FTP连接通道,允许使用标准的ftp命令。还有一个好处就是“sftp”允许你通过“exec”命令运行远程的程序。从2.0.7版以后,图形化的ftp客户软件“gftp”就支持“sftp”。

如果远程的服务器没有安装sftp服务器软件“sftpserv”,可以把“sftpserv”的可执行文件拷贝到你的远程的家目录中(或者在远程计算机的$PATH环境变量中设置的路径)。“sftp”会自动激活这个服务软件,你没有必要在远程服务器上有什么特殊的权限。

用“rsync”拷贝文件
“rsync”是用来拷贝、更新和移动远程和本地文件的一个有用的工具,很容易就可以用“-e ssh”参数和SSH结合起来使用。“rsync”的一个优点就是,不会拷贝全部的文件,只会拷贝本地目录和远程目录中有区别的文件。而且它还使用很高效的压缩算法,这样拷贝的速度就很快。

用“加密通道”的ftp拷贝文件
如果你坚持要用传统的FTP客户软件。SSH可以为几乎所有的协议提供“安全通道”。FTP是一个有一点奇怪的协议(例如需要两个端口)而且不同的服务程序和服务程序之间、客户程序和客户程序之间还有一些差别。

实现“加密通道”的方法是使用“端口转发”。你可以把一个没有用到的本地端口(通常大于1000)设置成转发到一个远程服务器上,然后只要连接本地计算机上的这个端口就行了。有一点复杂是吗?

其实一个基本的想法就是,转发一个端口,让SSH在后台运行,用下面的命令:

ssh [user@remote host] -f -L 1234:[remote host]:21 tail -f /etc/motd

接着运行FTP客户,把它设置到指定的端口:

lftp -u [username] -p 1234 localhost

当然,用这种方法很麻烦而且很容易出错。所以最好使用前三种方法。

用SSH设置“加密通道”
“加密通道”的基础知识
SSH的“加密通道”是通过“端口转发”来实现的。你可以在本地端口(没有用到的)和在远程服务器上运行的某个服务的端口之间建立“加密通道”。然后只要连接到本地端口。所有对本地端口的请求都被SSH加密并且转发到远程服务器的端口。当然只有远程服务器上运行SSH服务器软件的时候“加密通道”才能工作。可以用下面命令检查一些远程服务器是否运行SSH服务:

telnet [full name of remote host] 22

如果收到这样的出错信息:

telnet: Unable to connect to remote host: Connection refused

就说明远程服务器上没有运行SSH服务软件。

端口转发使用这样的命令语法:

ssh -f [username@remote host] -L [local port]:[full name of remote host]:[remote port] [some command]

你不仅可以转发多个端口而且可以在“~/.ssh/config”文件中用“LocalForward”设置经常使用的一些转发端口。

为POP加上“加密通道”
你可以用POP协议从服务器上取email。为POP加上“加密通道”可以防止POP的密码被网络监听器(sniffer)监听到。还有一个好处就是SSH的压缩方式可以让邮件传输得更快。

假定你在pop.foobar.com上有一个POP帐号,你的用户名是“bilbo”你的POP口令是“topsecret”。用来建立SSH“加密通道”的命令是:

ssh -f -C bilbo@pop.foobar.com -L 1234:pop.foobar.com:110 sleep 5

(如果要测试,可以把“sleep”的值加到500)。运行这个命令之后会提示你输入POP口令:

bilbo@pop.foobar.com's password:

输入口令之后就可以用“telnet”连接到本地的转发端口了。

telnet localhost 1234

你会收到远程mail服务器的“READY”消息。

当然,这个方法要求你手工输入所有的POP命令,这是很不方便的。可以用Fetchmail(参考how to configure Fetchmail)。Secure POP via SSH mini-HOWTO、man fetchmail和在“/usr/doc/fetchmail-[…]”目录下的Fetchmail的FAQ都提供了一些具体的例子。

请注意IMAP协议使用的是不同的端口:IMAP v2的端口号为143而IMAP v3的端口号为220。

为X加上“加密通道”
如果你打算在本地计算机上运行远程SSH服务器上的X程序,那么登录到远程的计算机上,创建一个名为“~/.ssh/environment”的文件并加上这一行:

XAUTHORITY=/home/[remote user name]/.Xauthority

(如果在远程主机上你的家目录下不存在“.Xauthority”这个文件,那么当用SSH登录的时候就会自动创建)。

比如启动一个X程序(xterm)可以这个命令:

ssh -f -X -l [remote user name] [remote machine] xterm

这将在远程运行xterm这个程序。其它的X程序也是用相同的方法。

为linuxconf加上“加密通道”
Linuxconf是Linux的配置工具,它支持远程管理。Linuxconf的FAQ重说明了如何通过SSH使用linuxconf:

其命令为:

remadmin --exec [link_command] linuxconf --guiproto

如果你想在两台计算机之间用加密的方式传送信息,那么最好用ssh。命令是:

remadmin --exec ssh -l [account] linuxconf --guiproto

这是非常有效的而且运行用图形界面管理计算机。

这种方法需要在客户端安装linuxconf。其它的方法还有直接登录到服务器上用“X11Forwarding”或字符界面运行linuxconf。

为Webmin加上“加密通道”
Webmin是一个新的基于浏览器的配置工具。它运行在1000端口。你可以用SSH的“端口转发”对它进行加密:

ssh -f -l [remote user name] [remote host] -L 1234:[remote host]:10000 tail -f /etc/motd

把浏览器指向

http://localhost:1234

版权说明
这篇文章翻译和改编自:http://www.mandrakeuser.org/secure/index.html。英文版的版权属于“MandrakeSoft SA and LSTB 1999/2000
01 04, 2005
oracle 10g Stream Replication 的新特征
作者 xzh2000 17:44 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
10g Stream Replication 的新特征
 在9iR2中,oracle stream组合advance queuing technique, replication methodology,
 data warehousing, and the event management system等技术;
 在10g中,oracle又增加了一些新的、有用的功能,并改善了stream的配置与管理:
配置改善(Configuration Changes)
 许多配置已经简化啦,提供了更集成的工具,比如简化了授权方法等。
 begin
dbms_streams_auth.grant_admin_privilege(
grantee => 'strmadmin',
grant_privileges => true);
end;
 /
异地捕获(Down Stream Capture)
 它允许将capture process配置在非source database上进行捕获,减轻产品库负载。
 
规则集改善(Rules Set Changes)
 捕获、传播、应用进程可以利用the positive rule set and a negative rule set。
Streams Pool In SGA
为stream 提供了专用的stream buffers,在9iR2中它是分配为shared pool的10%。
 
RAC支持(Support for RAC)
支持RAC的online redo log捕获,减少数据同步时间,
9iR2中capture进程只能捕获RAC的archive redo log。
Migrate from Advanced Replication to Streams
提供了脚本方便将Advanced Replication迁移到Stream。
消息机制(Messaging Mechanism)
 改进并简化了消息的入队与出列,消息通知等功能。
清除队列(Purge Streams Queues)
 完善了9iR2的清除队列与队列表的工具。
begin
dbms_aqadm.purge_queue_table (
queue_table      => 'strmadmin.streams_queue',
purge_condition => 'consumer_name=''sales_apply'' ',
block   => false);
end;
 /

01 04, 2005
这样的SQL需要优化吗
作者 xzh2000 15:12 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流
这样的SQL需要优化吗?
 1 不常用的SQL(executions < 10)
 2 性能恶劣(disk_reads/executeions>1000)
 3 执行时间长(>5second)
  
  系统中每天总有有一些不是很频繁,而物理读/逻辑读都比较大的SQL,
 虽然说有一部分是后台维护时执行的,部分用了bind var,所以调试起来
 不是很方便,只能用explain plan for来解释执行计划.
  偶认为是值得优化的,因为这部分SQL虽然不多,但性能较差,庞大的物
 理读必须会将部分有用的数据交换出去;优化的话,可能要创建一些索引
 之类,同样也会带来一些负面影响......
  
 你认为哪?
01 04, 2005
如何优化含有clob的字段
作者 xzh2000 14:05 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

 环境rhel3 + 9206 + 4G Raw

 a 情况 enable storage in row
 create table test_clob_in(id int,name varchar2(20),clob_1 clob,clob_2 clob);
 alter table test_clob_in modify clob_1 default empty_clob();
 alter table test_clob_in modify clob_2 default empty_clob();
 b 情况 disable storage in row
 create table test_clob_out(id int,name varchar2(20),clob_1 clob,clob_2 clob)
 lob (clob_1) store as (disable storage in row chunk 8k)
 lob (clob_2) store as (disable storage in row chunk 8k);
 alter table test_clob_out modify clob_1 default empty_clob();
 alter table test_clob_out modify clob_2 default empty_clob();
 c 情况 data与clob分两个表
 create table test_clob_1(id int,name varchar2(20));
 create table test_clob_2(id int,clob_1 clob,clob_2 clob);
 alter table test_clob_2 modify clob_1 default empty_clob();
 alter table test_clob_2 modify clob_2 default empty_clob();
 d 情况 data与clob分两个表
 create table test_clob_3(id int,name varchar2(20));
 create table test_clob_4(id int,clob_1 clob,clob_2 clob)
 lob (clob_1) store as (disable storage in row chunk 8k)
 lob (clob_2) store as (disable storage in row chunk 8k);
 alter table test_clob_4 modify clob_1 default empty_clob();
 alter table test_clob_4 modify clob_2 default empty_clob();

 a 测试脚本:
 set timing on
 set time on
 begin
  for i in 1..50000 loop
   insert into test_clob_in values(i,to_char(i),'clob_1'||to_char(i),'clob_2'||to_char(i));
   if mod(i,1000)=0 then
    commit;
   end if;
  end loop;
  commit;
 end;
 /
 PL/SQL procedure successfully completed.
 Elapsed: 00:00:12.50

 b 测试脚本
 begin
  for i in 1..50000 loop
   insert into test_clob_out values(i,to_char(i),'clob_1'||to_char(i),'clob_2'||to_char(i));
   if mod(i,1000)=0 then
    commit;
   end if;
  end loop;
  commit;
 end;
 /
 当lob被disable storage in row时,播入数据极慢,28分钟后,取消测试,
 些时只完成30000条的任务,故不再测试b/d方案(disable store in row).

 c 测试脚本
 begin
  for i in 1..50000 loop
   insert into test_clob_1 values(i,to_char(i));
   insert into test_clob_2 values(i,'clob_1'||to_char(i),'clob_2'||to_char(i));
   if mod(i,1000)=0 then
    commit;
   end if;
  end loop;
  commit;
 end;
 /
 PL/SQL procedure successfully completed.
 Elapsed: 00:00:24.58

 d 测试脚本
 begin
  for i in 1..50000 loop
   insert into test_clob_3 values(i,to_char(i));
   insert into test_clob_4 values(i,'clob_1'||to_char(i),'clob_2'||to_char(i));
   if mod(i,1000)=0 then
    commit;
   end if;
  end loop;
  commit;
 end;
 /
 说明:初步测试后,a/c(enable store in row)方案将进行下一轮测试,

 --刷新buffer cache
 alter session set events 'immediate trace name flush_cache';

 --测试它们的select性能.
 select count(*) from test_clob_in;
  COUNT(*)
 ----------
    50000
 Elapsed: 00:00:00.17
 select count(*) from test_clob_1;
  COUNT(*)
 ----------
    50000
 Elapsed: 00:00:00.01
 
 总结:
  clob在使用disable store in row时对insert性能影响很大,对select影响较小;
  clob在使用enable store in row时与不含clob的表相比,对select影响较大,
  含clob的表,如果不是经常查询clob的值,可以将clob与访问频繁的表分离.

  其实clob的还有一些参数,比如chunk的选择,对存储的影响很大.


01 04, 2005
IBM RS6000巡检步骤[转]
作者 xzh2000 11:08 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

1. IBM RS6000小型机机房要求:
1. 机房的卫生状况,要求清洁,键盘、显示器、机柜上没有灰尘。
2. 温度(摄氏 ℃)
10 ℃-40℃
湿度(%)
8% -80%

2. 设备故障灯分类:
主机故障灯
面板上不能有数字显示,如果有的话,说明系统有故障。
7133磁盘阵列故障灯
告警灯为黄色表示有故障
磁带机故障灯
告警灯为黄色说明有故障或磁带机太脏,须清洗。

3. 系统错误报告(Error Log)的检查:  
硬件故障检测命令:# errpt -d H -T PERM
若有故障执行命令# errpt -a -d H -T PERM>/tmp/harderror.log保存,分析结果报告给客户
软件故障检测命令:# errpt -d S -T PERM
若有故障执行命令# errpt -a -d S -T PERM>/tmp/softerror.log保存,分析结果报告给客户

4. 有否发给root用户的错误报告(mail):          
#mail
1. 观察所有未读消息,注意有关diagela的消息。
2. 常用命令:
h []               Display headings of group containing message
t []          Display messages in or current message.
n                       Display next message.
q                       Quit  
3. 对发现的问题详细分析,结果报告给客户

5. 件系统的检查:
命令:
# df –k
%Used为文件系统的使用率。所有文件系统的使用率不能大于80%

6.磁带机清洁的检查:
命令:
#/usr/lpp/diagnostics/bin/utape -cd rmt0 –n
显示结果为磁带机使用的小时数,若大于72小时,则不论磁带机黄灯是否亮都应用清洁带清洗。

6. 信系统的检测:
1. 网卡的状态
命令:
#ifconfig –a
输出判断:
en0: flags=e080863
inet 192.9.200.2 netmask 0xffffff00 broadcast 192.9.200.255
en1: flags=e080863
inet 192.9.201.1 netmask 0xffffff00 broadcast 192.9.200.255    
主备网卡的flag为UP属正常。同时检查ip地址和netmask是否正确。
2. 路由的检测
命令:
#lsattr –El inet0
authm         65536               Authentication Methods           True
hostname      h24                 Host Name                        True
gateway                           Gateway                          True
route         net,,0,172.16.23.81 Route                            True
bootup_option no                  Serial Optical Network Interface True
rout6                             FDDI Network Interface           True

3. 络的检测
命令:
#ping [ip address]
输出判断:
用ping命令对/etc/hosts文件中的IP地址进行操作,检测网络是否联通。

RAID 的Hotspare 属性是否打开
#smitty ssaraid? Change/Show Attributes of an SSA RAID Array
检查Enable Use of Hot Spares属性是否为YES

8.系统DUMP设置的检查
命令:
#sysdumdev –l
输出判断:
结果应为
primary              /dev/hd6
secondary            /dev/sysdumpnull
copy directory       /var/adm/ras
forced copy flag     TRUE
always allow dump    FALSE
dump compression     OFF
若不正确请用下列命令修改:
#sysdumdev –P –p /dev/hd6 –s /dev/sysdumpnull

9.HACMP 配置检测: Cluster Verification:
命令:
# /usr/sbin/cluster/diag/clconfig -v '-tr'
输出判断:
结果无Fail项输出。

10.系统硬件诊断:
   命令顺序为:
   1.#diag
2.Enter
3.Diagnostic Routines
4.System Verification
5.All Resources
6.F7
输出判断:
结果应为No trouble was found.

11.补丁程序(PTF)的检查    
1. 系统维护补丁版本为ML09,检查命令为:
#instfix –i |grep ML

12.系统参数的检查
1.HIGH water mark for pending write I/Os
# lsattr -El sys0 |grep maxpout
输出判断:
结果应为
maxpout     33      HIGH water mark for pending write I/Os per file   True
2.LOW water mark for pending write I/Os
# lsattr -El sys0|grep minpout
输出判断:
结果应为
minpout     24      LOW water mark for pending write I/Os per file    True
更改命令为:
#chdev -l sys0 -a maxpout='33' -a minpout='24'

3.Syncd参数
# grep syncd /sbin/rc.boot
输出判断:
结果应为
nohup /usr/sbin/syncd 10 > /dev/null 2>&1 &
更改命令为:
#vi /sbin/rc.boot
http://www.uxma.com/sheke/news/pic/8.swf
4.aio参数
# lsdev -Cc aio
输出判断:
结果应为
aio0 Available  Asynchronous I/O
# lsattr -El aio0
输出判断:
结果应为
minservers 1         MINIMUM number of servers                True
maxservers 10        MAXIMUM number of servers                True
maxreqs    4096      Maximum number of REQUESTS               True
kprocprio  39        Server PRIORITY                          True
autoconfig available STATE to be configured at system restart True
fastpath   enable    State of fast path                       True
更改命令为:
#smitty aio

5.Limits文件的设置:
#ulimit –a
输出判断:
结果应为
time(seconds)        unlimited
file(blocks)         2097151
data(kbytes)         262144  //尤其是这项参数
stack(kbytes)        32768
memory(kbytes)       32768
coredump(blocks)     2097151
nofiles(descriptors) 2000
更改命令为:
#vi /etc/security/limits
更改data为524288


31 03, 2005
Oracle Stream复制在24x7中迁移数据的设想
作者 xzh2000 19:09 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

前天听了一个小时的shareplex的产品推介,其中有个地方介绍了用
shareplex在24x7环境下的数据迁移(跨平台);而偶最近也有一个数
据迁移项目要做,共150G,如何才能最短时间完成迁移呢?
现在计划用mview来刷新,如果可以实现的话当然最好;另偶也考虑是
否可以用stream replication来完成数据迁移,其实shareplex的工
作与stream replication的工作机制是一样的,都是基于redo log来
获取数据库的改变,由于stream replication配置时需要短暂的停机,
所以对比起来就没能mview那么有优势.
现在我的设想是:
1 生产库与中间数据库用stream同步数据(需要短暂停机)
2 目标数据库与中间数据库用stream同步数据

大家有什么好的想法一定要告诉我哦.xixi


31 03, 2005
rename与alter table ... rename to ....的区别
作者 xzh2000 09:34 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

rename在功能上与alter table ... rename to是一样的,

区别是:rename ... to ...这个语句在logical standby database与stream replication

上是忽略的;alter table ... rename to却可以在logical standby database与stream

replication 上被apply.


30 03, 2005
oracle stream replication的初步研究[v0.1]
作者 xzh2000 21:14 | Permalink 静态链接网址 | Comments 最新回复 (7) | Trackback 引用 (0) | 技术交流

版面太差了,大家自己去下载吧.这只是在测试机上的测试过程,具体性能数据还待测试,

由于oracle stream是从oracle9iR2才推出的新功能,不稳定也是很正常的,期待在9i的

后续版本会更棒一些.

下载地址:stream[v0.1].rar


29 03, 2005
oracle stream 的又一bug.
作者 xzh2000 19:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
 发现某个实例的apply进程shutdown啦,查dba_apply发现该进程已经是aborted
 状态,查后台alert_sid.log发现报ora-00600错误,查metalink发现是一个bug,
 查udump目录发现有kwqphwmcbk: Source queue name NULL, flag = 0, action = 2
 bug号是2770025.oracle竟然说该错误可以略去.
 select apply_captured,status from dba_apply;
 APP STATUS
 --- --------
 YES ABORTED
 然后只有用exec dbms_apply_adm.start_apply('apply_simp');启动apply进程.
28 03, 2005
Supplemental Log的作用
作者 xzh2000 20:29 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

以前在配置logical standby database时, oracle文档中要求primary database需要添加附加日志:
 alter database add supplemental log data (primary key, unique index) columns;
在配置stream replication时,也要求参与复制的表传输附加日志:
 alter table scott.dept add supplemental log group log_group_dept_pk (id) always;
但总是不太明白supplemental log的作用,总是担心如果不设置,会不会在某种情况下对数据库造成
伤害,昨天看了一天文档,终于在oracle stream replication的online document中找到答案:
大致意思是说:
  如果你的主键或唯一索引是组合的(复合的),就需要为表配置supplemental log,否则就不必,
  也就是说,如果你的所有表的主键是单列的,那你根本就不必去理会它是什么意思.
为什么会这样:
  如果你更新了主键中的部分字段,那supplemental log的作用就是把该记录其余的组成部分的
  数据也传输到目标机,否则目标机就存在不确定性.


28 03, 2005
oracle stream 的一个bug.
作者 xzh2000 19:05 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在"one-to-multi"结构的stream replicaiton中,将job_queue_processes=2以后,

发现测试数据不正确,源测试库提交10000条记录后,目标库中只传播过来4000条左

右,这时监控stream env中的各数据库,相关的进程及视图都正常,然后检查以后dump

目录中的文件,发sid_jxxx_xxxx.trc中的有如下信息:

kwqjswproc: excep After loop: ASSIGNING to self

然后查metalink,发现果然是一个bug.

The information in this document applies to:

Oracle Server - Enterprise Edition - Version: 9.2.0.6
This problem can occur on any platform.

Symptoms

Trace file produced containing message
kwqjswproc: excep After loop: ASSIGNING to self

Cause

There are not enough job queue processes available for job activities.

select * from dba_queue_schedules;
This will indicates queue schedules existing which relate to this message being generated.

If you enable then disable and trace as follow to get more information :

alter system set events '24040 trace name context forever,level 10';
let this run for a little time 5 minutes
then disable this using :
alter system set events '24040 trace name context off';

You will likely see the following :

(from the trace file):
kwqjswproc: job_q_procs is 2
kwqjswproc: aq_procs = 1 ; non_aq_procs = 1
kwqjswproc: system_load = 0 ; avg_load = 0
kwqjswproc: assigning to existing proc
kwqjswproc: OLD assigned proc indx = 1
kwqjswproc: excep After loop: ASSIGNING to self
kwqjswproc: NEW assigned proc indx = 0

The is is a warning message which indicates that should prompt the value of job_queue_processes to
be increased.
ie typically, set job_queue_processes=10

Fix

increase job queue processes as indicated


25 03, 2005
oracle stream replication的测试步骤(one-to-mulit)
作者 xzh2000 19:55 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

oracle stream replication步骤

1 Instance Setup (参与stream replication的实例)
 alter system set job_queue_processes=1;
 alter system set aq_tm_processes=1;
 alter system set global_names=true;
 alter system set compatible='9.2.0' scope=spfile;
 alter system set log_parallelism=1 scope=spfile;
 shutdown immediate;
 startup;
 说明: job_queue_processes与aq_tm_processes最好设置为>2,
    如果想开多个capture进程,需要修改logmnr_max_persistent_sessions参数的值

2 Archive log (源数据库必须为归档状态)
 alter system set log_archive_start=true scope=spfile;
 shutdown immediate;
 startup mount;
 alter database archivelog;
 alter database open;

3 Stream Administrator Setup (在源数据库上创建)
 conn sys/oracle@test45 as sysdba
 create tablespace orastream datafile '/oradata/orastream01.dbf'
 size 100m autoextend on;

 create user strmadmin identified by strmadminpw
 default tablespace orastream quota unlimited on orastream;
 grant connect, resource, select_catalog_role to strmadmin;

 grant execute on dbms_aqadm            to strmadmin;
 grant execute on dbms_capture_adm      to strmadmin;
 grant execute on dbms_propagation_adm  to strmadmin;
 grant execute on dbms_streams_adm      to strmadmin;
 grant execute on dbms_apply_adm        to strmadmin;
 grant execute on dbms_flashback        to strmadmin;

 conn sys/oracle@test45 as sysdba
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_set_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 connect strmadmin/strmadminpw@test45
 exec dbms_streams_adm.set_up_queue();

4 Stream Administrator Setup (在目标数据库上创建)
 conn sys/sys@test44 as sysdba
 create tablespace orastream datafile '/var/oradata/orastream01.dbf'
 size 100m autoextend on;

 create user strmadmin identified by strmadminpw
 default tablespace orastream quota unlimited on orastream;
 grant connect, resource, select_catalog_role to strmadmin;

 grant execute on dbms_aqadm            to strmadmin;
 grant execute on dbms_capture_adm      to strmadmin;
 grant execute on dbms_propagation_adm  to strmadmin;
 grant execute on dbms_streams_adm      to strmadmin;
 grant execute on dbms_apply_adm        to strmadmin;
 grant execute on dbms_flashback        to strmadmin;

 connect sys/sys@test44 as sysdba;
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_set_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 connect strmadmin/strmadminpw@test44;
 exec dbms_streams_adm.set_up_queue();

 conn sys/oracle@test46 as sysdba
 create tablespace orastream datafile '/data2/orastream01.dbf'
 size 100m autoextend on;

 create user strmadmin identified by strmadminpw
 default tablespace orastream quota unlimited on orastream;
 grant connect, resource, select_catalog_role to strmadmin;

 grant execute on dbms_aqadm            to strmadmin;
 grant execute on dbms_capture_adm      to strmadmin;
 grant execute on dbms_propagation_adm  to strmadmin;
 grant execute on dbms_streams_adm      to strmadmin;
 grant execute on dbms_apply_adm        to strmadmin;
 grant execute on dbms_flashback        to strmadmin;

 conn sys/oracle@test46 as sysdba
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_set_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 connect strmadmin/strmadminpw@test46;
 exec dbms_streams_adm.set_up_queue();

 --在test45机器上指向44/46号机器
 connect strmadmin/strmadminpw@test45;
 create database link testdb1 connect to strmadmin identified by strmadminpw using 'test44';
 create database link testdbc connect to strmadmin identified by strmadminpw using 'test46';

 --在test44机器上指向45/46号机器
 connect strmadmin/strmadminpw@test44;
 create database link testdb2 connect to strmadmin identified by strmadminpw using 'test45';
 create database link testdbc connect to strmadmin identified by strmadminpw using 'test46';

 --在test46机器上指向44/45号机器
 connect strmadmin/strmadminpw@test46;
 create database link testdb1 connect to strmadmin identified by strmadminpw using 'test44';
 create database link testdb2 connect to strmadmin identified by strmadminpw using 'test45';
 说明:必须确保双方的数据库链是可以连通.

5 创建测试模式并授权(源数据库与目标数据库都做)
 connect / as sysdba;
 create user scott identified by tiger default tablespace orastream quota unlimited on orastream;
 grant connect,resource to scott;
 
 connect scott/tiger;
 create table dept(id int primary key,name varchar2(20));
 grant all on dept to strmadmin;

6 LogMinor Tablespace Setup(源数据库创建并配置)
 conn sys/oracle@test45 as sysdba;
 create tablespace logmnr datafile '/data2/logmnr01.dbf'
 size 25m reuse autoextend on maxsize unlimited;
 execute dbms_logmnr_d.set_tablespace('logmnr');

7 Supplemental Logging (在源数据库配置)
 conn sys/oracle@test45 as sysdba;
 alter table scott.dept add supplemental log group log_group_dept_pk (id) always;

8 Configure Propagation Process(源数据库配置传播进程)
 connect strmadmin/strmadminpw@test45
 begin
  dbms_streams_adm.add_table_propagation_rules(
   table_name              => 'scott.dept',
   streams_name            => 'test45_to_test46',
   source_queue_name       => 'strmadmin.streams_queue',
   destination_queue_name  => 'strmadmin.streams_queue@testdbc',
   include_dml             =>  true,
   include_ddl             =>  true,
   source_database         => 'testdb2');
 end;
 /
 begin
  dbms_streams_adm.add_table_propagation_rules(
   table_name              => 'scott.dept',
   streams_name            => 'test45_to_test44',
   source_queue_name       => 'strmadmin.streams_queue',
   destination_queue_name  => 'strmadmin.streams_queue@testdb1',
   include_dml             =>  true,
   include_ddl             =>  true,
   source_database         => 'testdb2');
 end;
 /
 set lines 121
 col job format 999
 col what format a36
 select schema_user,job,
   to_char(last_date, 'dd-mon-yyyy hh24:mi:ss') last_date,
   to_char(next_date, 'dd-mon-yyyy hh24:mi:ss') next_date,
   what
 from dba_jobs;

9 Configure Capture Process (源数据库配置捕获进程)
 connect strmadmin/strmadminpw@test45
 begin
  dbms_streams_adm.add_table_rules(
   table_name     => 'scott.dept',  
   streams_type   => 'capture',
   streams_name   => 'capture_simp',
   queue_name     => 'strmadmin.streams_queue',
   include_dml    =>  true,
   include_ddl    =>  true);
 end;
 /
10 Configure Instantiation SCN(源表必须在目标表应用之前被配置)
 exp userid=scott/tiger@test45 FILE=dept_instant.dmp TABLES=dept OBJECT_CONSISTENT=y ROWS=n
 
 imp userid=scott/tiger@test44 FILE=dept_instant.dmp IGNORE=y COMMIT=y LOG=import.log STREAMS_INSTANTIATION=y
 imp userid=scott/tiger@test46 FILE=dept_instant.dmp IGNORE=y COMMIT=y LOG=import.log STREAMS_INSTANTIATION=y

  删除目标数据库的附加日志
 conn sys/sys@test44 as sysdba;
 alter table scott.dept drop supplemental log group log_group_dept_pk;
 conn sys/oracle@test46 as sysdba;
 alter table scott.dept drop supplemental log group log_group_dept_pk;

11 Alternatively the instantiation SCN can be set using the DBMS_APPLY_ADM package:
 connect strmadmin/strmadminpw@test45
 declare
  v_scn number;
 begin
  v_scn := dbms_flashback.get_system_change_number();
  dbms_apply_adm.set_table_instantiation_scn@testdb1(
   source_object_name    => 'scott.dept',
   source_database_name  => 'testdb2',
   instantiation_scn     => v_scn);
  dbms_apply_adm.set_table_instantiation_scn@testdbc(
   source_object_name    => 'scott.dept',
   source_database_name  => 'testdb2',
   instantiation_scn     => v_scn);
 end;
 /

12 Configure Apply Process (目标数据库上配置应用进程)
 connect strmadmin/strmadminpw@test44;
 begin
  dbms_streams_adm.add_table_rules(
   table_name      => 'scott.dept',
   streams_type    => 'apply',
   streams_name    => 'apply_simp',
   queue_name      => 'strmadmin.streams_queue',
   include_dml     =>  true,
   include_ddl     =>  true,
   source_database => 'testdb2');
 end;
 /
 connect strmadmin/strmadminpw@test46;
 begin
  dbms_streams_adm.add_table_rules(
   table_name      => 'scott.dept',
   streams_type    => 'apply',
   streams_name    => 'apply_simp',
   queue_name      => 'strmadmin.streams_queue',
   include_dml     =>  true,
   include_ddl     =>  true,
   source_database => 'testdb2');
 end;
 /
13 Start Apply Process (在目标数据库上启动应用进程)
 connect strmadmin/strmadminpw@test44;
 begin
  dbms_apply_adm.stop_apply(
   apply_name => 'apply_simp');
  dbms_apply_adm.set_parameter(
   apply_name  => 'apply_simp',
   parameter   => 'disable_on_error',
   value       => 'n');
  dbms_apply_adm.start_apply(
   apply_name  => 'apply_simp');
 end;
 /
 connect strmadmin/strmadminpw@test46;
 begin
  dbms_apply_adm.stop_apply(
   apply_name => 'apply_simp');
  dbms_apply_adm.set_parameter(
   apply_name  => 'apply_simp',
   parameter   => 'disable_on_error',
   value       => 'n');
  dbms_apply_adm.start_apply(
   apply_name  => 'apply_simp');
 end;
 /
14 Start Capture Process (在源数据库上启动捕获进程)
 connect strmadmin/strmadminpw@test45
 begin
  dbms_capture_adm.start_capture(
   capture_name  => 'capture_simp');
 end;
 /
15 测试(不支持truncate table...)
 begin
  for i in 1..10000 loop
   insert into dept values(i,to_char(i));
   if mod(i,100)=0 then
    commit;
   end if;
  end loop;
  commit;
 end;
 /
 begin
  for i in 1..10000 loop
   insert into test values(i,to_char(i),sysdate);
   if mod(i,100)=0 then
    commit;
   end if;
  end loop;
  commit;
 end;
 /
 create sequence test_pk;
 create sequence dept_pk;
 create or replace procedure up_test_stream
 as
 begin
  for i in 1..10000 loop
   insert into dept values(dept_pk.nextval,to_char(i));
   insert into test values(dept_pk.nextval,to_char(i),sysdate);
   if mod(i,100)=0 then
    commit;
   end if;
  end loop;
  commit;
 end;
 /
 variable job number;
 exec dbms_job.submit(:job,'up_test_stream;',sysdate,'sysdate+1/14400');

16 清除测试过程
 select s.user_data.gettypename()
 from   streams_queue_table s;

 set serveroutput on
 declare
  v_anydata  sys.anydata;
  v_lcr      sys.lcr$_row_record; 
  v_row_list sys.lcr$_row_list;
  v_result   pls_integer;
 begin
  select user_data
  into   v_anydata
  from   strmadmin.streams_queue_table
  where  rownum < 2;
  v_result := anydata.getobject(
         self  => v_anydata,
         obj   => v_lcr);
  dbms_output.put_line('command type         : ' || v_lcr.get_command_type);
  dbms_output.put_line('object owner         : ' || v_lcr.get_object_owner);
  dbms_output.put_line('object name          : ' || v_lcr.get_object_name);
  dbms_output.put_line('source database name : ' || v_lcr.get_source_database_name);
 end;
 /
 begin
  for cur_rec in (select rule_owner,rule_name from dba_rules) loop
   dbms_rule_adm.drop_rule(
    rule_name => cur_rec.rule_owner || '.' || cur_rec.rule_name,
    force => true);
  end loop;
 end;
 /
 begin
  for cur_rec in (select capture_name from dba_capture) loop
   dbms_capture_adm.stop_capture(
    capture_name => cur_rec.capture_name);
   dbms_capture_adm.drop_capture(
    capture_name => cur_rec.capture_name);
  end loop;
  for cur_rec in (select apply_name from dba_apply) loop
   dbms_apply_adm.stop_apply(
    apply_name => cur_rec.apply_name);
   dbms_apply_adm.drop_apply(
    apply_name => cur_rec.apply_name);
  end loop;
 end;
 /
 connect strmadmin/strmadminpw@test45
 begin
  dbms_streams_adm.purge_source_catalog(
   source_database        => 'testdb2',
   source_object_name     => 'scott.dept',
   source_object_type     => 'table');
 end;
 /
 connect strmadmin/strmadminpw@test45
 begin
  for cur_rec in (select propagation_name from dba_propagation) loop
   dbms_propagation_adm.drop_propagation(cur_rec.propagation_name);
  end loop;
 end;
 /

17 添加其它要传播表(源数据库上添加)
 connect scott/tiger@test45;
 create table test(id int primary key,name varchar2(20),log_time date);
 alter table test add supplemental log group log_group_test_pk (id) always;
 grant all on test to strmadmin;

 connect strmadmin/strmadminpw@test45
 begin
  dbms_streams_adm.add_table_propagation_rules(
   table_name              => 'scott.test',
   streams_name            => 'test45_to_test46',
   source_queue_name       => 'strmadmin.streams_queue',
   destination_queue_name  => 'strmadmin.streams_queue@testdbc',
   include_dml             =>  true,
   include_ddl             =>  true,
   source_database         => 'testdb2');
  dbms_streams_adm.add_table_propagation_rules(
   table_name              => 'scott.test',
   streams_name            => 'test45_to_test44',
   source_queue_name       => 'strmadmin.streams_queue',
   destination_queue_name  => 'strmadmin.streams_queue@testdb1',
   include_dml             =>  true,
   include_ddl             =>  true,
   source_database         => 'testdb2');
  dbms_streams_adm.add_table_rules(
   table_name     => 'scott.test',  
   streams_type   => 'capture',
   streams_name   => 'capture_simp',
   queue_name     => 'strmadmin.streams_queue',
   include_dml    =>  true,
   include_ddl    =>  true);
 end;
 /
 exp userid=scott/tiger@test45 FILE=test_instant.dmp TABLES=test OBJECT_CONSISTENT=y ROWS=n

 imp userid=scott/tiger@test44 FILE=test_instant.dmp IGNORE=y COMMIT=y LOG=import.log STREAMS_INSTANTIATION=y
 imp userid=scott/tiger@test46 FILE=test_instant.dmp IGNORE=y COMMIT=y LOG=import.log STREAMS_INSTANTIATION=y

 conn sys/sys@test44 as sysdba
 alter table scott.test drop supplemental log group log_group_test_pk;
 grant all on scott.test to strmadmin;

 conn sys/oracle@test46 as sysdba
 alter table scott.test drop supplemental log group log_group_test_pk;
 grant all on scott.test to strmadmin;
 
 connect strmadmin/strmadminpw@test45
 declare
  v_scn number;
 begin
  v_scn := dbms_flashback.get_system_change_number();
  dbms_apply_adm.set_table_instantiation_scn@testdbc(
   source_object_name    => 'scott.test',
   source_database_name  => 'testdb2',
   instantiation_scn     => v_scn);
  dbms_apply_adm.set_table_instantiation_scn@testdb1(
   source_object_name    => 'scott.test',
   source_database_name  => 'testdb2',
   instantiation_scn     => v_scn);
 end;
 /
 connect strmadmin/strmadminpw@test44;
 begin
  dbms_streams_adm.add_table_rules(
   table_name      => 'scott.test',
   streams_type    => 'apply',
   streams_name    => 'apply_simp',
   queue_name      => 'strmadmin.streams_queue',
   include_dml     =>  true,
   include_ddl     =>  true,
   source_database => 'testdb2');
 end;
 /
 connect strmadmin/strmadminpw@test46;
 begin
  dbms_streams_adm.add_table_rules(
   table_name      => 'scott.test',
   streams_type    => 'apply',
   streams_name    => 'apply_simp',
   queue_name      => 'strmadmin.streams_queue',
   include_dml     =>  true,
   include_ddl     =>  true,
   source_database => 'testdb2');
 end;
 /
18 事务在master size如何传播到其它多站点?
 begin
  dbms_streams_adm.add_schema_propagation_rules(
   schema_name               => 'hr',
   streams_name              => 'mult1_to_mult2',   
   source_queue_name         => 'strmadmin.streams_queue',
   destination_queue_name    => 'strmadmin.streams_queue@mult2.net',
   include_dml               =>  true,
   include_ddl               =>  true,
   source_database           => 'mult1.net');
 end;
 /
 begin
  dbms_streams_adm.add_schema_propagation_rules(
   schema_name               => 'hr',
   streams_name              => 'mult1_to_mult3',   
   source_queue_name         => 'strmadmin.streams_queue',
   destination_queue_name    => 'strmadmin.streams_queue@mult3.net',
   include_dml               =>  true,
   include_ddl               =>  true,
   source_database           => 'mult1.net');
 end;
 /

19 多站点传播对master site的性能影响如何?
 待测试

20 如果多站点中某个复制失败该如何处理?
 待测试

21 在进行stream replication时的package.
 dbms_streams_adm package
 dbms_capture_adm package
 dbms_propagation_adm package
 dbms_apply_adm package
 dbms_rule_adm package
 dbms_rule package
 dbms_streams package

22 如何对stream replication进行监控?
 all_apply
  dba_apply
 all_apply_conflict_columns
  dba_apply_conflict_columns
 all_apply_dml_handlers
  dba_apply_dml_handlers
 all_apply_error
  dba_apply_error
 no all_ view
  dba_apply_instantiated_objects
 all_apply_key_columns
  dba_apply_key_columns
 all_apply_parameters
  dba_apply_parameters
 all_apply_progress
  dba_apply_progress
 all_capture
  dba_capture
 all_capture_parameters
  dba_capture_parameters
 all_capture_prepared_database
  dba_capture_prepared_database
 all_capture_prepared_schemas
  dba_capture_prepared_schemas
 all_capture_prepared_tables
  dba_capture_prepared_tables
 all_evaluation_context_tables
  dba_evaluation_context_tables
  user_evaluation_context_tables
 all_evaluation_context_vars
  dba_evaluation_context_vars
  user_evaluation_context_vars
 all_evaluation_contexts
  dba_evaluation_contexts
  user_evaluation_contexts
 all_propagation
  dba_propagation
 all_rule_set_rules
  dba_rule_set_rules
  user_rule_set_rules
 all_rule_sets
  dba_rule_sets
  user_rule_sets
 all_rules
  dba_rules
  user_rules
 all_streams_global_rules
  dba_streams_global_rules
 all_streams_schema_rules
  dba_streams_schema_rules
 all_streams_table_rules
  dba_streams_table_rules

23 在stream monitor中的动态性能视图
 v$streams_apply_coordinator
 v$streams_apply_reader
 v$streams_apply_server
 v$streams_capture

24 高级复制与流复制的区别?
 高级复制是基于mv刷新机制
 流复制是基于logmnr+aq的sql apply机制

25 流复制于逻辑备用库的区别?
 流复制数据可以被updated,逻辑备用库不可以
 流复制可以基于异构平台,逻辑备用库不可以
 流复制可以与主站点有不同的字符集,逻辑备用库不可以
 挖掘online log以减少传播时间
 流复制可以有多于10份的拷贝,逻辑备用库不可以
 流复制一次捕获LCRs,将可以发送到多个站点
 流与逻辑备用库不可共存,如果希望他们共存,必须用Streams APIs创建与维护逻辑备用库.
 Standby SQL apply mode and Streams are not supported on the same database.
 RAC中的流复制只能从archived log中miner sql.

26 Best Practices for Streams High Availability Environments
 Configuring Streams for High Availability
  Directly Connecting Every Database to Every Other Database
  Creating Hub and Spoke Configurations
  Configuring Oracle Real Application Clusters with Streams
 Recovering from Failures
  Reestablishing Database Links After a Failover
  Restarting Capture After a Failover
  Restarting Propagation After a Failover
  Restarting Apply After a Failover

27 检测正在进行捕获的表
 column table_owner heading 'table owner' format a15
 column table_name heading 'table name' format a15
 column scn heading 'instantiation scn' format 999999999999
 column timestamp heading 'time ready for|instantiation'
 select table_owner,
     table_name,
     scn,
     to_char(timestamp, 'hh24:mi:ss mm/dd/yy') timestamp
 from dba_capture_prepared_tables;

 column log_group_name heading 'log group' format a20
 column table_name heading 'table' format a20
 column always heading 'type of log group' format a30
 select log_group_name,table_name,
  decode(always,'always','unconditional',null,'conditional') always
 from dba_log_groups;

 column owner heading 'owner' format a10
 column name heading 'queue name' format a25
 column queue_table heading 'queue table' format a20
 column user_comment heading 'comment' format a20
 select q.owner,q.name,t.queue_table,q.user_comment
 from dba_queues q, dba_queue_tables t
 where t.object_type = 'sys.anydata' and q.queue_table = t.queue_table and q.owner = t.owner;

 column 'source queue' format a35
 column 'destination queue' format a35
 select p.source_queue_owner ||'.'||
     p.source_queue_name ||'@'||
     g.global_name "source queue",
     p.destination_queue_owner ||'.'||
     p.destination_queue_name ||'@'||
     p.destination_dblink "destination queue"
 from dba_propagation p, global_name g
 where propagation_name = upper('test45_to_test44');

28 如果完全清除流复制的字典信息
 col object_name format a32
 select object_name from dba_objects where object_name like '%APPLY%' and object_type='TABLE';
 select object_name from dba_objects where object_name like '%STREAM%' and object_type='TABLE';
 清除SYS中的字典表中的信息即可.

29 ORA-26701: STREAMS process APPLY_XXX不存在的处理
 -- remove all the rules associated with the apply process
 begin
 dbms_streams_adm.remove_rule(
 rule_name => null,
 streams_type => 'apply',
 streams_name => 'APPLY_SIMP');
 end;
 /
 -- stop the apply process.
 begin
 dbms_apply_adm.stop_apply(
 apply_name => 'apply_simp',
 force => true);
 end;
 /
 -- drop the apply process.
 begin
 dbms_apply_adm.drop_apply(apply_name => 'apply_simp');
 end;

30 ORA-26666: cannot alter STREAMS process APPLY_SIMP的处理方法
 connect strmadmin/strmadminpw@test46;
 begin
  dbms_apply_adm.stop_apply(
   apply_name => 'apply_simp');
  dbms_apply_adm.set_parameter(
   apply_name  => 'apply_simp',
   parameter   => 'disable_on_error',
   value       => 'n');
  dbms_apply_adm.start_apply(
   apply_name  => 'apply_simp');
 end;
 /


25 03, 2005
oracle stream replication的测试步骤(one-to-one)
作者 xzh2000 08:43 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

oracle stream replication步骤

1 Instance Setup (参与stream replication的实例)
 alter system set job_queue_processes=1;
 alter system set aq_tm_processes=1;
 alter system set global_names=true;
 alter system set compatible='9.2.0' scope=spfile;
 alter system set log_parallelism=1 scope=spfile;
 shutdown immediate;
 startup;

2 Archive log (源数据库必须为归档状态)
 alter system set log_archive_start=true scope=spfile;
 shutdown immediate;
 startup mount;
 alter database archivelog;
 alter database open;

3 Stream Administrator Setup (在源数据库上创建)
 conn sys/oracle@test45 as sysdba
 create tablespace orastream datafile '/oradata/orastream01.dbf'
 size 100m autoextend on;

 create user strmadmin identified by strmadminpw
 default tablespace orastream quota unlimited on orastream;
 grant connect, resource, select_catalog_role to strmadmin;

 grant execute on dbms_aqadm            to strmadmin;
 grant execute on dbms_capture_adm      to strmadmin;
 grant execute on dbms_propagation_adm  to strmadmin;
 grant execute on dbms_streams_adm      to strmadmin;
 grant execute on dbms_apply_adm        to strmadmin;
 grant execute on dbms_flashback        to strmadmin;

 conn sys/oracle@test45 as sysdba
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_set_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 connect strmadmin/strmadminpw@test45
 exec dbms_streams_adm.set_up_queue();

 create database link testdbc connect to strmadmin identified by strmadminpw using 'testdbc'

4 Stream Administrator Setup (在目标数据库上创建)
 conn sys/oracle@test46 as sysdba
 create tablespace orastream datafile '/data2/orastream01.dbf'
 size 100m autoextend on;

 conn sys/oracle@test46 as sysdba
 create user strmadmin identified by strmadminpw
 default tablespace orastream quota unlimited on orastream;
 grant connect, resource, select_catalog_role to strmadmin;

 grant execute on dbms_aqadm            to strmadmin;
 grant execute on dbms_capture_adm      to strmadmin;
 grant execute on dbms_propagation_adm  to strmadmin;
 grant execute on dbms_streams_adm      to strmadmin;
 grant execute on dbms_apply_adm        to strmadmin;
 grant execute on dbms_flashback        to strmadmin;

 conn sys/oracle@test46 as sysdba
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_set_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 begin
  dbms_rule_adm.grant_system_privilege(
   privilege    => dbms_rule_adm.create_rule_obj,
   grantee      => 'strmadmin',
   grant_option => false);
 end;
 /
 connect strmadmin/strmadminpw@test46;
 exec dbms_streams_adm.set_up_queue();

 create database link testdb2 connect to strmadmin identified by strmadminpw using 'testdb2'
 说明:必须确保双方的数据库链是可以连通.

5 创建测试模式并授权(源数据库与目标数据库都做)
 connect / as sysdba;
 create user scott identified by tiger default tablespace orastream quota unlimited on orastream;
 grant connect,resource to scott;
 
 connect scott/tiger;
 create table dept(id int primary key,name varchar2(20));
 grant all on dept to strmadmin;

6 LogMinor Tablespace Setup(源数据库创建并配置)
 conn sys/oracle@test45 as sysdba;
 create tablespace logmnr datafile '/data2/logmnr01.dbf'
 size 25m reuse autoextend on maxsize unlimited;
 execute dbms_logmnr_d.set_tablespace('logmnr');

7 Supplemental Logging (在源数据库配置)
 conn sys/oracle@test45 as sysdba;
 alter table scott.dept add supplemental log group log_group_dept_pk (id) always;

8 Configure Propagation Process(源数据库配置传播进程)
 connect strmadmin/strmadminpw@test45
 begin
  dbms_streams_adm.add_table_propagation_rules(
   table_name              => 'scott.dept',
   streams_name            => 'test45_to_test46',
   source_queue_name       => 'strmadmin.streams_queue',
   destination_queue_name  => 'strmadmin.streams_queue@testdbc',
   include_dml             =>  true,
   include_ddl             =>  true,
   source_database         => 'testdb2');
 end;
 /
 set lines 121
 col job format 999
 col what format a36
 select schema_user,job,
   to_char(last_date, 'dd-mon-yyyy hh24:mi:ss') last_date,
   to_char(next_date, 'dd-mon-yyyy hh24:mi:ss') next_date,
   what
 from dba_jobs;

 如何删除已经添加的传播规则?
 begin
  dbms_propagation_adm.drop_propagation(propagation_name =>'test46_to_test45');
 end;
 /   
9 Configure Capture Process (源数据库配置捕获进程)
 connect strmadmin/strmadminpw@test45
 begin
  dbms_streams_adm.add_table_rules(
   table_name     => 'scott.dept',  
   streams_type   => 'capture',
   streams_name   => 'capture_simp',
   queue_name     => 'strmadmin.streams_queue',
   include_dml    =>  true,
   include_ddl    =>  true);
 end;
 /
10 Configure Instantiation SCN(源表必须在目标表应用之前被配置)
 exp userid=scott/tiger@test45 FILE=dept_instant.dmp TABLES=dept OBJECT_CONSISTENT=y ROWS=n
 imp userid=scott/tiger@test46 FILE=dept_instant.dmp IGNORE=y COMMIT=y LOG=import.log STREAMS_INSTANTIATION=y

  删除目标数据库的附加日志
 conn sys/oracle@test46 as sysdba
 alter table scott.dept drop supplemental log group log_group_dept_pk;

11 Alternatively the instantiation SCN can be set using the DBMS_APPLY_ADM package:
 connect strmadmin/strmadminpw@test45
 declare
  v_scn number;
 begin
  v_scn := dbms_flashback.get_system_change_number();
  dbms_apply_adm.set_table_instantiation_scn@testdbc(
   source_object_name    => 'scott.dept',
   source_database_name  => 'testdb2',
   instantiation_scn     => v_scn);
 end;
 /
12 Configure Apply Process (目标数据库上配置应用进程)
 connect strmadmin/strmadminpw@test46;
 begin
  dbms_streams_adm.add_table_rules(
   table_name      => 'scott.dept',
   streams_type    => 'apply',
   streams_name    => 'apply_simp',
   queue_name      => 'strmadmin.streams_queue',
   include_dml     =>  true,
   include_ddl     =>  true,
   source_database => 'testdb2');
 end;
 /
13 Start Apply Process (在目标数据库上启动应用进程)
 connect strmadmin/strmadminpw@test46;
 begin
  dbms_apply_adm.set_parameter(
   apply_name  => 'apply_simp',
   parameter   => 'disable_on_error',
   value       => 'n');
  dbms_apply_adm.start_apply(
   apply_name  => 'apply_simp');
 end;
 /
14 Start Capture Process (在源数据库上启动捕获进程)
 connect strmadmin/strmadminpw@test45
 begin
  dbms_capture_adm.start_capture(
   capture_name  => 'capture_simp');
 end;
 /
15 测试(不支持truncate table...)
 begin
  for i in 1..10000 loop
   insert into dept values(i,to_char(i));
   if mod(i,100)=0 then
    commit;
   end if;
  end loop;
  commit;
 end;

 create sequence test_pk;
 create sequence dept_pk;
 create or replace procedure up_test_stream
 as
 begin
  for i in 1..10000 loop
   insert into dept values(dept_pk.nextval,to_char(i));
   insert into test values(dept_pk.nextval,to_char(i),sysdate);
   if mod(i,100)=0 then
    commit;
   end if;
  end loop;
  commit;
 end;
 /
 variable job number;
 exec dbms_job.submit(:job,'up_test_stream;',sysdate,'sysdate+1/14400');

16 清除测试过程
 select s.user_data.gettypename()
 from   streams_queue_table s;

 set serveroutput on
 declare
  v_anydata  sys.anydata;
  v_lcr      sys.lcr$_row_record; 
  v_row_list sys.lcr$_row_list;
  v_result   pls_integer;
 begin
  select user_data
  into   v_anydata
  from   strmadmin.streams_queue_table
  where  rownum < 2;
  v_result := anydata.getobject(
         self  => v_anydata,
         obj   => v_lcr);
  dbms_output.put_line('command type         : ' || v_lcr.get_command_type);
  dbms_output.put_line('object owner         : ' || v_lcr.get_object_owner);
  dbms_output.put_line('object name          : ' || v_lcr.get_object_name);
  dbms_output.put_line('source database name : ' || v_lcr.get_source_database_name);
 end;
 /
 begin
  for cur_rec in (select rule_owner, rule_name from dba_rules) loop
   dbms_rule_adm.drop_rule(
    rule_name => cur_rec.rule_owner || '.' || cur_rec.rule_name,
    force => true);
  end loop;
 end;
 /
 begin
  for cur_rec in (select capture_name from dba_capture) loop
   dbms_capture_adm.stop_capture(
    capture_name => cur_rec.capture_name);
   dbms_capture_adm.drop_capture(
    capture_name => cur_rec.capture_name);
  end loop;
  for cur_rec in (select apply_name from dba_apply) loop
   dbms_apply_adm.stop_apply(
    apply_name => cur_rec.apply_name);
   dbms_apply_adm.drop_apply(
    apply_name => cur_rec.apply_name);
  end loop;
 end;
 /
 begin
  dbms_streams_adm.purge_source_catalog(
   source_database        => 'testdbc',
   source_object_name     => 'scott.dept',
   source_object_type     => 'table');
 end;
 /

17 添加其它要传播表(源数据库上添加)
 connect scott/tiger@test45;
 create table test(id int primary key,name varchar2(20),log_time date);
 alter table test add supplemental log group log_group_test_pk (id) always;
 grant all on test to strmadin;

 connect strmadmin/strmadminpw@test45
 begin
  dbms_streams_adm.add_table_propagation_rules(
   table_name              => 'scott.test',
   streams_name            => 'test45_to_test46',
   source_queue_name       => 'strmadmin.streams_queue',
   destination_queue_name  => 'strmadmin.streams_queue@testdbc',
   include_dml             =>  true,
   include_ddl             =>  true,
   source_database         => 'testdb2');
 end;
 /
 connect strmadmin/strmadminpw@test45
 begin
  dbms_streams_adm.add_table_rules(
   table_name     => 'scott.test',  
   streams_type   => 'capture',
   streams_name   => 'capture_simp',
   queue_name     => 'strmadmin.streams_queue',
   include_dml    =>  true,
   include_ddl    =>  true);
 end;
 /
 exp userid=scott/tiger@test45 FILE=test_instant.dmp TABLES=test OBJECT_CONSISTENT=y ROWS=n
 imp userid=scott/tiger@test46 FILE=test_instant.dmp IGNORE=y COMMIT=y LOG=import.log STREAMS_INSTANTIATION=y FULL=y

 conn sys/oracle@test46 as sysdba
 alter table scott.test drop supplemental log group log_group_test_pk;
 grant all on test to strmadmin;

 connect strmadmin/strmadminpw@test45
 declare
  v_scn number;
 begin
  v_scn := dbms_flashback.get_system_change_number();
  dbms_apply_adm.set_table_instantiation_scn@testdbc(
   source_object_name    => 'scott.test',
   source_database_name  => 'testdb2',
   instantiation_scn     => v_scn);
 end;
 /
 connect strmadmin/strmadminpw@test46;
 begin
  dbms_streams_adm.add_table_rules(
   table_name      => 'scott.test',
   streams_type    => 'apply',
   streams_name    => 'apply_simp',
   queue_name      => 'strmadmin.streams_queue',
   include_dml     =>  true,
   include_ddl     =>  true,
   source_database => 'testdb2');
 end;
 /

18 事务在master size如何传播到其它多站点?
 begin
  dbms_streams_adm.add_schema_propagation_rules(
   schema_name               => 'hr',
   streams_name              => 'mult1_to_mult2',   
   source_queue_name         => 'strmadmin.streams_queue',
   destination_queue_name    => 'strmadmin.streams_queue@mult2.net',
   include_dml               =>  true,
   include_ddl               =>  true,
   source_database           => 'mult1.net');
 end;
 /
 begin
  dbms_streams_adm.add_schema_propagation_rules(
   schema_name               => 'hr',
   streams_name              => 'mult1_to_mult3',   
   source_queue_name         => 'strmadmin.streams_queue',
   destination_queue_name    => 'strmadmin.streams_queue@mult3.net',
   include_dml               =>  true,
   include_ddl               =>  true,
   source_database           => 'mult1.net');
 end;
 /

19 多站点传播对master site的性能影响如何?
 待测试

20 如果多站点中某个复制失败该如何处理?
 待测试

21 在进行stream replication时的package.
 dbms_streams_adm package
 dbms_capture_adm package
 dbms_propagation_adm package
 dbms_apply_adm package
 dbms_rule_adm package
 dbms_rule package
 dbms_streams package

22 如何对stream replication进行监控?
 all_apply
  dba_apply
 all_apply_conflict_columns
  dba_apply_conflict_columns
 all_apply_dml_handlers
  dba_apply_dml_handlers
 all_apply_error
  dba_apply_error
 no all_ view
  dba_apply_instantiated_objects
 all_apply_key_columns
  dba_apply_key_columns
 all_apply_parameters
  dba_apply_parameters
 all_apply_progress
  dba_apply_progress
 all_capture
  dba_capture
 all_capture_parameters
  dba_capture_parameters
 all_capture_prepared_database
  dba_capture_prepared_database
 all_capture_prepared_schemas
  dba_capture_prepared_schemas
 all_capture_prepared_tables
  dba_capture_prepared_tables
 all_evaluation_context_tables
  dba_evaluation_context_tables
  user_evaluation_context_tables
 all_evaluation_context_vars
  dba_evaluation_context_vars
  user_evaluation_context_vars
 all_evaluation_contexts
  dba_evaluation_contexts
  user_evaluation_contexts
 all_propagation
  dba_propagation
 all_rule_set_rules
  dba_rule_set_rules
  user_rule_set_rules
 all_rule_sets
  dba_rule_sets
  user_rule_sets
 all_rules
  dba_rules
  user_rules
 all_streams_global_rules
  dba_streams_global_rules
 all_streams_schema_rules
  dba_streams_schema_rules
 all_streams_table_rules
  dba_streams_table_rules

23 在stream monitor中的动态性能视图
 v$streams_apply_coordinator
 v$streams_apply_reader
 v$streams_apply_server
 v$streams_capture

24 高级复制与流复制的区别?
 高级复制是基于mv刷新机制
 流复制是基于logmnr+aq的sql apply机制

25 流复制于逻辑备用库的区别?
 流复制数据可以被updated,逻辑备用库不可以
 流复制可以基于异构平台,逻辑备用库不可以
 流复制可以与主站点有不同的字符集,逻辑备用库不可以
 挖掘online log以减少传播时间
 流复制可以有多于10份的拷贝,逻辑备用库不可以
 流复制一次捕获LCRs,将可以发送到多个站点
 流与逻辑备用库不可共存,如果希望他们共存,必须用Streams APIs创建与维护逻辑备用库.
 Standby SQL apply mode and Streams are not supported on the same database.
 RAC中的流复制只能从archived log中miner sql.

26 Best Practices for Streams High Availability Environments
 Configuring Streams for High Availability
  Directly Connecting Every Database to Every Other Database
  Creating Hub and Spoke Configurations
  Configuring Oracle Real Application Clusters with Streams
 Recovering from Failures
  Reestablishing Database Links After a Failover
  Restarting Capture After a Failover
  Restarting Propagation After a Failover
  Restarting Apply After a Failover

27 检测正在进行捕获的表
 column table_owner heading 'table owner' format a15
 column table_name heading 'table name' format a15
 column scn heading 'instantiation scn' format 999999999999
 column timestamp heading 'time ready for|instantiation'
 select table_owner,
     table_name,
     scn,
     to_char(timestamp, 'hh24:mi:ss mm/dd/yy') timestamp
 from dba_capture_prepared_tables;

 column log_group_name heading 'log group' format a20
 column table_name heading 'table' format a20
 column always heading 'type of log group' format a30
 select log_group_name,table_name,
  decode(always,'always','unconditional',null,'conditional') always
 from dba_log_groups;

 column owner heading 'owner' format a10
 column name heading 'queue name' format a25
 column queue_table heading 'queue table' format a20
 column user_comment heading 'comment' format a20
 select q.owner, q.name, t.queue_table, q.user_comment
 from dba_queues q, dba_queue_tables t
 where t.object_type = 'sys.anydata'
 and q.queue_table = t.queue_table and q.owner = t.owner;

 column 'source queue' format a35
 column 'destination queue' format a35
 select p.source_queue_owner ||'.'||
     p.source_queue_name ||'@'||
     g.global_name "source queue",
     p.destination_queue_owner ||'.'||
     p.destination_queue_name ||'@'||
     p.destination_dblink "destination queue"
 from dba_propagation p, global_name g
 where propagation_name = upper('test45_to_test46');


 


22 03, 2005
一次standby的可耻经历
作者 xzh2000 19:54 | Permalink 静态链接网址 | Comments 最新回复 (6) | Trackback 引用 (0) | 技术交流

前天为一台双节点的RAC做DataGuard,用Rman将数据文件拷
到目标位置后,就启动standby实例并mount在standby状态,
然后将standby机进行recover managed standby状态.

然后配置主从三台机器的tns,配置完毕后,进入rac的node1,
发现该RAC已经有一个standby机啦,暂以db212为代号吧,所以
偶就理所当然地去修改log_archive_dest_3.
ALTER SYSTEM SET log_archive_dest_3='SERVICE=db213'
修改完后查alter_sid.log文件发现一个错误:
ORA-16040: standby destination archive log file is locked

第一感觉是db212/db213接收RAC归档的路径重复啦,然检查
db212/db213之后发现,它们都指向各自的本地路径.然后又
检查n次,确保不是路径的问题.

将log_archive_dest_2的db212换成db213,发现归档依然被归
档到db212的机器上,基本上也就排除了归档路径设置的问题.

这时只好将相关的机器的初始参数一个个查看,终于发现db212
竟然设置了local_listener与remore_listener,它的remote
listerner恰巧就是db213的监听地址.

也就是说RAC每次归档时,都被db212响应啦......


22 03, 2005
ORA-02085的解决办法
作者 xzh2000 19:31 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

QL> connect scott/tiger
Connected.
SQL> desc a1@testdbc
ERROR:
ORA-02085: database link TESTDBC connects to TESTDB1

SQL> host oerr ora 2085
02085, 00000, "database link %s connects to %s"
// *Cause: a database link connected to a database with a different name.
//  The connection is rejected.
// *Action: create a database link with the same name as the database it
//  connects to, or set global_names=false.

实际上在网络中已经没有叫TESTDB1的数据库啦,但由于该db_name
以前是TESTDB1,后来用nid修改db_name为TESTDBC,结果每次测试
db link时还是要求连接到修改前的数据库名.
查metalink,发现global_name字典中的停息并没有被一起修改
SQL> select * from global_name;
GLOBAL_NAME
-------------------------------
TESTDB1
用alter database rename global_name to TESTDBC;
然后再用desc a1@testdbc测试,一切正常.

http://metalink.oracle.com/metalink/plsql/ml2_gui.startup


22 03, 2005
nid使用注意事项
作者 xzh2000 19:20 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

nid
DBNEWID: Release 9.2.0.6.0 - Production
Copyright (c) 1995, 2002, Oracle Corporation.  All rights reserved.

Keyword     Description                    (Default)
----------------------------------------------------
TARGET      Username/Password              (NONE)
DBNAME      New database name              (NONE)
LOGFILE     Output Log                     (NONE)
REVERT      Revert failed change           NO
SETNAME     Set a new database name only   NO
APPEND      Append to output log           NO
HELP        Displays these messages        NO
通常情况下,如果你用nid修改了db_name,然后你可以用revert=y来取消,
如果某文件没有扩展名,该文件将不可以被打开.且不可以用revert=y来取消

NID-00100: Cannot open datafile "/opt/oradata/testdb2/tbs_auc_p1_2"

这时只有mount状态alter database datafile ..... offline drop,打开数据库,
所以在用nid修改db_name时,一定要注意做好备份,否则就可能会造成数据丢失.


21 03, 2005
Oracle Stream 资料[转]
作者 xzh2000 15:23 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Streams
Oracle Streams are a generic mechanism for sharing data which can be used as the basis of many processes including messaging, replication and warehouse ETL processes. They are an extension of a number of existing technologies including Advanced Queuing, LogMinor and Job Scheduling. This article presents a simple replication scenario as an example of their use:

http://www.oracle-base.com/articles/9i/Streams9i.php

Architecture
Instance Setup
Stream Administrator Setup
LogMinor Tablespace Setup
Supplemental Logging
Configure Propagation Process
Configure Capture Process
Configure Instantiation SCN
Configure Apply Process
Start Apply Process
Start Capture Process
Test It
Clean Up
Basic Architecture

The processing of streams is divided into three main processes (Capture, Staging and Apply):

The capture process is an optional background process that mines DDL and DML changes from the redo logs and wraps them up as Logical Change Records (LCRs). In addition to the default capture mechanism user defined events can be enqueued directly.
Staging involves storing the LCRs in queues of datatype SYS.AnyData. LCRs can be propogated between a source and destination staging area in different databases if necessary. Propagation is scheduled using job queues.
The apply process is an optional background process that dequeues LCRs and either applies them directly or for user-defined messages passes them as parameters to user-defined packages.
Both the capture and apply processes can use table, schema and database level rules to determine their actions.

Instance Setup
In order to begin the following parameters should be set in the spfiles of participating databases:

ALTER SYSTEM SET JOB_QUEUE_PROCESSES=1;
ALTER SYSTEM SET AQ_TM_PROCESSES=1;
ALTER SYSTEM SET GLOBAL_NAMES=TRUE;
ALTER SYSTEM SET COMPATIBLE='9.2.0' SCOPE=SPFILE;
ALTER SYSTEM SET LOG_PARALLELISM=1 SCOPE=SPFILE;
SHUTDOWN IMMEDIATE;
STARTUP;
In addition, any databases involved in capture (DBA1) must be in ARCHIVELOG mode.

Stream Administrator Setup
Next we create a stream administrator, a stream queue table and a database link on the source database:

CONN sys/password@DBA1 AS SYSDBA

CREATE USER strmadmin IDENTIFIED BY strmadminpw
DEFAULT TABLESPACE users QUOTA UNLIMITED ON users;

GRANT CONNECT, RESOURCE, SELECT_CATALOG_ROLE TO strmadmin;

GRANT EXECUTE ON DBMS_AQADM            TO strmadmin;
GRANT EXECUTE ON DBMS_CAPTURE_ADM      TO strmadmin;
GRANT EXECUTE ON DBMS_PROPAGATION_ADM  TO strmadmin;
GRANT EXECUTE ON DBMS_STREAMS_ADM      TO strmadmin;
GRANT EXECUTE ON DBMS_APPLY_ADM        TO strmadmin;
GRANT EXECUTE ON DBMS_FLASHBACK        TO strmadmin;

BEGIN
  DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
    privilege    => DBMS_RULE_ADM.CREATE_RULE_SET_OBJ,
    grantee      => 'strmadmin',
    grant_option => FALSE);
END;
/

BEGIN
  DBMS_RULE_ADM.GRANT_SYSTEM_PRIVILEGE(
    privilege    => DBMS_RULE_ADM.CREATE_RULE_OBJ,
    grantee      => 'strmadmin',
    grant_option => FALSE);
END;
/

CONNECT strmadmin/strmadminpw@DBA1
EXEC DBMS_STREAMS_ADM.SET_UP_QUEUE();

CREATE DATABASE LINK dba2 CONNECT TO strmadmin IDENTIFIED BY strmadminpw USING 'DBA2';
This process must be repeated on the destination database (DBA2). The reverse database link is not necessary in this example but the following grant must be added:

GRANT ALL ON scott.dept TO strmadmin;
LogMinor Tablespace Setup
Next we create a new tablespace to hold the logminor tables on the source database:

CONN sys/password@DBA1 AS SYSDBA

CREATE TABLESPACE logmnr_ts DATAFILE '/u01/app/oracle/oradata/DBA1/logmnr01.dbf'
  SIZE 25 M REUSE AUTOEXTEND ON MAXSIZE UNLIMITED;
  
EXECUTE DBMS_LOGMNR_D.SET_TABLESPACE('logmnr_ts');
Supplemental Logging
The apply process requires additional information for some actions so we must configure suplimental logging of primary key information for tables of interest:

CONN sys/password@DBA1 AS SYSDBA
ALTER TABLE scott.dept ADD SUPPLEMENTAL LOG GROUP log_group_dept_pk (deptno) ALWAYS;
Configure Propagation Process
Configure the propagation process on DBA1:

CONNECT strmadmin/strmadminpw@DBA1
BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_PROPAGATION_RULES(
    table_name              => 'scott.dept',
    streams_name            => 'dba1_to_dba2',
    source_queue_name       => 'strmadmin.streams_queue',
    destination_queue_name  => 'strmadmin.streams_queue@dba2',
    include_dml             =>  true,
    include_ddl             =>  true,
    source_database         => 'dba1');
END;
/
The propagation is performed using a job which can be monitored using:

SELECT job,
       TO_CHAR(last_date, 'DD-Mon-YYYY HH24:MI:SS') last_date,
       TO_CHAR(next_date, 'DD-Mon-YYYY HH24:MI:SS') next_date,
       what
FROM   dba_jobs;
Configure Capture Process
Configure the capture process on DBA1:

CONNECT strmadmin/strmadminpw@DBA1
BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
    table_name     => 'scott.dept',  
    streams_type   => 'capture',
    streams_name   => 'capture_simp',
    queue_name     => 'strmadmin.streams_queue',
    include_dml    =>  true,
    include_ddl    =>  true);
END;
/
Configure Instantiation SCN
The instantiation SCN of the source table must be configured in the destination table before the apply process will work. If the destination table is already present this can be accomplished using a metadata only export/import:

exp userid=scott/tiger@dba1 FILE=dept_instant.dmp TABLES=dept OBJECT_CONSISTENT=y ROWS=n
imp userid=scott/tiger@dba2 FILE=dept_instant.dmp IGNORE=y COMMIT=y LOG=import.log STREAMS_INSTANTIATION=y
During the transfer of the meta information the supplematal logging was also transferred. Since no capture is done on DBA2 this can be removed:

CONN sys/password@DBA2 AS SYSDBA
ALTER TABLE scott.dept DROP SUPPLEMENTAL LOG GROUP log_group_dept_pk;
Alternatively the instantiation SCN can be set using the DBMS_APPLY_ADM package:

CONNECT strmadmin/strmadminpw@dba1
DECLARE
  v_scn  NUMBER;
BEGIN
  v_scn := DBMS_FLASHBACK.GET_SYSTEM_CHANGE_NUMBER();
  DBMS_APPLY_ADM.SET_TABLE_INSTANTIATION_SCN@DBA2(
    source_object_name    => 'scott.dept',
    source_database_name  => 'dba1',
    instantiation_scn     => v_scn);
END;
/
Configure Apply Process
Configure the apply process on the destination database (DBA2):

CONNECT strmadmin/strmadminpw@DBA2
BEGIN
  DBMS_STREAMS_ADM.ADD_TABLE_RULES(
    table_name      => 'scott.dept',
    streams_type    => 'apply',
    streams_name    => 'apply_simp',
    queue_name      => 'strmadmin.streams_queue',
    include_dml     =>  true,
    include_ddl     =>  true,
    source_database => 'dba1');
END;
/
Start Apply Process
Start the apply process on destination database (DBA2) and prevent errors stopping the process:

CONNECT strmadmin/strmadminpw@DBA2
BEGIN
  DBMS_APPLY_ADM.SET_PARAMETER(
    apply_name  => 'apply_simp',
    parameter   => 'disable_on_error',
    value       => 'n');

  DBMS_APPLY_ADM.START_APPLY(
    apply_name  => 'apply_simp');
END;
/
Start Capture Process
Start the capture process on the source database (DBA1):

CONNECT strmadmin/strmadminpw@DBA1
BEGIN
  DBMS_CAPTURE_ADM.START_CAPTURE(
    capture_name  => 'capture_simp');
END;
/
Test It
With the streams activated we can see that DML changes to the source table are visible in the destination table:

CONNECT scott/tiger@dba1
INSERT INTO dept (deptno, dname, loc) VALUES (99, 'Test Dept', 'UK');
COMMIT;

SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        99 Test Dept      UK

5 rows selected.

CONNECT scott/tiger@dba2
SELECT * FROM dept;

    DEPTNO DNAME          LOC
---------- -------------- -------------
        10 ACCOUNTING     NEW YORK
        20 RESEARCH       DALLAS
        30 SALES          CHICAGO
        40 OPERATIONS     BOSTON
        99 Test Dept      UK

5 rows selected.
We can also see that DDL changes to the source table are reflected in the destination table:

CONNECT scott/tiger@dba1
ALTER TABLE dept ADD (
  new_col NUMBER(10)
)
/
DESC dept

 Name                         Null?    Type
 ---------------------------- -------- --------------
 DEPTNO                       NOT NULL NUMBER(2)
 DNAME                                 VARCHAR2(14)
 LOC                                   VARCHAR2(13)
 NEW_COL                               NUMBER(10)

CONNECT scott/tiger@dba2
DESC dept

 Name                         Null?    Type
 ---------------------------- -------- --------------
 DEPTNO                       NOT NULL NUMBER(2)
 DNAME                                 VARCHAR2(14)
 LOC                                   VARCHAR2(13)
 NEW_COL                               NUMBER(10)
The contents of the streams can be viewed using statements like:

SELECT s.user_data.getTypeName()
FROM   streams_queue_table s;

SET SERVEROUTPUT ON
DECLARE
  v_anydata  SYS.ANYDATA;
  v_lcr      SYS.LCR$_ROW_RECORD; 
  v_row_list SYS.LCR$_ROW_LIST;
  v_result   PLS_INTEGER;
BEGIN
 
  SELECT user_data
  INTO   v_anydata
  FROM   strmadmin.streams_queue_table
  WHERE  rownum < 2;
 
  v_result := ANYDATA.GetObject(
                self  => v_anydata,
                obj   => v_lcr);
               
  DBMS_OUTPUT.PUT_LINE('Command Type         : ' || v_lcr.Get_Command_Type);
  DBMS_OUTPUT.PUT_LINE('Object Owner         : ' || v_lcr.Get_Object_Owner);
  DBMS_OUTPUT.PUT_LINE('Object Name          : ' || v_lcr.Get_Object_Name);
  DBMS_OUTPUT.PUT_LINE('Source Database Name : ' || v_lcr.Get_Source_Database_Name);
END;
/
Clean Up
All rules can be identified and removed using the following statements:

BEGIN
  FOR cur_rec IN (SELECT rule_owner, rule_name FROM dba_rules) LOOP
    DBMS_RULE_ADM.DROP_RULE(
      rule_name => cur_rec.rule_owner || '.' || cur_rec.rule_name,
      force => TRUE);
  END LOOP;
END;
/
All capture and apply processes can be identified, stopped and dropped using:

BEGIN
  FOR cur_rec IN (SELECT capture_name FROM dba_capture) LOOP
    DBMS_CAPTURE_ADM.STOP_CAPTURE(
      capture_name => cur_rec.capture_name);
    DBMS_CAPTURE_ADM.DROP_CAPTURE(
      capture_name => cur_rec.capture_name);
  END LOOP;

  FOR cur_rec IN (SELECT apply_name FROM dba_apply) LOOP
    DBMS_APPLY_ADM.STOP_APPLY(
      apply_name => cur_rec.apply_name);
    DBMS_APPLY_ADM.DROP_APPLY(
      apply_name => cur_rec.apply_name);
  END LOOP;
END;
/
All streams information relating to a specific object can be purged using:

BEGIN
  DBMS_STREAMS_ADM.PURGE_SOURCE_CATALOG(
    source_database        => 'dba1',
    source_object_name     => 'scott.dept',
    source_object_type     => 'TABLE');
END;
/
For further information see:

Oracle9i Streams Release 2 (9.2)
Monitoring a Streams Environment
Oracle9i Supplied PL/SQL Packages and Types Reference Release 2 (9.2)


20 03, 2005
初来杭州生活印记
作者 xzh2000 13:28 | Permalink 静态链接网址 | Comments 最新回复 (10) | Trackback 引用 (0) | 技术交流

初来杭州,真有点下地狱的感觉.

由于火车晚点了3个小时吧,所以从广州到杭州下车后,已经是下午

4点左右,然后打电话约房东看房(先前是杭州同学帮着找的),到达

房东那里,已经是晚上七点钟.

房间是三居的,只是室内没有装修,还是水泥地板,房间里也是乱七八

糟的,有两个房间出租,我要了一个小房间,本来就没有打算在那里住

多久的,房间里一个单人床,一个电脑桌.

将房间收拾了一下,终于有点温謦的感觉,然后就交了一个月房租,

最最要命的是,卫生间里没有热水器,而且也没有阳台,晕,不知开发

商搞什么的,连凉衣服也成问题.

还好也没有多少衣服可凉,现在最大的问题就是洗澡问题啦,希望房

东能买部热水器,或者我来买,房租必须降一些,后来房东同意由我来

买,但具体降多少也没有说明,看来房东是不怎么洗澡的.

在广州生活了两年多,别的没有学到,却学到了每天洗澡的习惯,想想

还是自己去买一台热水器吧,反正也不贵,找了很久,终于找到一家卖

场,最便宜的热水器也要300元左右,而且安装材料等还不包括在内,

真是气愤,在广州全部搞定才200元.

想想也不会住那里长住,最后还是没买,如果要洗澡,只有到浴室啦,

打听了一下,了附近就有2家浴室,大概有10分钟的路,每次洗澡7-10元,

如果搓背,另收10元.


19 03, 2005
广州两年生活印记
作者 xzh2000 14:33 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

总的在广州的生活时间大概有二年半左右吧,最初是2001.3-2001.10月,

当时在广州的一家大型纺织公司做开发。第二次到广州是2003.3月,当时

正是非典时期哦,到2005.3月离开。

很早就听说广州很乱啦,但实际在广州生活时,却反而没有什么感觉啦,

尽管很多朋友或同事都有被抢的经历,本人却从来没有被偷或被抢过,大

概是运气吧。

有次晚上下班,与同事一块坐560回家,下车后发现钱包丢了,当时就

晕了,第二天一早就准备去挂失银行卡,这时同事竟然将钱包又给我送

过来啦,原来我的钱包掉在座位上,坐在我旁边那个打不开窗户,就只

好拖我的同事把钱包送回去,真的很感激那个陌生人。

广州坐车难,比北京还要严重一些;至于生活方面,倒感觉是我生活的所

有城市中,是最最方便的一个。冬天一点都不冷,呵呵。


19 03, 2005
火车上的人生
作者 xzh2000 13:49 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

从广州到杭州的机票新公司是可以报销的,但突然离开生活了

2年的城市,心中总有一种依依不舍的感觉,鬼使神差般地买

了从广州到杭州的火车票。

为了一次把全部的行李带走,买了一个很大的行李箱,虽然也

只有随身的衣物等,及一部手提电脑,结果还是很重,上了火

车后才发现,行车架是放不下的,汗。

本以为3月份比较好买票,提前2天竟没有买到卧铺票,只好抱

希望在车上补卧铺票啦,但上车后就失望了,补卧的人就排了

很长的队。

车箱内人行道上也站满了人,大部分是民工,他们毫无顾忌抽

烟,乱丢果皮,与老乡大声讲话,有些人一上车就脱了鞋子,

一会儿车厢中就乌烟瘴气。

最搞笑的就是每节车厢的列车员啦,车一开就把所有的窗户都

关闭了,并不允许打开,坐在里面闷得要命。他先是很负责地

地将所有的行李箱都码整齐,真是TMD的体力活。

然后就开始干其买卖了,先拿了一些小马扎来卖,然后就是纪

念品,最后竟然干起方便面的行当啦,真有前途。火车在下一

站停下时,该车站上的小商贩拼命地拍窗户,就是不开,终于

明白为什么要锁上啦,这叫肥水不流外人田吧。

偶所在的车厢列车员每隔一段时间就清扫一次垃圾,看到刚扫

过的又被搞脏啦,就不客气地将那些民工呵斥一顿,但他刚走

不久,那些民工就故意地把果皮丢到地下。。。。。。

总之一路上,民工与列车员吵了一路,发现变态的人太多啦,,,

以前总觉得老师比较变态,现在发现列车员也是一样的。


10 03, 2005
辞职也艰难(2)
作者 xzh2000 09:03 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

公司终于同意提前离职啦,心情也放松了许多,想着这两年经营起来的小窝,

也有了许多依依不舍的情结,由于比较伧促,一些家电及书藉就不太好处理,

还好一个朋友刚买了房,可以把书藉放在朋友那里,电器看看能否托运回或

者带到杭州去。

由于和一些朋友合租,离开前还要帮助朋友找人来转租,也是比较麻烦的,

更麻烦的是到杭州租房,虽然已经托同学先帮忙找找,但要租到合适的也不

是那么容易的。

总之,年龄越大,跳来跳去的胆量就越小。


07 03, 2005
数据库交接说明书
作者 xzh2000 16:02 | Permalink 静态链接网址 | Comments 最新回复 (7) | Trackback 引用 (0) | 技术交流

1 了解加油站的体系结构
  -----------------           -----------------
  |   (data1)  |          |    (data2)  |
 |  加油站数据库  |-------------------| 加油站备用数据库 |
 | 172.16.64.81 |          |  172.16.64.82 |
 -----------------          -----------------   
     |
     |
     |
  -----------------           -----------------
  | (www1.apache) |          |  (www2.squid) |
 |  应用服务器  |-------------------|  代理服务器  |
 | 172.16.64.84 |          | 172.16.64.83 |
 -----------------          -----------------   
 说明:www2的机器位于防火墙之外,其它的机器都在防火墙之内,广州的
 访问必须通过www2;通常的维护与管理都在防火墙内的www1上进行,在
 /home/oracle/sql目录内的scripts是我日常维护用的(切勿删除);
 data1是加油站数据库所在的机器;data2是dataguard的备用数据库。

 在www1/data1/data2上都有通过cron调度的shell,所以这些服务器
 的cron服务都不可以停,否则人工维护的事情就比较多,通过crontab -e
 可以查看这些shell所在的目录。

2 关于自由空间的监控
 [oracle@www1 sql]$ pwd
 /home/oracle/sql
 [oracle@www1 sql]$ sh free_space.sh
 表空间名     表空间(M) 已使用(M) 使用比   空闲(M) 最大块(M)
 ------------ ------ -------- -------- ------- ---------
 TS_CYBERCAFE  30000 24673.87   82.25  5326.13   1475.94
 CARDSALE        500   346.37   69.27   153.63    152.94
 SYSTEM          500   233.87   46.77   266.13    167.00
 PERFSTAT        500    96.25   19.25   403.75    402.94
 RMANTBS1        100    16.87   16.87    83.13     82.94
 UNDOTBS1        500    52.31   10.46   447.69    430.94
 说明:在www1上的sql目录内,free_space.sh可以输出各表空间的使用
 情况,temp表空间是非自动增长的,可从dba_temp_files中查看,如果它
 不能自动扩展,前台页面将产生错误消息返回.

 ts_cybercafe/cardsale是存放生产数据的表空间,cardsale在数据增
 长很慢,在它<100m后需要找大到1000m;ts_cybercafe增长较快,如果它
 的数据<2000m时,需要增加ts_cybercafe表空间的数据文件。

 undotbs1是允许自动扩展的,但通常是<500m的,可以不用处理,rmantbs1
 是存储rman需要的catalog信息,可以不用处理(数据量很小),perfstat表
 空间是存放statspack收集的快照,如果<100m时需要清空perfstat.
 sql>@connect_perf
 sql>@?/rdbms/admin/sptrunc

 每天早上www1服务器会将加油站的磁盘空间使用情况发给dba及系统维护人
 员,如果磁盘空间不足请删除/home/oracle/backup目录的备份,也可以立
 即清空agent_price_log表或/home/oracle/oradata/esal/archive
 目录内所有归档日志。

3 数据库的启动与关闭
 数据库已经配置了在操作系统启动时同时启动实例与监听,关闭数据库时请使
 用shutdown immediate,手工启动数据库startup即可,因为数据库使用的
 系统参数文件(spfile)启动数据库的。

4 数据库性能监控报表
 statspack从早上8点到晚上下班8点,每小时收集一次快照,然后在晚上8点半
 成statspack报表,发给dba及相关系统管理员,仔细阅读及分析statspack报
 表是了解数据库运行状态的最佳手段。

5 数据库中自动任务监控
 数据库的job是保障系统稳定运行的一些必要措施,确保每个job都能正常工作,
 若发现某job中止,一定要找到原因并修复,否则可能会对系统造成严重的影响。

6 数据库故障监控
 每天早中晚要定时检查alter_sid.log是否有错误发生,当然可以通过cron来
 调度,每隔几分钟就检查一次,确保问题最先被发现并处理。

7 系统参数修正意见
 千万不要随意修改系统参数,这些参数都是久经考验的。


03 03, 2005
oracle/linux命令集锦
作者 xzh2000 13:03 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
http://www.ss64.com/
02 03, 2005
昨天系统被攻击了...
作者 xzh2000 11:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

昨天下午下班时,收到一些前台页面的错误通知,一看就知道有些客户
在攻击系统,手法很差的,在输入中加了go exec sp_helpdb等信息,
这些小毛贼,搞了很久,大概发现不是ms sqlserver数据库,然后,就
开始用一些软件搞强力攻击......
应用服务器+代理服务器(防火墙外)+数据库服务器的负载都比较低,
但应用服务器中有很多apache的进程(正常状态下<30),在数据库服
务器上有很多(<200)oracle的session(local=no)没有退出,状态
是inactive,这种进程越来越多,但数据库负载还是很低(<2),也没有
客户投诉系统慢,重启了apache后问题依旧......


01 03, 2005
redhat 系统优化[转]
作者 xzh2000 17:56 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

处理器∶Intel 赛扬 366 MHz
记忆体∶?128 Mb PC100 RAM
硬碟∶IBM 15Gb 7200 rpm ATA66
显示卡∶Sis 620 AGP
声卡∶CS46xx
网络卡∶D-Link DFE530TX (ver A)
显示器∶Alfscan G17 17 寸
操作系统∶安装 Windows 98 与 RH7.0 + CLE 1.0

一、开启硬盘 DMA 支持。

系统安装完毕後,硬盘的 DMA 是没有打开的,我的方法是在
/etc/rc.d/rc.local 最後面加上一行 /sbin/hdparm -d1 -c3 -m16 /dev/hda 这样每次开机後,硬盘的 DMA 就会开启,不必每次手动设定。

如果您的硬盘机支持 ATA33 可以加上 -X66 这个参数,ATA66则是 -X68,像我的硬盘是 ATA66 那麽完整参数就是 /sbin/hdparm -d1 -X68 -c3 -m16 /dev/hda 经过我的测试 ,在 DMA 未开启以前,实际读取效率是每秒约 4.10 Mb 左右,开启 DMA 後,每秒实际读取效率跃升为 20 Mb 大约提升 5 倍之多。

§未开启 DMA 时的测试

[root@firefly /root]# hdparm -d0 /dev/hda

/dev/hda:

setting using_dma to 0 (off)
using_dma = 0 (off)

[root@firefly /root]# hdparm -Tt /dev/hda

/dev/hda:

Timing buffer-cache reads: 128 MB in 2.75 seconds = 46.55 MB/sec
Timing buffered disk reads: 64 MB in 15.58 seconds = 4.11 MB/sec

§开启 DMA 後的测试结果

[root@firefly /root]# hdparm -d1 -X68 -c3 -m16 /dev/hda

/dev/hda:

setting 32-bit I/O support flag to 3
setting multcount to 16
setting using_dma to 1 (on)
setting xfermode to 68 (UltraDMA mode4)
multcount = 16 (on)
I/O support = 3 (32-bit w/sync)
using_dma = 1 (on)

[root@firefly /root]# hdparm -Tt /dev/hda/dev/hda:

Timing buffer-cache reads: 128 MB in 2.75 seconds = 46.55 MB/sec
Timing buffered disk reads: 64 MB in 3.20 seconds = 20.00 MB/sec

由以上的数据,可以看得出来,硬盘 DMA 是否开启,对读取效率影响很大。

二、关闭多馀的系统服务。

这是老生常谈的题目了,一般我们当作桌上型工作站的时候,只需要激活几个基本的?Service 即可,其他的不但没用,一方面会占用系统资源,另一方面则会有安全上的顾虑,我平常只用来连网、打打文件、听听音乐、看看电影,多半时间只是一个 Client 端,实在没必要激活 Server 端的服务,所以,我在 Setup System Services时,只留下以下几个 Service,其馀的都关闭。

1. crond
2. network
3. syslogd

真的,相信我,只要这四个就足够了!

三、下载 Kernel 重新编程。

因为系统所默认安装的 Kernel 是为了适用大部分的计算机而做的,并未对你的计算机作最优化,所以显得臃肿肥大,因为 Kernel 直接掌控著计算机的一切,所以对系统效率影响当然很大。

我的作法是∶下载最新的 Kernel 重新编程,将我计算机上的硬件直接编程进 Kernel 里面,不要作成 Module ,对於不需要的就不编程,这样,打造出完全面向自己环境的 Kernel ,才能完全发挥计算机的威力。

至於 Kernel 怎样编程?这就不是我的主题了,大家可以到CLDP 自行参考 KERNEL HOW-TO 中译版。

四、减少虚拟终端机的数量。

系统默认是6个,也就是 CTRL+ALT F1~F6 那六个,我关掉其中四个,只留下 CTRL+ALT F1~F2,大约省下 4 Mbytes 的记忆体,但是这样一来,X-Window 会从原来的 CTRL+ALT F7 变成 CTRL+ALT F3 。

修改 /etc/inittab 中,将 mingetty 3 ~6 全部加上 # 字号,然後下指令 #init q

五、调整 X-Windows 环境

我习惯操作 KDE ,对 GNOME 不熟,所以,以下是都是面向 KDE而设,GNOME 的使用者,我想,应该也差不多啦!

1、颜色数设为 16 Bit 就有很好的效果了,24 Bit 除了浪费资源,看不出有何好处。
2、不要使用屏幕保护程序。
3、取消动画窗口功能。
4、尽量使用同一种字型。
5、浏览器用 Mozilla 不要用 Netscape。
6、不要激活音效服务器 artd

Speed Up X by Managing Font Setting 在你抱怨 X 跑得不够快之前,
先检查字型设定, 很可能就是影响效能的一大元凶。
先看一下 /etc/X11/XF86Config-4 档案里的 FontPath 设定值, 如果是
如下∶
Section "Files"

RgbPath "/usr/X11R6/lib/X11/rgb"

# Multiple FontPath entries are allowed (they are concatenated together)
# By default, Mandrake 6.0 and later now use a font server independent of
# the X server to render fonts.

FontPath "unix/:-1"

EndSection

可参考 /etc/X11/fs/config 档案里的字型设定值, 挑选几个喜欢的字型目录(全部比较不会错)
来修改, 例如我直接设定下列几个字型目录∶
Section "Files"

RgbPath "/usr/X11R6/lib/X11/rgb"

# Multiple FontPath entries are allowed (they are concatenated together)
# By default, Mandrake 6.0 and later now use a font server independent of
# the X server to render fonts.

FontPath "/usr/X11R6/lib/X11/fonts/misc:unscaled"
FontPath "/usr/X11R6/lib/X11/fonts/75dpi:unscaled"
FontPath "/usr/X11R6/lib/X11/fonts/Type1"
FontPath "/usr/X11R6/lib/X11/fonts/mdk:unscaled"
FontPath "/usr/share/fonts/ttf/big5"

EndSection

修改之後, 重新激活 startx 感受看看棉。

原本的 FontPath "unix/:-1" 将字型由 X Font Server 来提供,
一般使用者未蒙其利、先受其害, 可以考虑等熟悉 X Font Server 功能後再使用。
如此就可以关掉xfs了
ps:试用时不要用默认开机直接进x-window,若不行会卡在x-window
ps:引用自http://twopensource.org/~marr/xfont_tip.html
六、调整应用程序优先权。

一般时候,我们使用任何程序时,其 NICE 值都是 0,意思是CPU 的使用权值。如果我们常用程序有较高的优先权的话,自然效率就会比较好,优先权的值从 -20 到 19 ,数字越小优先权就越高,但要注意的是一般使用者只能调低( 0~19),只有 root 有权调高优先权( -20 ~ 19 )。我们可以用 ps -fel 来观察 NI 那栏就知道。

说了半天,到底如何调整呢?有一个指令 /bin/nice 就是用来作这件事的,用法如下∶nice?-n?程序名称?参数....
n 的值从 -20 到 19,这是手动操作,在 KDE 中,可?$$$〉ケ嗉骼瓷瓒ǎ椒ㄊ窃谀阋髡畔热ǖ某绦虻?[ 命令 ] 那一栏的前面,加上 /bin/nice --n 就可以了。

比方说我常用 Mozilla 来浏览网页,我改成 /bin/nice --10 /usr/local/mozilla/mozilla 这样我的 Mozilla 执行时,就比其他程序有更高的优先权,在实际测试的时候,Mozilla 激活速度以及回应都快了不少,其他一些常用的程序,也可以比照办理。

後记

Linux 真的是一套很棒的操作系统,经过这样调整後,光是开机到登入窗口画面出现,从原来的 48 秒,变成 30 秒,用 top 指令(每秒)观察CPU idle 时间也从 82% 提升到 93%,而窗口程序的反应感觉上与 Windows 98 差不多了。

这个是从一个网站上下载的文章(在WINDOWS下,因为linux下无法保存网页,请高手指教!!).我把
那个网址链接给忘了,对不起,加上这个网站又不能上传html的后缀,只好把文章的内容拷贝下来
了.这个方法我试过,就是编译内核和字体不成功外其他的都可以成功.
望小鸟们试一试这个文章!!!也算对版主的支持吧,那么多的版主曾经那么关心过我的文章,如今
是该报答的时候了!!呵呵!!

25 02, 2005
LVM2+ReiserFS.2[转贴]
作者 xzh2000 14:59 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

继续 ^_^ 下面说一下如何扩充,删除,管理它:)
使用lvextend -L size LVNAME 增大一个逻辑卷的大小。
[root@NEWLFS mnt]#lvextend -L +1G /dev/lvm_vg/lv_home
  Extending logical volume lv_home to 3.00 GB
  Logical volume lv_home successfully resized
[root@NEWLFS mnt]#                     
-L +1G 为lv_home加上 1G 空间。或者使用这种格式:
[root@NEWLFS mnt]#lvextend -L 3G /dev/lvm_vg/lv_home
指定lv_home更改后的大小,效果相同。

更改逻辑卷大小后,还应该更改文件系统的大小,保持一致:
[root@NEWLFS mnt]#resize_reiserfs -f /dev/lvm_vg/lv_home
resize_reiserfs 3.6.19 (2003 www.namesys.com)

ReiserFS report:
blocksize             4096
block count           786432 (524288)
free blocks           778197 (516061)
bitmap block count    24 (16)

Syncing..done
resize_reiserfs: Resizing finished successfully.

[root@NEWLFS mnt]df
Filesystem            Size  Used Avail Use% Mounted on
/dev/md0              5.4G  2.8G  2.7G  51% /
/dev/hda1             6.4G  4.0G  2.5G  62% /mnt/C
/dev/hda6              25G   22G  3.6G  86% /mnt/E
/dev/hda7             9.7G  3.7G  5.6G  40% /mnt/lfs
/dev/mapper/lvm_vg-lv_home
                      3.0G   33M  3.0G   2% /mnt/lvm_home
[root@NEWLFS mnt]#
成功的将lvm_home扩展到了3G,没有重新启动,并且没有卸载文件系统。
ReiserFS真是好用!  ^_^

当然,ReiserFS 也允许卸载文件系统后resize,使用下列命令:
[root@NEWLFS mnt]#umount /dev/lvm_vg/lv_home
卸载文件系统
[root@NEWLFS mnt]#resize_reiserfs /dev/lvm_vg/lv_home
调整大小,与上面不同的地方是没有 -f 参数.
[root@NEWLFS mnt]#mount -t reiserfs /dev/lvm_vg/lv_home lvm_home/
重新挂载上.

EXT2/3 安装,扩展:
[root@NEWLFS mnt]#lvcreate -L 2G -n lv_opt lvm_vg
  Logical volume "lv_opt" created
分出一块2G名字为lv_opt的逻辑卷

[root@NEWLFS mnt]#mke2fs -j /dev/lvm_vg/lv_opt
mke2fs 1.35 (28-Feb-2004)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
262144 inodes, 524288 blocks
26214 blocks (5.00%) reserved for the super user
First data block=0
16 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912

Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 35 mounts or
180 days, whichever comes first.  Use tune2fs -c or -i to override.
创建ext3文件系统
[root@NEWLFS mnt]#mkdir lvm_opt
[root@NEWLFS mnt]#mount -t ext3 /dev/lvm_vg/lv_opt lvm_opt/
创建挂载点,挂载上。
[root@NEWLFS mnt]#df
Filesystem            Size  Used Avail Use% Mounted
..............
/dev/mapper/lvm_vg-lv_home
                      3.0G   33M  3.0G   2% /mnt/lvm_home
/dev/mapper/lvm_vg-lv_opt
                      2.0G   33M  1.9G   2% /mnt/lvm_opt

[root@NEWLFS mnt]#lvextend -L +1G /dev/lvm_vg/lv_opt
  Extending logical volume lv_opt to 3.00 GB
  Logical volume lv_opt successfully resized
为lv_opt 增加一个G的空间。

[root@NEWLFS mnt]#umount lvm_opt/
调整ext2/3文件系统 需要先卸载,然后调整,不象ReiserFS可以不用卸载。

[root@NEWLFS mnt]#resize2fs /dev/lvm_vg/lv_opt
resize2fs 1.35 (28-Feb-2004)
Please run 'e2fsck -f /dev/lvm_vg/lv_opt' first.
提示先运行e2fsck -f 那就检查下吧 :)
resize2fs -f 参数可以不用e2fsck,检查下也是好的。

[root@NEWLFS mnt]#e2fsck -f /dev/lvm_vg/lv_opt
e2fsck 1.35 (28-Feb-2004)
Pass 1: Checking inodes, blocks, and sizes
Pass 2: Checking directory structure
Pass 3: Checking directory connectivity
Pass 4: Checking reference counts
Pass 5: Checking group summary information
/dev/lvm_vg/lv_opt: 11/262144 files (0.0% non-contiguous), 16443/524288 blocks
[root@NEWLFS mnt]#resize2fs /dev/lvm_vg/lv_opt
resize2fs 1.35 (28-Feb-2004)
Resizing the filesystem on /dev/lvm_vg/lv_opt to 786432 (4k) blocks.
The filesystem on /dev/lvm_vg/lv_opt is now 786432 blocks long.
成功将lv_opt调整成3G,重新mount 看看吧 !

[root@NEWLFS mnt]#mount -t ext3 /dev/lvm_vg/lv_opt lvm_opt/
[root@NEWLFS mnt]#df
Filesystem            Size  Used Avail Use% Mounted on
.............
/dev/mapper/lvm_vg-lv_home
                      3.0G   33M  3.0G   2% /mnt/lvm_home
/dev/mapper/lvm_vg-lv_opt
                      3.0G   33M  2.9G   2% /mnt/lvm_opt
[root@NEWLFS mnt]#
OK啦。 LVM真是方便 ^_^

再来看看如何减小分区大小:
注意: 减小逻辑卷大小之前,应该先减小文件系统的大小,否则可能会导致数据丢失。

ReiserFS :
[root@NEWLFS mnt]#umount lvm_home/
首先卸载ReiserFS文件系统。

[root@NEWLFS mnt]#resize_reiserfs -s-1G /dev/lvm_vg/lv_home
resize_reiserfs 3.6.19 (2003 www.namesys.com)

You are running BETA version of reiserfs shrinker.
This version is only for testing or VERY CAREFUL use.
Backup of you data is recommended.

Do you want to continue? [y/N]:y
Processing the tree: 0%....20%....40%....60%....80%....100%    left 0, 0 /sec

nodes processed (moved):
int        0 (0),
leaves     1 (0),
unfm       0 (0),
total      1 (0).

check for used blocks in truncated region

ReiserFS report:
blocksize             4096
block count           524288 (786432)
free blocks           516061 (778197)
bitmap block count    16 (24)

Syncing..done

resize_reiserfs: Resizing finished successfully.

先减小文件系统的大小, -s-1G 减去1个G

[root@NEWLFS mnt]#lvreduce -L -1G /dev/lvm_vg/lv_home
WARNING: Reducing active logical volume to 2.00 GB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce lv_home? [y/n]: y
  Reducing logical volume lv_home to 2.00 GB
  Logical volume lv_home successfully resized
然后减小LV大小, -L -1G 减去1个G 与文件系统保持一致。

[root@NEWLFS mnt]#mount -t reiserfs /dev/lvm_vg/lv_home lvm_home/
[root@NEWLFS mnt]#df
Filesystem            Size  Used Avail Use% Mounted on
/dev/md0              5.4G  2.8G  2.7G  51% /
/dev/hda1             6.4G  4.0G  2.5G  62% /mnt/C
/dev/hda6              25G   22G  3.6G  86% /mnt/E
/dev/hda7             9.7G  3.7G  5.6G  40% /mnt/lfs
/dev/mapper/lvm_vg-lv_opt
                      3.0G   33M  2.9G   2% /mnt/lvm_opt
/dev/mapper/lvm_vg-lv_home
                      2.0G   33M  2.0G   2% /mnt/lvm_home

OK,成功减少了一个G,从上面输出可以看出,减小要比增大危险一些
所以应该尽量避免减小分区大小,以及做重要数据的备份,有备无患嘛 :)

EXT2/3:
在LVM1中可以通过e2fsadm这个程序,方便的减小一个ext2/3的大小。
而LVM2中这个程序不可用。
所以在LVM2中减小EXT2/3大小时麻烦一些,因为必须要知道减少后卷的块数。

[root@NEWLFS ~]#umount /mnt/lvm_opt/
首先卸载文件系统
[root@NEWLFS ~]#mke2fs -n /dev/lvm_vg/lv_opt
mke2fs 1.35 (28-Feb-2004)
Filesystem label=
OS type: Linux
Block size=4096 (log=2)
Fragment size=4096 (log=2)
262144 inodes, 786432 blocks
26214 blocks (5.00%) reserved for the super user
First data block=0
16 block groups
32768 blocks per group, 32768 fragments per group
16384 inodes per group
Superblock backups stored on blocks:
        32768, 98304, 163840, 229376, 294912
[root@NEWLFS ~]#
因为必须知道减少后卷的块数,所以通过mke2fs -n 列出块大小

注意: -n 参数不会使mke2fs真的创建文件系统,而只是列出文件系统的信息。
千万不要少了-n 否则数据就全没了。。:(
块大小是4096(4kb) 当前有786432个blocks 现在打算减小一个G的空间。
1G占用的blocks一共是262144个,所以减少后的blocks应该是524288个。

减小FS大小:
[root@NEWLFS ~]#resize2fs /dev/lvm_vg/lv_opt 524288
resize2fs 1.35 (28-Feb-2004)
Resizing the filesystem on /dev/lvm_vg/lv_var to 524288 (1k) blocks.
The filesystem on /dev/lvm_vg/lv_var is now 524288 blocks long.
减少LV大小:
[root@NEWLFS mnt]#lvreduce -L -1G /dev/lvm_vg/lv_var
  WARNING: Reducing active logical volume to 2.00 GB
  THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce lv_var? [y/n]: y
  Reducing logical volume lv_var to 2.00 GB
  Logical volume lv_var successfully resized
ok,成功缩小了1G,再重新mount上吧。

[root@NEWLFS mnt]#mount /dev/lvm_vg/lv_var lvm_var/
[root@NEWLFS mnt]#df
..........
/dev/mapper/lvm_vg-lv_var
                      2.0G   33M  1.9G   2% /mnt/lvm_var
下面再来看看如何删除LV,VG :
删除LV:
[root@NEWLFS mnt]#umount /dev/lvm_vg/lv_opt
必须先关闭LV才可以删除它。
[root@NEWLFS mnt]#lvremove /dev/lvm_vg/lv_opt
Do you really want to remove active logical volume "lv_opt"? [y/n]: y
  Logical volume "lv_opt" successfully removed
[root@NEWLFS mnt]
使用lvremove命令删除一个逻辑卷,这里删除了lv_opt.

删除VG:
首先必须确保VG中没有任何逻辑卷存在,才可以删除一个VG。
我已经使用lvremove 删除了lv_usr lv_home。
[root@NEWLFS mnt]#lvdisplay
[root@NEWLFS mnt]#
没有任何输出,说明已经没有lv了。

[root@NEWLFS mnt]#vgchange -a n lvm_vg
  0 logical volume(s) in volume group "lvm_vg" now active
使用vgchange -a n 关闭了lvm_vg,然后才可以删除它。

[root@NEWLFS mnt]#vgremove lvm_vg
  Volume group "lvm_vg" successfully removed
干掉了 ....世界清静了 ^_^

[root@NEWLFS mnt]#vgdisplay
[root@NEWLFS mnt]#                    
没有回显,说明已经没有任何VG了。

向VG中添加/删除PV :
上面已经提到了,VG可以由多个PV组成(hda1,hda3,hda5....)
可以使不相邻的分区,结合在一起使用。(和线性RAID同样的作用)

来看看如何向VG中添加PV:

因为我没有多余的物理设备来演示,所以用到了loop设备。
首先我通过
[root@NEWLFS ~]#dd if=/dev/zero of=/root/lvm bs=4096 count=32768
在/root目录下创建了一个128M的文件(/root/lvm)
然后用losetup 命令挂在了/dev/loop0上,这样我的loop0就象/dev/hdaX一样
是一个可用的块设备了。loop设备真是不错,用来做实验很好,比如试试reiserfs
raid,LVM.....练习好了,再在真实分区上实践。

看看我是怎么使用的 :)
[root@NEWLFS ~]#losetup /dev/loop0 lvm
将刚刚建立的lvm文件挂在了/dev/loop0中,这样loop0可以象其他物理设备可以使用了。
初始化loop0 为PV:
[root@NEWLFS ~]#pvcreate /dev/loop0
  Physical volume "/dev/loop0" successfully created
[root@NEWLFS ~]#

使用vgextend命令将/dev/loop0添加到lvm_vg中:
[root@NEWLFS ~]#vgextend lvm_vg /dev/loop0
  Volume group "lvm_vg" successfully extended
[root@NEWLFS ~]#
成功的将/dev/loop0加入到了lvm_vg中。下面就可以创建LV啦。
[root@NEWLFS ~]#lvcreate -L 128M -n loop_lv lvm_vg /dev/loop0
  Insufficient allocatable logical extents (31) for logical volume loop_lv: 32 required
加上/dev/loop0表示指定这个LV只在/dev/loop0中,可能因为LE自身占用空间,所以无法分配128M
[root@NEWLFS ~]#lvcreate -L 100M -n loop_lv lvm_vg /dev/loop0
  Logical volume "loop_lv" created
[root@NEWLFS ~]#
100M就可以成功创建了,可以看出,loop_lv这个LV完全在/dev/loop0上。

删除PV:
必须确保要删除的PV中没有被任何LV使用
使用 pvdisplay /dev/loop0 查看 (假设loop0是要删除的pv)

[root@NEWLFS ~]#pvdisplay /dev/loop0
  --- Physical volume ---
  PV Name               /dev/loop0
  VG Name               lvm_vg
  PV Size               124.00 MB / not usable 0
  Allocatable           yes
  PE Size (KByte)       4096
  Total PE              31
  Free PE               31 ---->FreePE=TotalPE
  Allocated PE          0------>占用的PE为0 说明loop0上没有lv
  PV UUID               K38G8y-G6b7-81O0-SFz5-HZii-Rp6t-sHq4ou
[root@NEWLFS ~]#


如果仍然有LV使用该物理卷,可以通过 pvmove 命令转移到另一个PV上
然后使用vgreduce命令 删除PV :

[root@NEWLFS ~]#vgreduce lvm_vg /dev/loop0
  Removed "/dev/loop0" from volume group "lvm_vg"
[root@NEWLFS ~]#
成功将/dev/loop0从lvm_vg中删除,很简单吧 ^_^                  
系统启动时自动加载LVM分区:

修改/etc/fstab 加入LVM分区 以及挂载点,FS类型等。。。。
/dev/lvm_vg/lv_home /mnt/lvm_home reiserfs defaults 0 0
/dev/lvm_vg/lv_opt  /mnt/lvm_opt  ext3     defaults 0 0

然后需要在系统启动脚本中加入激活LVM的命令
并且必须在挂载/etc/fstab中的文件系统之前激活LVM,不然怎么挂载阿。^_^
我写在了/etc/rc.d/init.d/mountfs这个脚本中,它的作用是
在fsck检查各个分区后,将/分区及其他分区重新挂载成read-write的
/sbin/vgscan  -------->需要加入的两行
/sbin/vgchange -a y

mountfs脚本主要内容是:(传递start参数)
echo "Remounting root file system in read-write mode..."
mount -n -o remount,rw /
echo "Recording existing mounts in /etc/mtab..."
                > /etc/mtab
                mount -f / || failed=1
                mount -f /proc || failed=1
                if grep -q '[[:space:]]sysfs' /proc/mounts ; then
                        mount -f /sys || failed=1
                fi
echo "Mounting remaining file systems..."
                ##############LVM##############
                /sbin/vgscan  #------->在挂载其他文件系统之前
                /sbin/vgchange -a y #---->就激活了LVM,随后就挂载上啦
                mount -a -O no_netdev #--->依照/etc/fstab挂载FS

这样系统启动时,就会激活LVM,并自动挂载上。

一篇关于LVM的文章中说,将这两条命令加在了检查文件系统脚本中,但是我加在那里
不成功,可能因为在checkfs时,系统是read-only的,而vgchange -a y
需要写入数据却无法写入,所以不行.

udev服务先于checkfs启动,并且通过mount -n -t ramfs ramfs /dev
将/dev挂载成ramfs,完全在内存中活动,无论根分区是否可写,/dev都是可写的。
莫非vgchange -a y 还要向其他位置写入数据?有待研究:)

在其他的发行版中,如Red Hat,Mandrake中,检查根文件系统,依照/etc/fstab
挂载各个文件系统,开启SWAP分区...等等,这些都是通过/etc/rc.d/rc.sysinit完成的
而在LFS中则是将这个脚本 分成了若干的小脚本,然后逐一的运行它们。
个人认为这样可以更直观的了解系统的启动过程,方便修改。
所以在其他发行版中,激活lvm,就要写到/etc/rc.d/rc.sysinit中
并且必须要在挂载/etc/fstab中文件系统之前激活。还要注意激活时,系统是rw的。

最后我又在mountfs中添加了关闭VG的语句,这样可以
在系统关机/重启的时候自动关闭VG。
/sbin/vgchange -a n ------>添加这句

当系统关机/重启时,mountfs会依照/etc/fstab卸载所有的文件系统:
mountfs 脚本内容 : (传递stop参数)

echo "Unmounting all other currently mounted file systems..."
umount -a -d -r -t noramfs
/sbin/vgchange -a n # --->加在了这里

在卸载LV卷后,才可以关闭VG,开始我加在了umount上面一行就不行。提示仍有LV在使用。
其他发行版中,关闭VG要比激活VG容易多啦。只要加在halt/reboot这个服务脚本里就可以。
其实只要卸载文件系统后的服务脚本都可以,随你喜欢了。 ^_^

原文:http://mengxin.blogchina.com/blog/article_136010.832775.html


25 02, 2005
LVM2+ReiserFS.1[转贴]
作者 xzh2000 14:41 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

LVM+ReiserFS v3.6.19 
 
lvm真是好东东,分区-------  想怎么分就怎么分,想怎么变,随你喜欢!
本想这个东东应该很容易搞定了,不想又搞了一下午。陷在不断的编译内核
lvm程序不断的"segment fault" 估计程序错误中就这个问题比较难办了。
完全靠经验解决 (对我等菜鸟来说,就是瞎猫碰死耗子,碰上就阿弥陀佛啦)
经过一下午的 编译内核<---->创建lvm 的折磨,终于搞定了,还算走运  ^_^

注:LVM现在有LVM1,LVM2两种版本,本文使用的是LVM2
Ok, Let`s GO !
什么是 LVM ? (Logical Volume Manager)为计算机提供了更高层次的磁盘存储。
它使系统管理员可以更方便的为应用与用户分配存储空间。
在LVM管理下的存储卷可以按需要随时改变大小与移除(可能需对文件系统工具进行升级)。
LVM也允许按用户组对存储卷进行管理,允许管理员用更直观的名称(如"sales'、'development')
代替物理磁盘名(如'sda'、'sdb')来标识存储卷。
简单的说就是LVM管理介于物理介质(hda,md,loop)和文件系统(ReiserFS)之间
使用LVM可以灵活的管理分区,在需要时,方便的增加或减小分区的大小
不用重新"格式化",甚至不用重新启动系统,这对于服务器系统来说很实用。
对于个人用户也是分区管理的绝佳选择,例如用几十G的空间来装linux
分区是很头疼的,简单的分成 "/","SWAP" 太过草率,也不利于管理,而分出/usr
/var /opt .... 对于每个分区大小要评估的准确,不然以后使用中出现
空间不够的情况,可能就需要转移数据,重新分区,很麻烦。

而使用LVM管理,就容易多了,可以先按照当前需要分配空间,当不够用的时候再增加
而这一切只是简单的几条命令就可以完成,甚至不用重新启动就可以使用扩展后的空间了。

是不是有些神奇?  follow me ^_^

使用LVM2需要三件事:

安装device-mapper库
安装lvm2 tools

在内核中支持device-mapper
注意:以下方法仅适用于2.6.x内核,使用udev或devps管理设备文件。
2.4.x内核请详细查看device-mapper的INSTALL文件。

首先下载device-mapper库以及lvm2 tools:
http://sources.redhat.com/lvm2/ 这里会得到lvm2相关资源信息
ftp://sources.redhat.com/pub/dm/ 这里下载device-mapper库
ftp://sources.redhat.com/pub/lvm2/ 这里下载lvm2 tools
我使用的版本是:LVM2.0-stable.tgz  device-mapper-stable.tgz
ftp://sources.redhat.com/pub/lvm2/LVM2.0-stable.tgz
ftp://sources.redhat.com/pub/dm/device-mapper-stable.tgz

安装device-mapper库,lvm2 tools :
device-mapper-stable.tgz使用如下命令安装:
tar zxvf device-mapper-stable.tgz &&
cd device-mapper.1.00.21/  &&
./configure && make && make install

安装好device-mapper后安装lvm2.0-stable.tgz :
tar zxvf LVM2.0-stable.tgz &&
cd LVM2.2.00.33 &&
./configure && make install

内核中支持device-mapper :
就是这里,害我编译内核十几次,我使用的是2.6.10-mm3支持ReiserFS 4.0的内核
Device Drivers  --->
       [*] Multiple devices driver support (RAID and LVM) ---->
                  <*>   Device mapper support 
                  < >     Crypt target support
                  < >     Snapshot target (EXPERIMENTAL)                
                  < >     Mirror target (EXPERIMENTAL)
                  < >     Zero target (EXPERIMENTAL)

只是支持了Device mapper,没有选择其他的特性。
编译安装好device-mapper lvm-tools 后,使用pvcreate,vgcreate成功的创建了
物理卷(PV),卷组(VG),当使用lvcreate创建逻辑卷(LV)时,出现了"segment fault"

首先怀疑是因为gcc的CFLAGS,CXXFLAGS(优化参数)造成的,于是unset CFLAGS CXXFLAGS
重新编译device-mapper lvm2,仍然出现错误。
难道是内核错误?重新编译内核......

将Device mapper support 下面的全部选择,编译进核心,仍然错误。。。。
编译内核去掉CFLAGS,CXXFLAGS再编译,还是错误。。。。 莫非是整个环境问题?
换到未优化的lfs中,编译。。安装。。。。错误。。。:(

不甘心,换到Mandrake 使用标准2.6.10内核,另一个.config编译,安装。。
竟然成功了!?把这个内核作为两个lfs的内核启动,竟然都正常了!
把成功的.config  拿到2.6.10-mm3中,编译。。。。安装。。。又出错了。。
难道只有在MDK环境编译出来的才可用?
不应该,没道理。  内核版本问题??
mv过来标准的2.6.10内核,编译。。。安装。。。。成功了!!
faint...竟然是2.6.10-mm3内核的问题。。。lvm+ReiserFS 4.0 是不可以了:(
所以这里我建议最好使用标准的内核,不容易出问题。。。。。。。

最终我只选择了<*>  Device mapper support  如果希望使用其他特性
比如pvmove 就要选择Mirror target的支持. 这些特性请查看相关文档. :)

编译好内核,udev/devps就应该会根据/proc/misc中的"Num device-mapper"
在/dev/下 建立mapper目录,并且在目录中建立control这个字符设备。
其设备号由Num决定,如:我的/proc/misc中是:63 device-mapper
则control应该为:
crw-------  1 root root 10, 63 2005-02-10 09:22 /dev/mapper/control

如果你没有这个control就需要手动建立一个:
[root@NEWLFS ~]#cat /proc/misc | grep device-mapper | awk '{print $1}'
得到control的设备号,我的是63.
[root@NEWLFS ~]#mkdir /dev/mapper
[root@NEWLFS ~]#mknod /dev/mapper/control c 10 设备号
基本使用udev/devps管理设备,都会自动建立好这些的。
现在已经编译好了内核,安装好了device-mapper lvm2,一切准备就绪,开始动工:)

先说一下几个需要知道的概念:

来看看LVM的组成:
 hda1   hdc1      (PV:s on partitions or whole disks)
          /                                         
        /                                    
       diskvg        (VG)                          
       /  |                                     
      /   |                                                                   
  usrlv rootlv varlv (LV:s)
    |      |     |                                                             
 ext2  reiserfs  xfs (filesystems)
PV (Physical Volume物理卷):
物理卷可以是整个硬盘(hda),也可以是某个分区(hda1),md(software raid),loop设备....

VG (Volume Group 卷组):
卷组是LVM中最高抽象层,是由一个或多个物理卷所组成的存储器池。

从图中可以看出,卷组是由一个或几个物理卷组成,然后分支成若干个LV.

LV (Logical Volume 逻辑卷):
逻辑卷相当于非LVM系统中的分区,它在卷组上建立
是一个标准的块设备,可以在其上建立文件系统。
+-- Volume Group --------------------------------+
|                                                |
|    +----------------------------------------+  |
| PV | PE |  PE | PE | PE | PE | PE | PE | PE |  |
|    +----------------------------------------+  |
|      .          .          .        .          |
|      .          .          .        .          |
|    +----------------------------------------+  |
| LV | LE |  LE | LE | LE | LE | LE | LE | LE |  |
|    +----------------------------------------+  |
|            .          .        .         .     |
|            .          .        .         .     |
|    +----------------------------------------+  |
| PV | PE |  PE | PE | PE | PE | PE | PE | PE |  |
|    +----------------------------------------+  |
|                                                |
+------------------------------------------------+

PE (Physical Extent物理块):
物理卷按大小相等的"块"为单位存储,块的大小与卷组中逻辑卷块的大小相同。

LE (Logical Extent 逻辑块):
逻辑卷按"块"为单位存储,在一卷组中的所有逻辑卷的块大小是相同的。

OK,基本概念已经了解了,使用lvm基本流程就是:
 初始化物理卷---> 创建卷组,将PV加入到卷组中--->创建逻辑卷---->创建文件系统

1. 初始化物理卷 :
在初始化物理卷之前,我已经清空了/dev/hda5,并且标识分区类型为83(linux分区)
在LVM1中,必须将分区类型标识为8E(LVM分区)才可以使用,lvm2中没有这个限制。

在创建之前,先修改下/etc/lvm/lvm.conf :
# Exclude the cdrom drive
     filter = [ "r|/dev/cdrom|" ]
找到上面两行,将filter前面的#去掉,这样创建LV时就不会搜寻/dev/cdrom了。
不然也很烦,总是提示/dev/cdrom错误。修改好后,执行vgscan命令使生效.
[root@NEWLFS LVM2.2.00.33]#vgscan

使用pvcreate PV1 [PV2.....] 创建物理卷:

[root@NEWLFS mnt]#pvcreate /dev/hda5
Physical volume "/dev/hda5" successfully created
[root@NEWLFS mnt]#

使用 pvdisplay 查看PV详细信息:

[root@NEWLFS mnt]#pvdisplay
  --- Physical volume ---
  PV Name               /dev/hda5
  VG Name               lvm_vg
  PV Size               20.85 GB / not usable 0
  Allocatable           yes
  PE Size (KByte)       4096
  Total PE              5338
  Free PE               4076
  Allocated PE          1262
  PV UUID               y5LlEs-iBIY-t3PU-gTaT-ZIUt-iDmE-b9J9aC

[root@NEWLFS mnt]#

2.创建卷组,并将PV加入到卷组中:

使用vgcreate  VGNAME PV1 [PV2......]创建卷组

[root@NEWLFS mnt]#vgcreate lvm_vg /dev/hda5
  Volume group "lvm_vg" successfully created
[root@NEWLFS mnt]#

使用vgdisplay 查看VG详细信息:

[root@NEWLFS mnt]#vgdisplay
  --- Volume group ---
  VG Name               lvm_vg
  System ID
  Format                lvm2
  Metadata Areas        1
  Metadata Sequence No  3
  VG Access             read/write
  VG Status             resizable
  MAX LV                0
  Cur LV                2
  Open LV               0
  Max PV                0
  Cur PV                1
  Act PV                1
  VG Size               20.85 GB
  PE Size               4.00 MB
  Total PE              5338
  Alloc PE / Size       1262 / 4.93 GB
  Free  PE / Size       4076 / 15.92 GB
  VG UUID               TFjqOG-5aHq-6SUz-q96N-Lu20-GrrP-Qvh2WM

[root@NEWLFS mnt]#

当重新启动或执行vgchange -a n 后,需要重新激活VG,才可以访问VG,LV

[root@NEWLFS mnt]#vgchange -a y lvm_vg
  1 logical volume(s) in volume group "lvm_vg" now active
[root@NEWLFS mnt]#

当关机或不再使用VG时,使用 vgchage -a n VGNAME 使VG不可用。
 
[root@NEWLFS mnt]#vgchange -a n lvm_vg
  0 logical volume(s) in volume group "lvm_vg" now active
[root@NEWLFS mnt]#

3. 创建逻辑卷:

使用lvcreate -L Size -n NAME VGNAME 创建逻辑卷:

[root@NEWLFS ~]#lvcreate -L 2G -n lv_home lvm_vg
  Logical volume "lv_home" created
[root@NEWLFS ~]#

使用lvdisplay 查看LV详细信息:

[root@NEWLFS mnt]#lvdisplay
  --- Logical volume ---
  LV Name                /dev/lvm_vg/lv_usr
  VG Name                lvm_vg
  LV UUID                zrpaw1-vMdI-KvT2-4XlA-2TxZ-4iV8-38fN88
  LV Write Access        read/write
  LV Status              NOT available
  LV Size                2.93 GB
  Current LE             750
  Segments               1
  Allocation             inherit
  Read ahead sectors     0

  --- Logical volume ---
  LV Name                /dev/lvm_vg/lv_home
  VG Name                lvm_vg
  LV UUID                spGvLc-8lOM-CgAi-8XvI-E5Jt-xCce-l4B54K
  LV Write Access        read/write
  LV Status              available
  # open                 0
  LV Size                2.00 GB
  Current LE             512
  Segments               1
  Allocation             inherit
  Read ahead sectors     0
  Block device           253:0

[root@NEWLFS mnt]#
由于我之前已经创建了一个lv_usr 所以这里显示两个LV 
          
最后一步,创建文件系统。这里我使用ReiserFS 3.6.19 :
[root@NEWLFS mnt]#mkreiserfs /dev/lvm_vg/lv_home
..........略
Continue (y/n):y
Initializing journal - 0%....20%....40%....60%....80%....100%
Syncing..ok

Tell your friends to use a kernel based on 2.4.18 or later,
and especially not a
kernel based on 2.4.9, when you use reiserFS. Have fun.

ReiserFS is successfully created on /dev/lvm_vg/lv_home.
[root@NEWLFS mnt]#

创建挂载点,挂载它:
[root@NEWLFS mnt]#mkdir lvm_usr lvm_home
[root@NEWLFS mnt]#mount -t reiserfs /dev/lvm_vg/lv_home lvm_home/
[root@NEWLFS mnt]#df
Filesystem            Size  Used Avail Use% Mounted on
/dev/md0              5.4G  2.8G  2.7G  51% /
/dev/hda1             6.4G  4.0G  2.5G  62% /mnt/C
/dev/hda6              25G   22G  3.6G  86% /mnt/E
/dev/hda7             9.7G  3.7G  5.6G  40% /mnt/lfs
/dev/hda8              99M   18M   76M  20% /boot
/dev/hda10            6.7G  2.9G  3.4G  46% /mnt/mdk
/dev/mapper/lvm_vg-lv_home
                      2.0G   33M  2.0G   2% /mnt/lvm_home
[root@NEWLFS mnt]#

OK,现在已经成功的创建好了逻辑卷,并且使用了ReiserFS,可以投入使用啦。
下一部分说一下 如何管理LVM
原文:http://blog.blogchina.com/category.214692.html


21 02, 2005
红帽ads4安装10.1.0.3小记
作者 xzh2000 17:40 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

1 在用vmgsx3安装ads4时找不到scsi硬盘怎么办?
 在vmgsx3上安装ads3时,用scsi硬盘是支持的,在vmgsx3上安装ads4时,
 如果提示找不到hard drivers时,你创建ide硬盘就可以啦,其它的安装过
 程照ads3的安装即可。
2 自定义安装时选择不安装KDE/GNOME等桌面,安装后发现还是登陆到KDE.
3 红帽ads4使用2.6.9的内核
 # uname -a
 Linux ads4 2.6.9-5.EL #1 Wed Jan 5 EST 2005 i686 i686 i386 GNU/Linux
4 逻辑卷管理LVM的变化
 先前虽然知道lvm从1.0升级到2.0,LVM的管理加强了。
5 ftp不能连接
 这个是由于SELinux的防火墙在起作用,关闭防火墙后ftp登陆正常
 # service iptables stop
6 vnc client不能连接到vncserver
 这个是由于SELinux的防火墙在起作用,关闭防火墙后vnc client登陆正常
7 运行./runInstaller后
 Checking operating system versio failed
 vi /home/oracle/oradata/Disk1/install/oraparam.ini
 [Certified Versions]
 Linux=redhat-2.1,redhat-3,redhat-4,SuSE-9,SuSE-8,UnitedLinux-1.0

其它正常


21 02, 2005
在线生成iptables脚本[转]
作者 xzh2000 16:40 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流
在线生成firewall脚本(iptables)--向导模式
Bifrost - GUI firewall management interface to iptables
http://bifrost.heimdalls.com

LinWiz - Linux configuration file and scripting Wizards
http://www.lowth.com/LinWiz/

GIPTables Firewall - IPTABLES Rules Generator
http://www.giptables.org/

Easy Firewall Generator for IPTables(在线生成复杂的防火墙脚本*****)
http://morizot.net/firewall/gen/

PFG for IPTables 在线生成简单的防火墙脚本***
http://www.thegate.nu/pfg/

Firewall Builder - GUI Firewall Frontend(功能强大的防火墙构建工具*****)
http://www.fwbuilder.org/index.html

______________________________________________________
Dnsmasq - caching DNS forwarder
http://thekelleys.org.uk/dnsmasq/doc.html

FireHOL, the iptables stateful packet filtering firewall builder
http://firehol.sourceforge.net/

BullDog - A comprehensive and progressive firewall
http://tanaya.net/BullDog/
WallFire: wflogs - firewall log analysis tool
http://www.wallfire.org/wflogs/

Ulog-php - a php analyser for netfilter U-log
http://home.regit.org/ulogd-php.html

Firewall Tester
http://ftester.sourceforge.net/

YAFT's Another Firewall Tool
http://sourceforge.net/projects/yaft

Turtle Firewall Project
http://turtlefirewall.sourceforge.net/

TuxFrw - Firewall Automation Tool
http://tuxfrw.sourceforge.net/index.html

Shoreline Firewall
http://www.shorewall.net/
______________________________________
perl firewall在线生成
levy - Perl Firewall Generater
http://muse.linuxmafia.org/levy/
____________________________________
gSshield - BASH Shell Script Configurator
http://muse.linuxmafia.org/gshield.html
_________________________________
流量分析
Mason - Builds from system traffic
http://www.stearns.org/mason/
________________________________________
firewall log分析软件
adcfw-log - firewall logs analyzer/summarizer
http://adcfw-log.sourceforge.net/

IPTables log analyzer
http://www.gege.org/iptables/
_______________________

IPMENU - Curses Firewall Frontend
http://users.pandora.be/stes/ipmenu.html
________________________________
Firelogd - Firewall Log Daemon
http://www.speakeasy.org/~roux/dmn/
firewall log分析软件主页(fireparse)
Fireparse - Firewall Log Parser
http://aaron.marasco.com/linux.html
__________________________________________
SAINT - Assess the Security of Computer Networks
http://www.saintcorporation.com/saint/
saint在linux著名的扫描软件下面那个是下载地址
SATAN - Port Scanner with a Web Interface
http://www.ibiblio.org/pub/packages...atan-for-Linux/
_____________________________________
Abacus - Intrusion Prevention System
http://www.psionic.com/abacus/

Firewall Generator(在线生成简单的防火墙脚本***)
http://www.citadec.com/FirewallGenerator.html
21 02, 2005
dba的二重境界
作者 xzh2000 11:56 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

1 故障快速解决
2 防患未然之间

没心情写,以后再补齐吧。


20 02, 2005
soug ora资料整理的真好
作者 xzh2000 12:42 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流
http://www.psoug.org/reference/
20 02, 2005
Oracle Materialized Views
作者 xzh2000 12:35 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

http://www.psoug.org/reference/materialized_views.html

真是好资料


19 02, 2005
Snort 用户手册[中文]
作者 xzh2000 17:37 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

http://www.linuxfans.org/nuke/modules.php?name=News&file=article&op=view&sid=2592


19 02, 2005
红帽rhce在线测试题
作者 xzh2000 17:24 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
http://www.rhce2b.com/cgi-bin/test/test.pl
18 02, 2005
如何界定long table scan与short table scan?
作者 xzh2000 18:28 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

full scan的时候,其实也是会被放到data buffer cache的RLU 一端的。_small_table_threshold参数决定了当表的超过多少Block时,表就不是小表了。这个参数默认是db_block_buffers * 2%. 就是说,它的大小间接的是由db_block_buffer控制的。 9i 里面,就是db_cache_size或者db_block_size间接决定了。

 查看全文

18 02, 2005
the Oracle usenet FAQ
作者 xzh2000 18:24 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Hosting the Oracle usenet FAQ
www.jlcomp.demon.co.uk/faq/ind_faq.html

很不错的oracle faq。


18 02, 2005
oracle events知识介绍(2)
作者 xzh2000 17:38 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Event 10013 - Monitor Transaction Recovery
This event can be used to trace transaction recovery during startup
For example
    ALTER SESSION SET EVENTS
    '10013 trace name context forever, level 1';
Event 10015 - Dump Undo Segment Headers
This event can be used to dump undo segment headers before and after transaction recovery
For example
    ALTER SESSION SET EVENTS
    '10015 trace name context forever, level 1';
Event 10032 - Dump Sort Statistics
This event can be used to dump sort statistics. Level 10 is the most detailed
For example
    ALTER SESSION SET EVENTS
    '10032 trace name context forever, level 10';
Event 10033 - Dump Sort Intermediate Run Statistics
This event can be used to dump sort intermediate run statistics. Level 10 is the most detailed
For example
    ALTER SESSION SET EVENTS
    '10033 trace name context forever, level 10';
Event 10045 - Trace Free List Management Operations
This event can be used to trace free list management operations
For example
    ALTER SESSION SET EVENTS
    '10045 trace name context forever, level 1';
Event 10046 - Enable SQL Statement Trace
This event can be used to dump SQL statements executed by
a session with execution plans and statistics.
Bind variable and wait statistics can optionally be included.
Level 12 is the most detailed.
For example
    ALTER SESSION SET EVENTS
    '10046 trace name context forever, level 12';
Levels are
Level Action
1 Print SQL statements, execution plans and execution statistics
4 As level 1 plus bind variables
8 As level 1 plus wait statistics
12 As level 1 plus bind variables and wait statistics

Event 10053 - Dump Optimizer Decisions
This event can be used to dump the decisions made by the optimizer when parsing a statement.
Level 1 is the most detailed
For example
    ALTER SESSION SET EVENTS
    '10053 trace name context forever, level 1';
Levels are
Level Action
1 Print statistics and computations
2 Print computations only

Event 10060 - Dump Predicates
This event can be used to force the optimizer to dump predicates to a table It is available in Oracle 7.1.3 and above,
and was still working in Oracle 9.2.
This event requires the following table to be created in the schema of the user parsing the statement
    CREATE TABLE kkoipt_table
    (
        c1 INTEGER,
        c2 VARCHAR2(80)
    );
To enable this event use
    ALTER SESSION SET EVENTS
    '10060 trace name context forever, level 1';
This example uses the following object
    CREATE TABLE t1 (c01 NUMBER, c02 NUMBER);
With event 10060 set to level 1, when the following statement is executed for the first time
    SELECT c01 FROM t1 WHERE c02 = 0;
It is parsed and the results written to kkoipt_table
The results can be selected using the statement
    SELECT c1,c2 FROM kkoipt_table ORDER BY c1;
C1 C2
1 Table:
2 T1
3 frofand
4 "T1"."C02"=0

The following table summarises the various operations that can be reported by this event
Operation Description
fptconst Folding constants
fptrnum Remove ROWNUM predicates
fptwhr Remove all WHERE predicates except remaining ROWNUM predicates
frofkks (rowid lookup) ROWID lookup
frofkks[i] (and-equal lookup) start key
frofkke[i] (and-equal lookup) end key
froiand index-only predicate
frofkksm[i] (sort-merge) sort-merge key
frosand (sort-merge) sort-merge predicates
frojand (sort-merge) join predicates
frofkks[i] (index start key) index start key
frofkke[i] (index stop key) index end key
frofand (hash part) table predicate (hash)
froiand (index only filter) index only predicate
frofand table predicate
froutand outer join predicates

Event 10065 - Restrict Library Cache Dump Output for State Object Dumps
The amount of library cache dump output for state object dumps can be limited using event 10065
    ALTER SESSION SET EVENTS '10065 trace name context forever, level level';
where level is one of the following

Level Description
1 Address of library object only
2 As level 1 plus library object lock details
3 As level 2 plus library object handle and library object

Level 3 is the default
Event 10079 - Dump SQL*Net Statistics
This event can be used to SQL*Net statistics. Level 2 is the most detailed
For example
    ALTER SESSION SET EVENTS
    '10079 trace name context forever, level 2';
Event 10081 - Trace High Water Mark Changes
This event can be used to trace high water mark changes
For example
    ALTER SESSION SET EVENTS
    '10081 trace name context forever, level 1';
Event 10104 - Dump Hash Join Statistics
This event can be used to hash join statistics. Level 10 is the most detailed
For example
    ALTER SESSION SET EVENTS
    '10104 trace name context forever, level 10';
Event 10128 - Dump Partition Pruning Information
This event can be used to partition pruning information
For example
    ALTER SESSION SET EVENTS
    '10128 trace name context forever, level level';
Levels are
Level Action
0x0001 Dump pruning descriptor for each partitioned object
0x0002 Dump partition iterators
0x0004 Dump optimizer decisions about partition-wise joins
0x0008 Dump ROWID range scan pruning information

There are further levels (up to 4096?)
In Oracle 9.0.1 and above, a table must be created before level 2 of this event can be set.
The table definition is as follows
    CREATE TABLE kkpap_pruning
    (
        partition_count     NUMBER,
        iterator            VARCHAR2(32),
        partition_level     VARCHAR2(32),
        order_pt            VARCHAR2(12),
        call_time           VARCHAR2(12),
        part#               NUMBER,
        subp#               NUMBER,
        abs#                NUMBER
    );
Event 10200 - Dump Consistent Reads
This event can be used to dump consistent reads
    ALTER SESSION SET EVENTS
    '10200 trace name context forever, level 1';
Event 10201 - Dump Consistent Read Undo Application
This event can be used to dump consistent read undo application
    ALTER SESSION SET EVENTS
    '10201 trace name context forever, level 1';
Event 10220 - Dump Changes to Undo Header
This event can be used to dump changes to the undo header (transaction table)
    ALTER SESSION SET EVENTS
    '10220 trace name context forever, level 1';
Event 10221 - Dump Undo Changes
This event can be used to dump undo changes applied. Level 7 is the most detailed
    ALTER SESSION SET EVENTS
    '10221 trace name context forever, level 7';
Event 10224 - Dump Index Block Splits / Deletes
This event can be used to dump index block splits and deletes detailed
    ALTER SESSION SET EVENTS
    '10224 trace name context forever, level 1';
Event 10225 - Dump Changes to Dictionary Managed Extents
This event can be used to dump changes to dictionary-managed extents made in the row cache
    ALTER SESSION SET EVENTS
    '10225 trace name context forever, level 1';
Event 10241 - Dump Remote SQL Execution
This event can be used to dump remotely executed SQL statements
    ALTER SESSION SET EVENTS
    '10241 trace name context forever, level 1';
Event 10246 - Trace PMON Process
This event can be used to trace the actions of the PMON background process
This event can only be enabled in the init.ora file using
    event = "10246 trace name context forever, level 1"
The ALTER SYSTEM command does not appear to work for this event
There only appears to be one level for this event (levels 5 and 10 appear to generate the same output as level 1)
Event 10248 - Trace Dispatcher Processes
This event can be used to trace dispatcher processes
This event can be enabled in the init.ora file using
    event = "10248 trace name context forever, level 10"
In Oracle 9.2 (Windows 2000) the trace is written to a file in the udump directory with a name in the format
    ServiceName_dDispatcherNumber_ThreadNumber.trc
e.g.
    JD92001_d000_1234.trc
Valid levels are 1 to 10 (Metalink Note)
Event 10249 - Trace Shared Server (MTS) Processes
This event can be used to trace shared server (MTS) processes
This event can be enabled in the init.ora file using
    event = "10249 trace name context forever, level 10"
In Oracle 9.2 (Windows 2000) the trace is written to a file
in the udump directory with a name in the format
    ServiceName_sSharedServerNumber_ThreadNumber.trc
e.g.
    JD92001_s000_5678.trc
Valid levels are 1 to 10 (Metalink Note)
Event 10270 - Debug Shared Cursors
This event can be used to enable debugging code in shared cursor management modules
    event = "10270 trace name context forever, level 10"
Event 10299 - Debug Prefetching
This event can be used to enable debugging code for table and index block prefetching.
It also enables dumping of trace by the CKPT process.
    event = "10299 trace name context forever, level 1"
Event 10357 - Debug Direct Path
This event can be used to enable debugging code for direct path
    ALTER SESSION SET EVENTS
    '10357 trace name context forever, level 1';
Event 10390 - Dump Parallel Execution Slave Statistics
This event can be used to dump parallel slave statistics
    ALTER SESSION SET EVENTS
'10390 trace name context forever, level level';


Levels are (from messages)
Level Action
0x0001 Slave-side execution messages
0x0002 Coordinator-side execution messages
0x0004 Slave context state changes
0x0008 Slave ROWID range bind variables and xty
0x0010 Slave fetched rows as enqueued to TQ
0x0020 Coordinator wait reply handling
0x0040 Coordinator wait message buffering
0x0080 Slave dump timing
0x0100 Coordinator dump timing
0x0200 Slave dump allocation file number
0x0400 Terse format for debug dumps
0x0800 Trace CRI random sampling
0x1000 Trace signals
0x2000 Trace parallel execution granule operations
0x4000 Force compilation by slave 0

Event 10391 - Dump Parallel Execution Granule Allocation
This event can be used to dump parallel granule allocation/assignment statistics
    ALTER SESSION SET EVENTS
    '10391 trace name context forever, level level';
Levels are (from messages)
Level Action
0x0001 Dump summary of each object scanned in parallel
0x0002 Full dump of each object except extent map
0x0004 Full dump of each object including extent map
0x0010 Dump summary of each granule generators
0x0020 Full dump of granule generators except granule instances
0x0040 Full dump of granule generators including granule instances
0x0080 Dump system information
0x0100 Dump reference object for the query
0x0200 Gives timing in kxfralo
0x0400 Trace affinity module
0x0800 Trace granule allocation during query execution
0x1000 Trace object flush
0x2000 Unknown

Event 10393 - Dump Parallel Execution Statistics
This event can be used to dump kxfp statistics after each parallel query
    ALTER SESSION SET EVENTS
    '10393 trace name context forever, level 1';
Note that in Oracle 9.2 for parallel execution trace is written to files with names of the format
    ServiceName_pServerNumber_ThreadNumber.trc
This is an example of the output for this event.
The output has been modified for readability
kxfpdst        
 dumping statistics       
        ---------------------------                  
                   Query Sessions         1             
              Total Messages Sent         0              
               Data Messages Sent       948        
             Stream Messages Sent       917        
             Dialog Messages Sent        26     
               Null Messages Sent         0   
       Fast Shared Memory Streams       669   
          Fast Distributed Stream         0   
          Stream Mode Credit Ping         0   
             Unknown Credit Pings         0   
              Single Credit Pings       252     
              Double Credit Pings         0      
              Triple Credit Pings         0    
            Multiple Credit Pings         0  
          Total Messages Dequeued         0   
           Data Messages Dequeued        31   
           Null Messages Dequeued         0     
               Immediate Dequeues         1       
                  Posted Dequeues        31       
               Timed-out Dequeues         0     
                Implicit Dequeues       255    
              Total Dequeue Waits        85    
           Total Dequeue Timeouts        44   
        Dequeues for Credit (geb)        77    
        Dequeues for Credit (free)        0   
        Dequeues for Credit (enq)        39
Event 10500 - Trace SMON Process
This event can be used to trace the actions of the SMON background process
This event can be enabled in the init.ora file using
    event = "10500 trace name context forever, level 1"
Event 10608 - Trace Bitmap Index Creation
This event traces bitmap index creation.
    ALTER SESSION SET EVENTS
    '10608 trace name context forever, level 10';
Event 10704 - Trace Enqueues
This event dumps information about which enqueues are being obtained
When enabled it prints out arguments to calls to ksqcmi and ksqlrl and the return values
    ALTER SESSION SET EVENTS
    '10704 trace name context forever, level 1';
Event 10706 - Trace Global Enqueue Manipulation
This event allows RAC global enqueue manipulation to be trace
    ALTER SESSION SET EVENTS
    '10706 trace name context forever, level 1';
The amount of output can be limited using the unsupported parameter '_ksi_trace'.
This parameter specifies the lock types that should be included e.g. TM,
TX etc. They are specified as a string e.g. 'TMTX'
The parameter '_ksi_trace' can only be set in the initialisation file.
Event 10708 - Trace RAC Buffer Cache
This event allows RAC buffer cache activity to be traced
    ALTER SESSION SET EVENTS
    '10708 trace name context forever, level 10';
This diagnostic applies only to RAC clusters (not single-instance)
Event 10710 - Trace Bitmap Index Access
This event traces bitmap index access.
It displays the start ROWID and end ROWID of each bitmap
    ALTER SESSION SET EVENTS
    '10710 trace name context forever, level 1';
Event 10711 - Trace Bitmap Index Merge Operation
This event traces the bitmap index merge operation.
    ALTER SESSION SET EVENTS
    '10711 trace name context forever, level 1';
Event 10712 - Trace Bitmap Index OR Operation
This event traces the bitmap index OR operation.
    ALTER SESSION SET EVENTS
    '10712 trace name context forever, level 1';
Event 10713 - Trace Bitmap Index AND Operation
This event traces the bitmap index AND operation.
    ALTER SESSION SET EVENTS
    '10713 trace name context forever, level 1';
Event 10714 - Trace Bitmap Index MINUS Operation
This event traces the bitmap index MINUS operation.
    ALTER SESSION SET EVENTS
    '10714 trace name context forever, level 1';
Event 10715 - Trace Bitmap Index Conversion to ROWIDs Operation
This event traces the bitmap index conversion to ROWIDs operation
    ALTER SESSION SET EVENTS
    '10715 trace name context forever, level 1';
Event 10716 - Trace Bitmap Index Compress/Decompress
This event traces the bitmap index compress/decompress
    ALTER SESSION SET EVENTS
    '10716 trace name context forever, level 1';
Event 10717 - Trace Bitmap Index Compaction
This event traces the bitmap index compaction.
    ALTER SESSION SET EVENTS
    '10717 trace name context forever, level 1';
Event 10719 - Trace Bitmap Index DML
This event traces the bitmap index DML.
    ALTER SESSION SET EVENTS
    '10719 trace name context forever, level 1';
Event 10730 - Trace Fine Grained Access Predicates
This event traces find grained access (RLS) predicates
    ALTER SESSION SET EVENTS
    '10730 trace name context forever, level 1';
Event 10731 - Trace CURSOR Statements
This event traces CURSOR statements
    ALTER SESSION SET EVENTS
    '10731 trace name context forever, level level';
Levels are
Level Action
1 Print parent query and subquery
2 Print subquery only

Event 10928 - Trace PL/SQL Execution
This event traces PL/SQL execution
    ALTER SESSION SET EVENTS
    '10928 trace name context forever, level 1';
Event 10938 - Dump PL/SQL Execution Statistics
This event dumps PL/SQL execution statistics.
    ALTER SESSION SET EVENTS
    '10938 trace name context forever, level 1';
This event currently generates the following output
--NOTICE  ---------------------------------------
--PL/SQL TRACE INFORMATION IS NOW IN THE DATABASE
-- To create the trace tables, use the script  --
-- rdbms/admin/tracetab.sql under ORACLE_HOME  --


18 02, 2005
oracle events知识介绍(1)
作者 xzh2000 17:19 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

Introduction

There are four types of numeric events

  • Immediate dumps

  • Conditional dumps

  • Trace dumps

  • Events that change database behaviour

Every event has a number which is in the Oracle error message range e.g.

event 10046 is ORA-10046 Each event has one or more levels which can be

  • range e.g. 1 to 10

  • bitmask e.g. 0x01 0x02 0x04 0x08 0x10

  • flag e.g. 0=off; 1=on

  • identifier e.g. object id, memory address etc

Note that events change from one release to another. As existing events become deprecated and then obsolete, the event number is frequently reused for a new event. Note also that the message file sometimes does not reflect the events in the current release.

Many events change the behaviour of the database. Some testing events may cause the database to crash. Never set an event on a production database without obtaining permission from Oracle support. In addition, never set an event on a development database without first making a backup.

Enabling Events

Events can be enabled at instance level in the init.ora file using

    event='event trace name context forever, level level';

Multiple events can be enabled in one of two ways

1 - Use a colon to separate the event text e.g.

    event = "10248 trace name context forever,level 10:10249 trace name context forever,level 10"

2 - List events on consecutive lines e.g.

    event = "10248 trace name context forever, level 10"

    event = "10249 trace name context forever, level 10"

Note that in some versions of Oracle, the keyword "event"

must be in the same case (i.e. always uppercase or always lowercase).

Events can also be enabled at instance level using the ALTER SYSTEM command

    ALTER SYSTEM SET EVENTS

    'event trace name context forever, level level';

Events are disabled at instance level using

    ALTER SYSTEM SET EVENTS

    'event trace name context off';

Events can also be enabled at session level using the

ALTER SESSION command

    ALTER SESSION SET EVENTS

    'event trace name context forever, level level';

Events are disabled at session level using

    ALTER SESSION SET EVENTS

    'event trace name context off';

Events can be enabled in other sessions using ORADEBUG

To enable an event in a process use

    ORADEBUG EVENT event TRACE NAME CONTEXT FOREVER, LEVEL level

For example to set event 10046, level 12 in Oracle process 8 use

    ORADEBUG SETORAPID 8

    ORADEBUG EVENT 10046 TRACE NAME CONTEXT FOREVER, LEVEL 12

To disable an event in a process use

    ORADEBUG EVENT event TRACE NAME CONTEXT OFF

To enable an event in a session use

    ORADEBUG SESSION_EVENT event TRACE NAME CONTEXT FOREVER, LEVEL level

For example

    ORADEBUG SESSION_EVENT 10046 TRACE NAME CONTEXT FOREVER, LEVEL 12

To disable an event in a session use

    ORADEBUG SESSION_EVENT event TRACE NAME CONTEXT OFF

Events can be also enabled in other sessions using

DBMS_SYSTEM.SETEV ,The SID and the serial number of the target session

must be obtained from V$SESSION. For example to enable event 10046

 level 8 in a session with SID 9 and serial number 29 use

    EXECUTE dbms_system.set_ev (9,29,10046,8,'');

To disable event 10046 in the same session use

    EXECUTE dbms_system.set_ev (9,29,10046,0,'');

Listing All Events

Most events are numbered in the range 10000 to 10999.

To dump all event messages in this range use

SET SERVEROUTPUT ON
DECLARE
 err_msg VARCHAR2(120);
BEGIN
 dbms_output.enable (1000000);
 FOR err_num IN 10000..10999
 LOOP
  err_msg := SQLERRM (-err_num);
  IF err_msg NOT LIKE '%Message '||err_num||' not found%' THEN
   dbms_output.put_line (err_msg);
  END IF;
 END LOOP;
END;
/
On Unix systems event messages are in the formatted text file

    $ORACLE_HOME/rdbms/mesg/oraus.msg

To print detailed event messages (Unix only)

use the following script

    event=10000

    while [ $event -ne 10999 ]

    do

        event=`expr $event + 1`

        oerr ora $event

    done

Listing Enabled Events

To check which events are enabled in the current session

SET SERVEROUTPUT ON
DECLARE
  l_level NUMBER;
BEGIN
  FOR l_event IN 10000..10999
  LOOP
    dbms_system.read_ev (l_event,l_level);
    IF l_level > 0 THEN
      dbms_output.put_line ('Event '||TO_CHAR (l_event)||
      ' is set at level '||TO_CHAR (l_level));
    END IF;
  END LOOP;
END;
/


18 02, 2005
红帽ads4下载地址[转贴]
作者 xzh2000 09:03 | Permalink 静态链接网址 | Comments 最新回复 (5) | Trackback 引用 (0) | 技术交流
期待已久的RH AS4已经可以下载了!
非常感谢whowho兄提供的ISO!
whowho兄上传的情况可以在这里看到:
(如果打开是乱码,请选择UTF-8这个编码!)

下载地址1:
ftp://yum.ourlinux.net/iso/redhat/AS/4/RH...86-AS-disc1.iso
ftp://yum.ourlinux.net/iso/redhat/AS/4/RH...86-AS-disc2.iso
ftp://yum.ourlinux.net/iso/redhat/AS/4/RH...86-AS-disc3.iso
ftp://yum.ourlinux.net/iso/redhat/AS/4/RH...86-AS-disc4.iso
ftp://yum.ourlinux.net/iso/redhat/AS/4/md5sum


下载地址2:(感谢attiseve兄)
ftp://219.218.64.9/rhel4/RHEL4-i386-AS-disc1.iso
ftp://219.218.64.9/rhel4/RHEL4-i386-AS-disc2.iso
ftp://219.218.64.9/rhel4/RHEL4-i386-AS-disc3.iso
ftp://219.218.64.9/rhel4/RHEL4-i386-AS-disc4.iso
ftp://219.218.64.9/rhel4/md5

BT下载:
ftp://yum.ourlinux.net/iso/redhat/AS/4.torrent

yum源:
[RH AS4 os]
name=RH AS - 4
baseurl=http://yum.ourlinux.net/redhat/AS/4/i386/RPMS.os

[RH AS4 updates]
name=RH AS - 4
baseurl=http://yum.ourlinux.net/redhat/AS/4/i386/RPMS.updates

apt源:
#for RH AS4
rpm http://yum.ourlinux.net redhat/AS/4/i386 os updates


本文地址:http://www1.ourlinux.net/bbs/showfo...p?showtopic=375
如要转载请注名:碧轩居 - http://www.ourlinux.net

17 02, 2005
红帽ads4发行注记[中文]
作者 xzh2000 18:33 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流
http://yum.ourlinux.net/redhat/AS/4/i386/RELEASE-NOTES-zh_CN.html
17 02, 2005
dbms_utility字串处理示例
作者 xzh2000 14:58 | Permalink 静态链接网址 | Comments 最新回复 (3) | Trackback 引用 (0) | 技术交流

 oracle字串处理示例
 1 将逗号分隔的字串分离出来
 declare
 v_str varchar2(9999);
 mytabl dbms_utility.uncl_array;
 myindx binary_integer;
 begin
 v_str := 'abc,def,ghi';
 dbms_utility.comma_to_table(v_str,myindx,mytabl);
 for i in 1..myindx loop
   dbms_output.put_line(mytabl(i));
 end loop;
 --dbms_output.put_line(myindx);
end;
/
abc
def
ghi

2 将数组中的字符用逗号分隔组成字符串
 declare
 mylist dbms_utility.uncl_array;
 mytabl varchar2(4000);
 myindx binary_integer;
 begin
 mylist(1) := 'abc';
 mylist(2) := 'def';
 mylist(3) := 'ghi';
 dbms_utility.table_to_comma(mylist,myindx,mytabl);
 dbms_output.put_line(mytabl);
end;
/
abc,def,ghi


17 02, 2005
从rdb求出file_id与block_id
作者 xzh2000 14:35 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

如何从一个rdb求出file_id与block_id?
 select to_number('&RDB_HEX','xxxxxxxx') from dual;
 select dbms_utility.data_block_address_file(&RDB_DEC) from ;
 select dbms_utility.data_block_address_block(&RDB_DEC) from dual;
 select dbms_utility.make_data_block_address(&file_id,&block_id) from dual;

从alter system dump ....... 出的信息中将rdb分解成file_id与block_id


16 02, 2005
sqlplus的高级技巧[精]
作者 xzh2000 16:22 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流


 可以看看rdbms/admin/spreport及awrrpt这两个脚本

 示例:
 spool x.lst
 set heading off
 column dscr format a28 newline;
 column val  format a10 just r;
 select 'Cache Sizes (end)'                                          dscr
    , '~~~~~~~~~~~~~~~~~'                                          dscr
    , '               Buffer Cache:'                               dscr
    , lpad(to_char(round(889192448/1024/1024),'999,999') || 'M', 10)     val
    , '     Std Block Size:'
    , lpad(to_char((8192/1024)          ,'999') || 'K',10)          val
    , '           Shared Pool Size:'                              dscr
    , lpad(to_char(round(134217728/1024/1024),'999,999') || 'M',10)      val
    , '         Log Buffer:'
    , lpad(to_char(round(1048576/1024)     ,'999,999') || 'K', 10)     val
 from sys.dual;
 spool off
 set heading on
 领会newline/just/dscr/val等的使用。


16 02, 2005
消除oracle使用swap分区
作者 xzh2000 14:35 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
如何消除oracle使用swap分区
关于oracle使用swap的问题,很难用oracle的相关技术来度量,
用sar -B来度量的话,很难确定是什么引起了swap的使用,如果
机器上只跑oracle的话,那就只有从oracle方面进行考虑swap
的使用问题,如果你的os使用swap,可以从以下方面考虑:
1 可能是sga/pga(sort_area_size)分配不合理引起的
2 可能是sql语句被大量的aged out引起的
3 可能是sql性能太差引起大量的数据被aged out引起的
4 可能是事务(大事务)没有及时提交引起的
通常使用swap的系统,有可能是上面某种情况引起的,有可能是三
种情况都有,所以问题只能是一点点地隔离;针对第一种情况,我们
要分析statspack报表,为pga/sga设置一个比较合理的大小;针
对第二种情况,需要对sql进bind var或将cursor_sharing参
数设置为force或similar即可;针对第三种情况,需要对sql进行
优化,减少sql的物理读等;第四种情况需要修改业务实现,及时对
事进行提交。
16 02, 2005
oracle中md5加密函数
作者 xzh2000 11:12 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流
CREATE OR REPLACE function md5(input_string VARCHAR2) return varchar2
IS
raw_input RAW(128) := UTL_RAW.CAST_TO_RAW(input_string);
decrypted_raw RAW(2048);
error_in_input_buffer_length EXCEPTION;
BEGIN
--dbms_output.put_line(sysdate || '> 加密前的数据:' || input_string);
sys.dbms_obfuscation_toolkit.MD5(input => raw_input,
checksum => decrypted_raw);
--dbms_output.put_line(sysdate || '> 加密后的数据:' || rawtohex(decrypted_raw));
return lower(rawtohex(decrypted_raw));
END;
15 02, 2005
redhat ads4更新介绍[转]
作者 xzh2000 23:32 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Red Hat Enterprise Linux 4.0--The Enterprise Gets An Update

http://www.linuxplanet.com/linuxplanet/print/5745/

内容要点
1. RHEL, redhat 的企业版本
由于 redhat 对软件开发过程的支持,以及对企业用户的完备服务,使得 RHEL 非常有价值,满足了不同对象的需求
2. RHEL 的分类
AS, ES, WS 侧重不同的硬件软件环境
3. 安装过程
图形界面,与 fedora 3 类似,默认使用 lvm。提供了包含 IBM JRE, BEA JRockit, acrobat reader, realplayer, flash, Agfa monotype fonts, Citrix ICA client for Unix, firmware for the Intel 2100 and 2200 wireless adapters, 以及 AT&T's Korn shell 的附加 CD
4. 主要软件包
CUPS 1.1.22, Evolution 2.0.2, Firefox 1.0, GCC 3.4.3, GDB 6.1, GNOME 2.8.0, KDE 3.3.1, Kernel 2.6.9, OpenOffice 1.1.2, OpenLDAP 2.2.13, OpenSSL 0.9.7a, Perl 5.8.5, Python 2.3.14, Ruby 1.8.1, X11(X.org) 6.8.1, Apache 2.0.52, PHP 4.3.9, NFS V4, automounter 4.1, Samba 3.0.10, LVM 2, MySQL 4.1.7, Postgresql 7.4.6, Cyrus IMAPD 2.2.10, exim 4.43, Postfix 2.1.5, Sendmail 8.13, spamassassin 3.0.1, mailman 2.1.5, tons of games
5. 有关 2.6 内核的备注
模块的变化 (.ko), audit, SELinux


引用:
osnews 给出的另一篇文章(newsforge)的链接和部分内容

Red Hat lacks integrated virtualization features like those found in SUSE Linux Enterprise Server 9 and Solaris 10, and it's more than three times the price of the comparably featured Mandrakelinux Corporate Server 3.0. But Red Hat's most dangerous competition may not be from outside companies, but from its own community distribution. We won't do an in-depth comparison with these distros, as their usefulness is dependent on your specific situation, preference, training, and infrastructure.

Manufacturer Red Hat Inc.
Architectures i386, IA64, AMD64/EM64T, IBM zSeries, S/390 series, and POWER series
License GNU General Public License
Market Enterprise computing, from desktops up to high-end servers
Price (retail) Varies dependent on edition and subscription length
Previous version Red Hat Enterprise Linux 3
Product Web site http://www.redhat.com/software/rhel/


----
Red Hat Enterprise Linux 4.0--The Enterprise Gets An Update

By: Bill von Hagen
Monday, February 14, 2005 12:05:15 AM EST
URL: http://www.linuxplanet.com/linuxplanet/reviews/5745/1/

Enterprise Linux and Red Hat

Red Hat is not only one of the oldest and best known Linux distributions, but is probably the one that has the most traction in the business community thanks to smart people, clever marketing, a steady stream of advertisements, and the introduction of some of the concepts that people take for granted in the commercial Linux space. Many Linux distributions, such as Red Hat, SUSE, Mandrakelinux, and even the ill-fated Caldera Linux distribution, have offered server and desktop products for years, but Red Hat was the first to make a lot of noise about "Linux for the Enterprise," pioneering the label, if not the concept.

Enterprise Linux vendors have to walk the tightrope between providing stable and up-to-date versions of the software packages required in enterprise deployments. Stability is an interesting notion in the Open Source world. On the one hand, you have the legions of dedicated and capable developers who are continually identifying and fixing problems in Open Source software.

On the other hand, you have Linux distribution vendors who are doing the same thing themselves, either by committing resources directly to supporting various software packages or by incorporating patches from the Open Source community. Either way, this is still a net win over proprietary software with a single possible source, a black-box approach to software deployment, and painfully slow release and update cycles.

Red Hat's focus on the Enterprise has had different effects on the desktop and enterprise communities. Desktop users who had previously committed to Red Hat have been split into two communities. One of these is made up of users who feel rejected, are disconcerted about desktop support, and have therefore largely gone elsewhere for supported desktop Linux products.

The flip side of this is the users who are taking advantage of the momentum of the Fedora project and the expertise of its contributors to keep moving forward with the descendant of a popular and widely-used distribution. In enterprise deployments, there's always Red Hat EL Desktop, which is attractive for support reasons and little else.

In the enterprise, most large organizations, except perhaps those with a huge existing commitment to the distribution formerly known as Red Hat N (now end-of-lifed), have seen Red Hat's Enterprise focus as a tremendous win because this has brought enterprise applications vendors such as Oracle into the Linux fold. Businesses can count on Red Hat for enterprise-caliber support and can therefore safely commit to adopting Linux as the heart of their infrastructure without having to worry that they may always have to retain legions of hackers chained in the basement.

Conservative release cycles and a more exhaustive test cycle make Red Hat Enterprise Linux a safer bet for the business community--they don't have to chase the release of the week. And finally, Red Hat's well-known and thoroughly advertised certification and training programs guarantee a certain level of competency and provide the kinds of data points that HR personnel and MIS/IT managers can identify on during the hiring process even if they don't personally know the right questions to ask.

Summary of Red Hat Enterprise Products

Red Hat provides four different products for the Enterprise. Their different server products are identified by two-letter combinations that are supposedly not acronyms, but which I will expand anyway because it's easier to remember them if you have some sort of mnemonic. At the top of the pyramid is Red Hat Enterprise Linux AS, which I think of as their Application server product. Red Hat AS supports systems with up to 16 CPUs and 64GB of main memory. We received a pre-release of the 4.0 version of this product for this review. Red Hat AS is server-rich and comes with various Java bells and whistles that are discussed later in this review.

Moving down the Enterprise Linux food chain is Red Hat Enterprise ES, which I think of as their Enterprise Server product. It supports systems with up to 2 CPUs and 8GB of main memory, and is targeted towards small or medium-sized business server systems who use it to run network, file, print, mail, and Web servers. Next, crossing into the desktop space, is Red Hat Enterprise Linux WS, which I think of as Red Hat Workstation.

WS supports systems with up to 2 CPUs, but does not provide many of the software servers that the higher-level products include. The list of missing servers include FTP, OpenLDAP, DNS/bind, TFTP, PXE, and INN. At the bottom of the Enterprise line comes the RHEL Desktop product, which is sold in quantities of 10, 50, and presumably higher numbers if you'd like. This is designed to run on single-CPU systems with up to 4GB of memory. It includes the things you expect to see on Linux equivalent of a Windows desktop--a mail client (evolution), an office productivity suite (OpenOffice), an instant messenger client (GAIM), a Web browser (Mozilla, currently), and other standards like Adobe Acrobat, Real Player, MacroMedia Flash support, and so on.

Installing RHEL 4

Red Hat Enterprise Linux 4 features a graphically updated version of the familiar Red Hat installation process consisting of two phases. In the first phase, you supply basic information about your system's location and nationalization, specify disk partitioning, select the basic type of installation that you want to perform and any additional packages that you want to install. In the second phase, you confirm the date and time, create user accounts, register with Red Hat Network in order to receive updates, and optionally install additional packages from CD #5, the Red Hat Extras CD. Figure 1 shows the Welcome screen from the RHEL AS 4.0 installer.

One exceptionally clever notion adopted from the Fedora Project is the use of logical volumes in RHEL's default disk partitioning suggestions. Figure 2 shows the default partitioning scheme proposed by the installer on a small system disk. I've appreciated this in Fedora, but it makes even more sense in enterprise deployments where disk space requirements almost always expand and downtime for adding disk space must be kept to a minimum. Using logical volumes by default makes it easy to bring down a system for scheduled maintenance, add new disk drives, and dynamically integrate the space that they provide once the system is running again. The alternative of manually cloning the contents of a partition to another and swapping the partitions during additional downtime is painfully primitive by comparison. More Linux distributions should take this enlightened, sysadmin-sensitive approach to default disk allocation and assignment.

Unlike the Red Hat N products of old, Red Hat EL AS doesn't provide a variety of default installation configurations, which is understandable because of its more focused audience. Your choices are to install the default set of packages or to customize the list of packages that you're installing. I typically do the latter and select "Everything" as my package list because disk space is much cheaper than my time when I find that I'm missing some package on my application server and have to hunt down the CDs, install and configure, and so on.

The Extras CD provided with Red Hat EL AS features an interesting choice of third-party packages divided into three sections--Java and Java Utilities, Multimedia, and Miscellaneous. Your Java choices consist of various selections that make up the IBM Runtime environment and Development kit and the BEA's WebLogic JRockit management console, plugins, and runtime. The Multimedia section contains Adobe Acrobat, Real's RealPlayer, and and Macromedia's Flash plugin. The Miscellaneous section contains Agfa Monotype fonts, the Citrix ICA client for Unix, firmware for the Intel 2100 and 2200 wireless adapters, and AT&T's Korn shell. Miscellaneous, indeed!

What's in the Box

One complaint commonly raised against RHEL is that it lags far behind the state-of-the-art in terms of Linux software. Conservative, well-tested releases are a requirement of a true enterprise Linux distribution, both so that no inconsistencies or problems are introduced into corporate infrastructure and to facilitate the longer product support provided for enterprise editions. At the same time, enterprise distributions need to provide a mechanism for keeping up with fundamental improvements in system software. Some of the versions of software provided with RHEL 3.0, such as OpenLDAP, were old enough that they did not support new and up-to-date features that system administrators need to use this in enterprise deployments. RHEL 4.0 corrects most of these sorts of problems, including a move to the more scalable and powerful 2.6 Linux kernel, but the underlying update/upgrade problem still needs to be addressed beyond vulnerability and bug fixes, which Red Hat seems to do a good job of keeping up with.

The following table shows the versions of some of the most popular GNU/Linux software packages found in Red Hat Enterprise Linux 4.0. For those perhaps new to Linux, this table lists the versions of commonly-used applications and system services such the Common Unix Print Server (CUPS) Evolution mail client, the GCC and GDB packages for compilation and debugging, the GNOME desktop system and the underlying X Window System, the Perl, Python, and Ruby scripting languages, authentication and security packages such as OpenLDAP and OpenSSL, the Open Office desktop office software package, the Linux kernel itself.
Package RHEL 4.0 Version
CUPS 1.1.22
Evolution 2.0.2
Firefox 1.0
GCC 3.4.3
GDB 6.1
GNOME 2.8.0
KDE 3.3.1
Kernel 2.6.9
OpenOffice 1.1.2
OpenLDAP 2.2.13
OpenSSL 0.9.7a
Perl 5.8.5
Python 2.3.14
Ruby 1.8.1
X11(X.org) 6.8.1

Figure 3 shows the default GNOME 2.8 desktop provided by Red Hat Enterprise Linux 4.

From the Web server point of view, RHEL4 provides httpd (Apache) version 2.0.52, with version 4.3.9 of the PHP scripting language and version 2.01 of the cool webalizer software for analyzing web logs and displaying traffic statistics. I didn't try any of the well-known exploits against PHP 4.3.9, but I suspect that an update will be coming soon for that particular package if Red Hat hasn't already patched them into their version. You should do some testing of this before some random Root Crew shows up and gives your brand new site an unwanted face lift.

From the file server point of view, RHEL 4 supports NFS V4, version 4.1 of the autmounter, and version 1.0.6 of the NFS support utilities. It provides Samba version 3.0.10 and supports version 2.00 of the updated Logical Volume Manager LVM2. I was somewhat disappointed with the fact that RHEL 4.0 does not include the utilities for managing the JFS, ReiserFS, or XFS journaling filesystems on local storage. Apparently, Red Hat believes that EXT3 is the only journaling filesystem suitable for managing local storage in the Enterprise. This is clearly untrue, but RHEL doesn't seem to provide any alternatives if you still want to get product support.

Open Source database fans should be happy that RHEL 4.0 provides MySQL 4.1.7 and Postgresql 7.4.6, along with modern versions of the ODBC connectors for each. RHEL 4.0 is also replete with a rich assortment of mail servers, providing Cyrus IMAPD 2.2.10, exim 4.43, Postfix 2.1.5, and Sendmail 8.13. Associated software includes version 3.0.1 of spamassassin for anyone who is deploying any of these mail servers, and includes version 2.1.5 of mailman for creating and managing mailing lists.

As a side note, if you do a custom install of RHEL4 and install everything, it installs a ton of games, which is somewhat surprising in the enterprise Linux Application Server market. However, if your 32-GB 8-CPU application server is under-utilized, you can always play a mean game of battleship (Kbattleship) on the console while configuring services and run-levels, as shows in Figure 4.

RHEL4 and 2.6 Kernel Notes for Sysadmins

The 2.6 Linux kernel has brought many general improvements to Linux system performance, capabilities, and capacity. The most commonly-noted of these are performance and responsiveness improvements, support for greater amounts of memory, better processor utilization and scaling in SMP environments, and integrated support for newer devices and interfaces such as Serial ATA. However, beyond these pleasant and immediately-noticeable improvements, many internal and system-level changes have occurred that enterprise system administrators should be aware of. RHEL4 and the 2.6 kernel provide many other improvements to administrative tools and capabilities - this section highlights my favorites.

Some of the most immediately visible and important changes introduced by the 2.6 Linux kernel are changes to loadable kernel module (LKM) naming conventions, internals, and build models. LKMs now end with the .ko extension (kernel object) to differentiate them from standard object files, have a simpler Makefile/build structure, and can more easily be built outside the kernel source by simply referring to the base location of a writable kernel source tree. If you are currently using devices whose drivers were supplied by a hardware or software vendor, you will need to obtain 2.6 versions of those drivers (assuming that they have not been folded into the official 2.6 kernel source).

Beyond server improvements and enhancements, RHEL4 and the 2.6 kernel give system administrators new levels of access control and system event monitoring. By using a recent version of the 2.6 kernel, RHEL4 introduces support for the light-weight auditing framework that provides interfaces that lower the overhead of providing audit information from the kernel and system applications. I couldn't find the audit daemon or associated applications on RHEL4, but at least the framework is present in the kernel--mechanisms for taking advantage of it can be distributed and RHEL4 updates, I suppose.

More importantly (and usable immediately), RHEL4 supports Security-Enhanced Linux (SELinux), which can be deactivated during the install process but is active by default. SELinux provides a variety of mechanisms for implementing and enforcing access control policies, including those based on the type of object being accessed (type-based) or on the role of the user attempting to access an object (role-based, commonly known as Role-Based Access Control, RBAC). SELinux access control policies operate outside the standard Linux protection and access control mechanisms, and are designed to limit user programs and system servers to the minimum privileges that they require in order to perform their tasks. A correct SELinux policy implementation can go a long way towards limiting the potential damage that can be done by exploiting server or application vulnerabilities through common techniques such as buffer overflows.

Wrapping Up

RHEL4 is a huge step forward for Red Hat and should be a breath of fresh air to businesses who require the stability and support associated with and enterprise Linux distribution, but desperately needed or wanted new versions of the kernel, servers, and applications. If you were waiting for newer features or software to appear in the Enterprise Linux space, Red Hat Enterprise Linux 4 is well worth a look. If you're already a RHEL customer, run, don;t walk, to your support representative for an upgrade.

Bill von Hagen is the author of numerous books and articles on Linux. For more information about Bill, see http://www.vonhagen.org.

Copyright © 1999 internet.com Corp. All Rights Reserved.

14 02, 2005
分区表可创建多少个分区
作者 xzh2000 15:01 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Tables can be partitioned into up to 64,000 separate partitions. Any table can be partitioned except those tables containing columns with LONG or LONG RAW datatypes. You can, however, use tables containing columns with CLOB or BLOB datatypes.  查看全文
04 02, 2005
Linux下c开发Oracle应用
作者 xzh2000 18:37 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

随着Linux操作系统的不断完善与发展,出现了大量基于Linux平台的应用开发,原有的基于UNIX平台的商业软件也不断被移植到Linux上来。最典型的,Oracle公司宣布,他的现有的及未来所有的数据库产品和商业应用都将支持Linux平台。本文所述OCI for Linux的C语言,我们知道,在一个复杂的Oracle数据库应用中,C程序代码由于其语言本身的灵活性、高效性,往往被加入到其商务逻辑的核心层模块中。Oracle数据库对C语言的接口就是OCI(Oracle Common Interface) C-Library,该库是一个功能十分强大的数据库操作模块。它支持事务处理,单事务中的多连接多数据源操作,支持数据的对象访问、存储过程的调用等一系列高级应用,并对Oracle下的多种附加产品提供接口。但是我们发现,为了使OCI库在多种平台上保持统一的风格并考虑向下兼容性,Oracle对大量的C语言类型和代码进行了重新封装,这使得OCI库初看上去显得纷繁复杂,初用者不知从何下手。由Kai Poitschke开发的Libsqlora8库初步解决了这一问题,它使得在Linux下Oracle的非高端C语言开发变得比较方便.Libsqlora8 for *nix是GNU/Linux组织开发的针对Oracle8 OCI library的易用性C语言封装。它将大量的OCI数据类型表现为通用C语言数据类型,将OCI函数按类型重新分类封装,大大减少了函数的调用步骤和程序代码量。Libsqlora8还有许多引人注目的特性:
  易于使用的动态SQL特性;
  同一连接中具有不同变量绑定的游标的重复打开;
  相同事务中的多数据库连接;
  Oracle数据库应用开发中的Build-in trace功能;
  正确处理数据插入操作中的数组变量问题;
  多平台支持Oracle 8.0.4(HP-UX 9), Oracle 8.05(GNU/Linux), Oracle
  可以作为静态或动态形式链接进入应用程序。
  分步骤详细阐述如何在Linux平台上利用Libsqlora8函数库开发Oracle数据库应:
  1.安装Linux操作系统,并对新系统进行适当的系统配置。在本例中我们选用RedHat Linux 6.2操作系统。在为系统分区时,我们为Oracle数据库专门分出两个分区:/u01,/u02,作为Oracle数据库的系统软件和数据库文件的安装点。安装好系统后,我们为系统增添两个新组:oinstall和dba,并创建一个新用户Oracle,他拥有整个数据库系统软件。这里就不详细说
  2.下面我们应该安装Oracle数据库了,这次我们选用Oracle 8.1.6版本,该版数据库对国际化有很好的支持。在安装数据库之前,我们要先对Oracle用户进行一些设置。主要是在该用户的启动脚本中,加入一些必要的环境变量,在本例中可以如下设置:
  ORACLE_BASE=/u01/app/oracle
  ORACLE_HOME=$ORACLE_BASE/product/8.1.6
  ORACLE_SID=oratest
  PATH=$ORACLE_HOME/bin:/usr/bin:/etc:/bin
  LD_LIBRARY_PATH=$ORACLE_HOME/lib
  export ORACLE_BASE ORACLE_HOME ORACLE_SID PATH

  3.Oracle 8.1.6的数据库安装是比较简单的,我们选择缺省安装,在系统的提示下逐一完成安装过程。注意,Oracle8i对系统的要求是比较高的,特别是内存,在一些特殊应用中,要修改系统的缺省设置以提高数据库性能。有关数据库调优的讨论与本文无关,在此就不再详细介绍了。启动数据库,好了,现在我们可以用sqlplus登录数据库,可以看到,缺省安装的Oracle数据库有一类OCITest数据库表,就使用这些表作为我们例子中的缺省表。
  4.安装Libsqlora8库函数。该库函数当前版本为Libsqlora8-2.1.5,可从许多Linux网站上得到,也可从http://www.china-linux.org上下载libsqlora8-2.1.5.tar.gz源程序包。按以下步骤安装:
  $>tar -xzvf libsqlora8-2.1.5.tar.gz
  对于要使用Oracle build-in trace功能的开发者,还要将以下环境变量设置好,SQLORA_TRACE_LEVEL,SOLORA_TRACE_FILE,SQLORA_ARRAYSIZE,当然,ORACLE_SID是一定要
  5.下面,我们介绍一下Libsqlora8的主要函数。
  1)int sqlo_init(int threaded_mode) 初始化程序库接口,读出环境变量,设置相应的
  2)int sqlo_connect(int * dbh, char * connect_str) 连接数据库,dbh为数据库连接
  3)int sqlo_finish(int dbh) 断开数据库连接。
  4)int sqlo_open(int dbh, char * stmt, int argc, char *argv[]) 打开由stmt确定的
查询语句所返回的游标。Argc,argv为查询的参数,后面我们将用更清晰的方法传递参数。
  5)int sqlo_close(int sth) 关闭由上一个函数打开的游标。
  6)int sqlo_fetch(int sth) 从打开的游标中获取一条记录,并将之存入一个已分配内存
  7)const char **sqlo_values(int sth, int *numbalues, int dostrip) 从内存中返回
上一次sqlo_fetch取得的值,是以字符串形式返回的。
  8)以下介绍另一种检索方式,int sqlo_prepare(int dbh, char const *stmt),返回一
  9)int sqlo_bind_by_name(int sth, const char * param_name, int param_type,
const void * param_addr, unsigned int param_size, short * ind_arr, int is_array)
将查询语句的传入参数,按照名字的形式与函数中的变量绑定。如果你使用数组,那么参数
  int sqlo_bind_by_pos(int sth, int param_pos, int param_type, const void *
param_addr, unsigned int param_size, short * ind_arr, int is_array) 将查询语句的传
  10)int sqlo_execute(int sth, int iterations) 执行查询语句。“Iterations”可设
  11)在执行完数据库操作后,我们可用int sqlo_commit (int dbh)提交操作,或用int
  12)Libsqlora8还有其他一些操作函数,这里就不一一列出了。
  下面举几个例子说明这些函数如何使用。
  cstr = "ocitest/ocitest"; //用户名/口令
  status = sqlo_init(0);
  if (SQLO_SUCCESS != status)
  { printf ("sql_init failed. Exitingn");

  exit(1);
  }
  status = sqlo_connect(&dbh, cstr); // int dbh
  以上源代码,显示了如何连接数据库。
  /* Select all and display */
  char *select_stmt="SELECT cname, clength, colid FROM ocicolu";
  if (0>(sd = sqlo_open(dbh, select_stmt, 0, NULL)))
  { printf("sqlo_open failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  while (0 == sqlo_fetch(sd,1))
  { v = sqlo_values(sd, NULL, 1);
  printf("Result: %sn",v);
  }   if (0 > sqlo_close(sd))
  { printf("sqlo_open failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  以上例子展示了第一种查询方法,显然,这种方法较简单,但不够灵活。
  char *update_stmt =
  "UPDATE ocitest.upload_log SET upload_fresh = where log_name = :1";
  if (0 <= (sth = sqlo_prepare(dbh, update_stmt)))
  { if (SQLO_SUCCESS !=
  (sqlo_bind_by_name(sth, ":1", SQLOT_STR, packet_name, 64, NULL, 0)
  ))
  { printf("sqlo_bind_param failed failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  }
  if (SQLO_SUCCESS != sqlo_execute(sth, 1))

  { printf("sqlo_execute failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  上面的代码显示了如何通过名字绑定变量,“:1”在Oracle SQL语句中表示为一个变量
(名字随意),在sqlo_bind_by_name函数中与packet_name变量绑定。在变量绑定完毕后,就
  好了,我们已经向大家介绍了Libsqlora8的基本使用方法,如果希望了解更多内容,
Libsqlora8的程序包中带有详细的说明和例子,大家不妨自己钻研一下。有什么心得,欢迎和
  /*--------------------------------------------
  * testlora.c
  * Test programm for libsqlora8(Kai Poitschke)

  * Assuming you installed the library with prefix=/usr/local, the command
  * to compile this is:
  * gcc -o sample sample.c -lsqlora8 -L$ORACLE_HOME/lib -lclntsh
  *-------------------------------------------*/
  #include
  #include "sqlora.h"
  #define MAX_ITERS 10
  #define MAX_LOOPS 1 /* how many time we run the tests */
  #define CLOSE_CURSOR 1
  /*-----------------------------------------
  * create our test table
  *-----------------------------------------*/
  int create_table( int dbh )
  {
  int nkey;
  char ckey[6];
  double nval;
  char cval[21];
  char dval[11];
  int sth;
  char * create_table =
  "CREATE TABLE T_SQLORA_TEST (n"
  "NKEY NUMBER(8) NOT NULL,n"
  "CKEY VARCHAR2(5) NOT NULL,n"
  "NVAL NUMBER(16,4) NULL,n"
  "CVAL VARCHAR2(20) NULL,n"
  "DVAL DATE)";
  /* Check if the table already exists */
  if (SQLO_NO_DATA ==
  sqlo_exists(dbh, "USER_TABLES", "TABLE_NAME", "T_SQLORA_TEST", NULL))
  {
  /* No, create it */
  if (SQLO_SUCCESS != sqlo_exec(dbh, create_table))
  {
  printf("create_table failed: %sn%sn", sqlo_geterror(dbh),
  create_table);
  return 0;
  }
  printf("Table T_SQLORA_TEST createdn");

  }
  return 1;
  }
  /*----------------------------------------------------
  * Query the test table
  *---------------------------------------------------*/
  int do_select( int dbh )
  {
  int sd;
  const char **v;
  int argc;
  const char *argv[1];
  char * select_stmt = "SELECT DVAL FROM T_SQLORA_TEST WHERE NKEY >= :1";
  argc = 0;
  argv[argc++] = "0";
  /* Select all and display */   if (0>(sd = sqlo_open(dbh, select_stmt, argc, argv)))
  {
  printf("sqlo_open failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  /* sqlo_print(sd);*/
  while (0 == sqlo_fetch(sd,1))
  {
  v = sqlo_values(sd, NULL, 1);
  printf("%4s%6s%19s%21s%11sn", v[0], v[1], v[2], v[3], v[4]);
  }
  #ifdef CLOSE_CURSOR   if (0 > sqlo_close(sd))
  {
  printf("sqlo_open failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  #endif
  return 1;
  }
  /*---------------------------------------------------
  * Select with prepare/execute/fetch.
  *-------------------------------------------------*/
  int test_select2( int dbh )
  {
  int sth;
  int nkey[MAX_ITERS];
  char ckey[MAX_ITERS][6];
  double nval[MAX_ITERS];
  char cval[MAX_ITERS][21];
  char dval[MAX_ITERS][11];
  int wc = 1;
  int status;
  int i;
  short nkeyl[MAX_ITERS];
  short ckeyl[MAX_ITERS];
  short nvall[MAX_ITERS];
  short cvall[MAX_ITERS];
  short dvall[MAX_ITERS];
  int rows_fetched = 0;
  int rows_fetched_total = 0;
  int rows_to_fetch;
  int done_fetching = 0;
  char * select_stmt = "SELECT DVAL FROM T_SQLORA_TEST WHERE NKEY >= :1";
  printf("Test select via classic methodsn");
  /* Select all and display */   if (0>(sth = sqlo_prepare(dbh, select_stmt)))
  {
  printf("sqlo_prepare failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  /* Bind input */
  if (SQLO_SUCCESS !=
  (sqlo_bind_by_name(sth, ":1", SQLOT_INT, &wc, sizeof(int), NULL, 0)))
  {
  printf("sqlo_bind_by_name failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  /* Define Output */
  if (SQLO_SUCCESS !=
  (sqlo_define_by_pos(sth, 1, SQLOT_INT, nkey, sizeof(int),0,nkeyl, 1) ||
  sqlo_define_by_pos(sth, 2, SQLOT_STR, ckey[0], 6, 0, ckeyl, 1) ||
  sqlo_define_by_pos(sth, 3, SQLOT_FLT, nval, sizeof(double),0,nvall,1) ||
  sqlo_define_by_pos(sth, 4, SQLOT_STR, cval[0], 21, 0, cvall, 1) ||
  sqlo_define_by_pos(sth, 5, SQLOT_STR, dval[0], 11, 0, dvall, 1)))
  {
  printf("sqlo_define_by_pos failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  rows_to_fetch = 3;
  rows_fetched = rows_to_fetch;
  status = sqlo_execute(sth, rows_to_fetch);

  {
  printf("sqlo_execute failed: %sn", sqlo_geterror(dbh) );
  return(0);
  }
  else if (status == SQLO_NO_DATA)
  {
  /* arrays were filled fully. Get rowcount */

  rows_fetched = sqlo_prows(sth);
  done_fetching = 1;
  printf("Execute fetched all %d rowsn", rows_fetched);
  printf("Fetched all in one gon");
  for (i = 0; i < rows_fetched; ++i)
  {
  printf("%3d %5s %19f %20s %10sn",
  nkey, ckey, nval, cval, dval);
  }
  }
  for (i = 0; i < rows_fetched; ++i)
  {
  if (!i)
  printf("Execute fetched %d rowsn", rows_fetched);
  printf("%3d %5s %19f %20s %10sn",
  nkey, ckey, nval, cval, dval);
  }
  rows_fetched_total += rows_fetched;
  rows_to_fetch = 4;
  while(!done_fetching)
  {
  rows_fetched = rows_to_fetch;
  status = sqlo_fetch(sth, rows_to_fetch);

  {
  printf("sqlo_fetch failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  if (status == SQLO_NO_DATA)
  {
  rows_fetched = sqlo_prows(sth);
  if (rows_fetched_total == rows_fetched)

  {
  /* no new fetches */
  done_fetching = 1;
  rows_fetched = 0;
  }
  else
  {
  rows_fetched = rows_fetched - rows_fetched_total;
  done_fetching = 1;
  }
  printf("sqlo_fetch fetched last %d rowsn", rows_fetched);
  }
  else if (status == SQLO_SUCCESS)
  {
  printf("sqlo_fetch fetched %d rowsn", rows_fetched);
  }
  else
  {
  printf("sqlo_fetch failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  for (i = 0; i < rows_fetched; ++i)
  {
  printf("%3d %5s %19f %20s %10sn",
  nkey, ckey, nval, cval, dval);
  }
  rows_fetched_total += rows_fetched;
  }
  #ifdef CLOSE_CURSOR   if (0 > sqlo_close(sth))
  {
  printf("sqlo_close failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  #endif
  return 1;
  }
  /*-------------------------------------------
  * test_reopen
  *-------------------------------------------*/
  int test_reopen( int dbh )
  {
  int sth;
  const char **v;
  int argc;
  const char *argv[1];
  char * select_stmt = "SELECT DVAL FROM T_SQLORA_TEST WHERE NKEY >= :1";
  argc = 0;
  argv[argc++] = "0";
  /* Select all and display */   if (0>(sth = sqlo_open(dbh, select_stmt, argc, argv)))
  {
  printf("sqlo_open failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  while (0 == sqlo_fetch(sth,1))
  {
  v = sqlo_values(sth, NULL, 1);
  printf("%s|%6s%19s%21s%11sn", v[0], v[1], v[2], v[3], v[4]);
  }
  argv[0] = "5";
  if (SQLO_SUCCESS != sqlo_reopen(sth, argc, argv))
  {
  printf("sqlo_reopen failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  printf("Fetch againn");
  while (0 == sqlo_fetch(sth,1))
  {
  v = sqlo_values(sth, NULL, 0);
  printf("%s|%6s%19s%21s%11sn", v[0], v[1], v[2], v[3], v[4]);
  }
  #ifdef CLOSE_CURSOR   if (0 > sqlo_close(sth))
  {
  printf("sqlo_open failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  #endif
  return 1;
  }
  /*----------------------------------------
  * test_plsql
  *----------------------------------------*/
  int test_plsql( int dbh )
  {
  int ip2, op1;
  double ip1;
  char op2[40];
  char * create_pack =
  "CREATE OR REPLACE PACKAGE SQLORA_TEST ISn"

  " PROCEDURE P1(ip1 IN NUMBER, ip2 IN NUMBER, op1 OUT NUMBER, op2 OUT
  "END;n";
  char * create_pack_body =
  "CREATE OR REPLACE PACKAGE BODY SQLORA_TEST ISn"
  " PROCEDURE P1(ip1 IN NUMBER, ip2 IN NUMBER, op1 OUT NUMBER, op2 OUT
  " IS n"
  " BEGINn"
  " op1 := TO_NUMBER(ip1) + ip2;n"
  " op2 := TO_CHAR(op1);n"
  " END;n"
  "END;n";
  char * stmt =
  "BEGINn"
  " SQLORA_TEST.P1(:ip1, :ip2, :op1, :op2);n"
  "END;n";
  int sth;
  printf("Testing PL/SQL proceduren");
  if (SQLO_SUCCESS != sqlo_exec(dbh, create_pack))
  {
  printf("sqlo_exec failed: %sn%sn",sqlo_geterror(dbh), create_pack );
  return 0;
  }
  printf("Package createdn");
  if (SQLO_SUCCESS != sqlo_exec(dbh, create_pack_body))
  {
  printf("sqlo_exec failed: %sn%sn",sqlo_geterror(dbh), create_pack_body );
  return 0;
  }
  printf("Package body createdn");
  ip1 = 1.123456789012345;
  ip2 = 20;
  op1 = 0;
  *op2 = 0;
  if (0 <= (sth = sqlo_prepare(dbh, stmt)))
  {
  if (SQLO_SUCCESS !=
  (sqlo_bind_by_name(sth, ":ip1", SQLOT_FLT, &ip1, sizeof(ip1),0,0) ||
  sqlo_bind_by_name(sth, ":ip2", SQLOT_INT, &ip2, sizeof(ip2),0,0) ||
  sqlo_bind_by_name(sth, ":op1", SQLOT_INT, &op1, sizeof(op1),0,0) ||
  sqlo_bind_by_name(sth, ":op2", SQLOT_STR, op2, sizeof(op2),0,0)
  ))
  {
  printf("sqlo_bind_param failed failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  else
  {
  if (SQLO_SUCCESS != sqlo_execute(sth, 1))
  {
  printf("sqlo_execute failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  }
  #ifdef CLOSE_CURSOR
  if (SQLO_SUCCESS != sqlo_close(sth))
  {
  printf("sqlo_close failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  #endif
  printf ("ip1: %.16f, ip2: %d, op1: %d, op2: %sn", ip1, ip2, op1, op2);
  }
  else
  {
  printf("sqlo_open failed: Status: %d, %sn", sth, sqlo_geterror(dbh) );
  return 0;
  }
  return 1;
  }
  /*-----------------------------------------
  * test_insert with bind by pos
  *-----------------------------------------*/
  int test_insert( int dbh )
  {
  int nkey;
  char ckey[6];
  double nval;
  char cval[21];
  char dval[11];
  int sth;
  char * insert_stmt =
  "INSERT INTO T_SQLORA_TEST (NKEY, CKEY, NVAL, CVAL, DVAL) VALUES (:NKEY,
  printf("Testing Insert (bind by pos)n");

  if (!create_table(dbh))
  return 0;
  nkey = 100;
  strcpy(ckey, "CKEY");
  nval = 1234567890.001;
  strcpy(cval,"aaaaaaaaaaaaaaaaaaaa");
  strcpy(dval,"01-JUL-00");
  if (0 <= (sth = sqlo_prepare(dbh, insert_stmt)))
  {
  if (SQLO_SUCCESS !=
  (sqlo_bind_by_pos(sth, 1, SQLOT_INT, &nkey, sizeof(int),0,0) ||
  sqlo_bind_by_pos(sth, 2, SQLOT_STR, ckey, 6,0,0) ||
  sqlo_bind_by_pos(sth, 3, SQLOT_FLT, &nval, sizeof(double),0,0) ||
  sqlo_bind_by_pos(sth, 4, SQLOT_STR, cval, 21,0,0) ||
  sqlo_bind_by_pos(sth, 5, SQLOT_STR, dval, 11,0,0)
  ))
  {
  printf("sqlo_bind_param failed failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  else
  {
  if (SQLO_SUCCESS != sqlo_execute(sth, 1))

  {
  printf("sqlo_execute failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  }
  #ifdef CLOSE_CURSOR
  if (SQLO_SUCCESS != sqlo_close(sth))
  {
  printf("sqlo_close failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  #endif
  do_select(dbh);
  }
  else
  {
  printf("sqlo_open failed: Status: %d, %sn", sth, sqlo_geterror(dbh) );
  return 0;
  }
  printf("finished test_insertn");
  return 1;
  }
  /*----------------------------------------------
  * test_array_insert
  *------------------------------------------*/
  int test_array_insert( int dbh )
  {
  int nkey[MAX_ITERS];
  char ckey[MAX_ITERS][6];
  double nval[MAX_ITERS];
  char cval[MAX_ITERS][21];
  char dval[MAX_ITERS][11];
  short nind[MAX_ITERS];
  short cind[MAX_ITERS];
  short dind[MAX_ITERS];
  int sth, i, j;
  int status;
  char * insert_stmt =
  "INSERT INTO T_SQLORA_TEST (NKEY, CKEY, NVAL, CVAL, DVAL) VALUES (:NKEY,
  printf("Testing Array Insert (bind by name)n");
  if (!create_table(dbh))
  return 0;
  /* setup bind arrays */   for ( i = 0 ; i < MAX_ITERS; i++)
  {
  nkey = i+1;
  sprintf(ckey, "%c", A + i % 26 );
  nval = 1234567890.0 + i / 1000.0;   for (j = 0; j < 20; j++)
  cval[j] = a + i % 26;
  cval[20] = ;
  sprintf(dval, "%02d-JUL-00", (i % 30 ) + 1);

  nind = 0;
  cind = 0;
  dind = 0;
  }
  if (0 <= (sth = sqlo_prepare(dbh, insert_stmt)))
  {
  if (SQLO_SUCCESS !=
  (sqlo_bind_by_name(sth, ":NKEY", SQLOT_INT, &nkey[0], sizeof(int), NULL,1) ||
  sqlo_bind_by_name(sth, ":CKEY", SQLOT_STR, &ckey[0], 6, NULL,1) ||
  sqlo_bind_by_name(sth, ":NVAL", SQLOT_FLT, &nval[0], sizeof(double), nind,1)
  sqlo_bind_by_name(sth, ":CVAL", SQLOT_STR, &cval[0], 21, cind,1) ||
  sqlo_bind_by_name(sth, ":DVAL", SQLOT_STR, &dval[0], 11, dind,1)
  ))
  {
  printf("sqlo_bind_param failed failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  else
  {
  if (SQLO_SUCCESS != sqlo_execute(sth, MAX_ITERS))
  {
  printf("sqlo_execute failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  }
  #ifdef CLOSE_CURSOR
  if (SQLO_SUCCESS != sqlo_close(sth))
  {
  printf("sqlo_close failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  #endif
  do_select(dbh);
  }
  else
  {
  printf("sqlo_open failed: Status: %d, %sn", sth, sqlo_geterror(dbh) );
  return 0;
  }
  if (SQLO_SUCCESS != (status = sqlo_commit(dbh))) {
  printf("commit failed (%d): %sn", status, sqlo_geterror(dbh));
  return 0;
  }
  return 1;
  }
  /*----------------------------------------------------
  * test_array_insert2 (by pos)
  *-------------------------------------------------*/
  int test_array_insert2( int dbh )
  {
  int nkey[MAX_ITERS];
  char ckey[MAX_ITERS][6];
  double nval[MAX_ITERS];
  char cval[MAX_ITERS][21];
  char dval[MAX_ITERS][11];
  short nind[MAX_ITERS];
  short cind[MAX_ITERS];
  short dind[MAX_ITERS];
  int i, j;
  int status;
  int sth;
  char * insert_stmt =
  "INSERT INTO T_SQLORA_TEST (NKEY, CKEY, NVAL, CVAL, DVAL) VALUES (:NKEY,
  printf("Testing Array Insert ( bind by pos)n");
  if (!create_table(sth))
  return (0);
  /* setup bind arrays */   for ( i = 0 ; i < MAX_ITERS; i++)
  {
  nkey = i+1;
  sprintf(ckey, "%c", A + i % 26 );
  nval = 1234567890.0 + i / 1000.0;   for (j = 0; j < 20; j++)
  cval[j] = a + i % 26;
  cval[20] = ;
  sprintf(dval, "%02d-JUL-00", (i % 30) + 1);
  nind = 0;
  cind = 0;
  dind = 0;
  }
  if (0 <= (sth = sqlo_prepare(dbh, insert_stmt)))
  {
  if (SQLO_SUCCESS !=
  (sqlo_bind_by_pos(sth, 1, SQLOT_INT, &nkey[0], sizeof(int), NULL,1) ||
  sqlo_bind_by_pos(sth, 2, SQLOT_STR, &ckey[0], 6, NULL,1) ||
  sqlo_bind_by_pos(sth, 3, SQLOT_FLT, &nval[0], sizeof(double), nind,1) ||
  sqlo_bind_by_pos(sth, 4, SQLOT_STR, &cval[0], 21, cind,1) ||
  sqlo_bind_by_pos(sth, 5, SQLOT_STR, &dval[0], 11, dind,1)
  ))
  {
  printf("sqlo_bind_param failed failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  else
  {
  if (SQLO_SUCCESS != sqlo_execute(sth, MAX_ITERS))
  {
  printf("sqlo_execute failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  }
  #ifdef CLOSE_CURSOR
  if (SQLO_SUCCESS != sqlo_close(sth))
  {
  printf("sqlo_close failed: %sn", sqlo_geterror(dbh) );
  return 0;
  }
  #endif
  do_select(dbh);
  }
  else
  {
  printf("sqlo_open failed: Status: %d, %sn", sth, sqlo_geterror(dbh) );
  return 0;
  }
  if (SQLO_SUCCESS != (status = sqlo_commit(dbh))) {
  printf("commit failed (%d): %sn", status, sqlo_geterror(dbh));
  return 0;
  }
  return 1;
  }
  /*--------------------------------------------------
  * test_exists
  *--------------------------------------------*/
  int test_exists(int dbh)
  {
  int status;
  if (SQLO_SUCCESS ==
  (status = sqlo_exists(dbh, "T_SQLORA_TEST", "CKEY", "B", NULL)))
  printf("test_exists(1) okn");
  else
  {
  printf("test_exists(1) failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  if (SQLO_SUCCESS ==
  (status = sqlo_exists(dbh, "T_SQLORA_TEST", "CKEY", "xxx", NULL)))
  printf("test_exists(2) failedn");
  else
  {
  if (status != SQLO_NO_DATA)
  {
  printf("test_exists(2) failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  else
  printf("test_exists(2) okn");
  }
  return 1;
  }
  /*---------------------------------------------------
  * test_count
  *-------------------------------------------------*/
  int test_count(int dbh)
  {
  int count;
  if ((count = sqlo_count(dbh, "T_SQLORA_TEST", NULL, NULL, NULL)))
  printf("test_count(1) okn");
  else
  {
  printf("test_count(1) failed: %sn", sqlo_geterror(dbh));
  return 0;
  }
  if ((count = sqlo_count(dbh, "T_SQLORA_TEST", "CKEY", "xxx", NULL)))
  {
  printf("test_count(2) failed (count=%d)n", count);
  }
  else
  {   if (count < 0)
  {
  printf("test_count(2) failed (count=%d): %sn", count, sqlo_geterror(dbh));
  return 0;
  }
  else
  printf("test_count(2) okn");
  }
  return 1;
  }
  /*----------------------------------------------------
  * int cleanup
  *-----------------------------------------------------*/
  int cleanup(int dbh)
  {
  /* ignore all errors maybe they weren created */
  sqlo_exec(dbh, "DROP TABLE T_SQLORA_TEST");

  sqlo_exec(dbh, "DROP PACKAGE BODY SQLORA_TEST");
  sqlo_exec(dbh, "DROP PACKAGE SQLORA_TEST");
  return 1;
  }
  /*======================================================
  * main
  *==================================================*/
  int main (int argc, char * argv[])
  {
  int status;
  int dbh[MAX_LOOPS];
  char * cstr;
  int i;
  printf("--------------------------------------nn");

  cstr = argv[1];
  else
  cstr = "scott/tiger";
  status = sqlo_init(0);
  if (SQLO_SUCCESS != status)
  {
  printf ("sql_init failed. Exitingn");
  exit(1);
  }
  for (i = 0; i < MAX_LOOPS; i++)
  {
  status = sqlo_connect(&dbh, cstr);
  if (SQLO_SUCCESS == status)
  printf("Connected. dbh=%dn", dbh);
  else
  {
  printf("connect failed with status: %d, %sn", status
  , sqlo_geterror(dbh));
  exit(1);
  }
  if (!test_plsql(dbh))
  exit(1);
  if (!test_insert(dbh))
  exit(1);
  if (!test_array_insert(dbh)) /* bind by name */

  exit(1);
  if (!test_array_insert2(dbh)) /* bind by pos */
  exit(1);
  if (!test_exists(dbh))
  exit(1);
  if (!test_count(dbh))
  exit(1);
  if (!test_reopen(dbh))
  exit(1);
  if (!test_select2(dbh))
  exit(1);
  cleanup(dbh);
  if (SQLO_SUCCESS != (status = sqlo_rollback(dbh)))
  printf("rollback failed (%d): %sn", status, sqlo_geterror(dbh));
  }
  for (i = 0; i < MAX_LOOPS; i++)
  {
  if (SQLO_SUCCESS != sqlo_finish(dbh))
  {
  printf("sql_finish failed for dbh: %dn%sn", dbh,
  sqlo_geterror(dbh));
  exit(1);
  }
  }
  return (0);
  }


04 02, 2005
OCI写多线程ORACLE应用
作者 xzh2000 18:31 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

怎样使用OCI编写多线程的ORACLE应用软件

刘永宁

中国石化石油勘探开发研究院南京石油物探研究所

摘要:

多线程的应用程序可充分利用计算机资源,能有效提高应用程序的运行效率。本文通过实例叙述了使用ORACLE  OCI 编写多线程的应用程序的方法和多线程应用程序的运行机制。

关键字:

 OCI  线程  互斥  应用程序

将一个较为复杂的应用软件按功能划分为若干执行不同操作的模块,再利用多线程机制使它们同时运行在多处理机或单处理机系统上,就能提高软件的运行效率。本文讨论多线程的实用性,并通过实例(二个线程反复轮流地交叉操作进程中二个缓冲区,以提高CPU的利用率)来说明多线程的运作机制和怎样利用Oracle提供的编程接口函数,编写运行在多线程环境中的数据库应用软件。

1. 多线程实用性

线程可以看作是由进程产生的一些可执行单位。它们能够共享进程中相同的代码段和数据段,但它们有自己的程序计数器,寄存器和堆栈。程序中的全局变量对所有线程来讲都是公用的。由于多个线程可能会同时访问这些公用的数据元素,所以要用互斥机制来管理对这些公用数据的访问,保证它们的正确性。该机制称为互斥锁,它能保证应用程序中同时访问共享资源的多个线程不发生矛盾冲突。

在多处理机系统中多个线程同时运行在不同的处理机上,显然可以提高软件的运行速度;在单处理机系统中,可用多个线程分开执行慢操作(如人机交互,I/O操作等)和快操作(数据计算处理),也可提高软件的运行效率。我们考虑显示地震勘探三维数据体程序。常规的程序流程是:

      从数据库中读数据    解压   三维图象处理   显示

 


由于地震勘探三维数据体的数据量较大,从数据库读数据到显示出图象的串行操作要花费一些时间。当数据少时,所花时间相对要少,人有时还感觉不到;但当数据量很大时,这个过程需要花费很多时间。分析流程中四个步骤就会发现:读数据和显示部分主要是和外部设备打交道,读数据还需使用网络;而解压和三维图象处理部分基本上是在主机内部作运算。我们知道对外设上数据的存取和计算机运算操作在速度上有很大差异,当外设与主存储器之间传输数据时,CPU有时可能会出现空闲。也就是说,在读数据和显示数据的过程中,可能会浪费一些CPU资源。若采用多线程方式编写这个程序,就会提高程序的运行效率。将整个过程分二个线程:一个读数据线程专门负责从数据库中取数据;另一个显示线程负责数据的解压,三维图象处理和显示输出。在程序中安排二个缓冲区,用于存放数据。读数据线程轮流地向这二个缓冲区中写数据,同样,显示线程也跟着轮流地使用缓冲区中的数据。即,当读数据线程向缓冲区1中写数据时,显示线程可处理缓冲区2中的数据;而当读数据线程向缓冲区2中写数据时,显示线程可处理缓冲区1中的数据。这样,就将一个进程的串行操作改为二个线程的并行操作,可以充分地利用CPU资源。由于这二个线程可能会同时访问相同的缓冲区,这是不允许的,可用互斥锁机制来协调这二个线程之间的关系。

2. OCIOCI线程安全性和线程函数包

OCI(Oracle Call Interface)ORACLE提供的面向程序员的C语言编程接口,是开发ORACLE数据库应用软件的较好的工具。用它开发出的应用程序运行效率比用Pro*C/C++的要高。程序员利用其中提供的函数,能访问Oracle数据库服务器。OCI应用程序的主要任务之一是处理SQL语句或PL/SQL脚本,在程序执行的过程中将用户对数据库服务器的请求送到ORACLE服务器,并接收来自服务器的响应。

Oracle数据库服务器和OCI函数库的线程安全特征允许程序开发人员在多线程环境中使用OCI。有了线程安全特征,OCI函数代码才具有可重入性,因此从应用程序的多个线程中同时发出OCI调用才不会彼此产生不良影响。要实现多线程安全化,应用程序必须在调用OCI初始化函数时定义mode参数为OCI_THREADED,它告诉OCI接口层,本应用程序运行在安全的多线程方式中。

OCIOCIThread软件包提供了一些线程化函数,主要有三种类型。实际使用情况见后面的编程实例。

⑴初始化和结束函数

在调用其他函数之前必须调用OCIThreadProcessInit()函数,执行OCIThread软件包的初始化工作,然后再调用OCIThreadInit()函数,初始化OCIThread上下文,供其他OCIThread函数使用。调用OCIThreadTerm()函数,结束OCIThread接口层的处理,释放OCIThread上下文内存。

⑵线程管理函数

类型为OCIThreadHandle的线程句柄用于表示线程的内部数据结构。在使用之前,应该用OCIThreadHndInit()来分配和初始化,用完后应调用OCIThreadHndDestroy()来释放内存。用OCIThreadCreate()函数创建新线程。用OCIThreadId类型变量来标识一个线程。使用OCIThreadIdInit()来分配和初始化线程ID,而用OCIThreadIdDestroy()来释放线程ID的结构。用OCIThreadClose()函数关闭线程。OCIThreadJoin()函数允许调用者线程与其他线程连接,当要想连接的线程正在运行时,阻塞调用该函数的线程。直到指定的线程运行结束,这个调用者线程才被唤醒,方能继续执行下去。

⑶互斥锁管理函数

在应用程序中用类型OCIThreadMutex的变量来表示互斥锁。互斥锁在使用之前必须用OCIThreadMutexInit()初始化,用完后要用OCIThreadMutexDestroy()释放内存结构。一个线程可用OCIThreadMutexAcquire()来掌握一把互斥锁,任何时候至多只能有一个线程掌握这把互斥锁,掌握这把互斥锁的线程能够用OCIThreadMutexRelease()来释放它。当一个线程掌握这把互斥锁后,其它线程若想再掌握这把互斥锁,就会被阻塞。直到掌握这把锁的线程释放它,被阻塞的线程之一才能得到它,获得互斥锁的线程才能继续执行下去。

3. 多线程应用软件的编制

下面用一个实例来讲述多线程方式ORACLE应用程序的编写和多线程的运行机制,仍以显示地震三维数据体为例。将从数据库中读数据当作一个线程,数据解压,三维图象处理和显示当作另一个线程,在进程中给出二个数据缓冲区,使这二个线程轮流交叉使用这二个缓冲区。并用二把互斥锁来协调这二个线程对缓冲区的使用。为能清楚而简单地说明线程和互斥锁的使用,这里仅给出程序的主要代码段。

#include

struct thrs_data {

    OCIThreadMutex *mutex1;  缓冲区1互斥锁

    int buffer1[10240];      缓冲区1

    OCIThreadMutex *mutex2;  缓冲区2互斥锁

    int buffer2[10240];      缓冲区2

    int flag;                数据处理结束标志

    int start_read;          开始读数据标志

    int start_disp;          开始显示数据标志

};

OCIEnv     *envhp;    OCI环境句柄

OCIError   *errhp;    OCI错误记录句柄

void read_fun(dvoid *arg);

void disp_fun(dvoid *arg);

int main(int argc, char* argv[])

{

  OCIThreadId *tId1,*tId2;   线程ID句柄

  OCIThreadHandle *tHnd1,*tHnd2;  线程句柄

  struct thrs_data op_data;   定义数据

OCI初始化(线程安全性)和分配句柄:

  OCIEnvCreate((OCIEnv **) &envhp,OCI_THREADED,(dvoid *)0,

   (dvoid* (*)(dvoid*,size_t))0,(dvoid* (*)(dvoid*,dvoid*,size_t))0,

   (void (*)(dvoid *, dvoid *)) 0, (size_t) 0,(dvoid **) 0 );

  OCIHandleAlloc((dvoid *)envhp, (dvoid **)&errhp,

    OCI_HTYPE_ERROR,(size_t)0, (dvoid **)0);

线程软件包和线程初始化:

  OCIThreadProcessInit();

  OCIThreadInit(envhp,errhp);

初始化线程ID和线程句柄:

  OCIThreadIdInit(envhp,errhp,&tId1);

  OCIThreadHndInit(envhp,errhp,&tHnd1);

  OCIThreadIdInit(envhp,errhp,&tId2);

  OCIThreadHndInit(envhp,errhp,&tHnd2);

分配和初始化互斥锁:

  OCIThreadMutexInit(envhp,errhp,&(op_data.mutex1));

  OCIThreadMutexInit(envhp,errhp,&(op_data.mutex2));

创建新的线程,执行线程函数调用:

  op_data.start_read=0; 

  op_data.start_disp=0;

  OCIThreadCreate(envhp,errhp,read_fun,(dvoid *)&op_data,

           tId1,tHnd1);

  OCIThreadCreate(envhp,errhp,disp_fun,(dvoid *)&op_data,

           tId2,tHnd2);

参数read_fun和disp_fun是二个线程函数,op_data是送给线程函数的变量。

等待线程执行完成并关闭线程句柄:

  OCIThreadJoin(envhp,errhp,tHnd1);

  OCIThreadClose(envhp,errhp,tHnd1);

  OCIThreadJoin(envhp,errhp,tHnd2);

  OCIThreadClose(envhp,errhp,tHnd2);

释放互斥锁内存:

  OCIThreadMutexDestroy(envhp,errhp,&(op_data.mutex1));

OCIThreadMutexDestroy(envhp,errhp,&(op_data.mutex2));

释放线程ID和线程句柄:

OCIThreadIdDestroy(envhp,errhp,&tId1);

  OCIThreadHndDestroy(envhp,errhp,&tHnd1);

  OCIThreadIdDestroy(envhp,errhp,&tId2);

  OCIThreadHndDestroy(envhp,errhp,&tHnd2);

释放线程上下文:

  OCIThreadTerm(envhp,errhp);

释放所有分配的句柄。

  OCIHandleFree((dvoid *)errhp, OCI_HTYPE_ERROR);

  OCIHandleFree((dvoid *)envhp, OCI_HTYPE_ENV);

}

下面是二个线程函数主要代码段:

void read_fun(dvoid* arg) {   读数据进缓冲区函数

 struct thrs_data *op_data;

 int n=0;

 op_data=(struct thrs_data *)arg;

 for(int k=0;k<5;k++) { 在实际应用中,此处可为for(;;) ,让退出循环的

条件由要读的实际数据确定,这里用5次循环,是为

了能够运行给出的框架程序。

   OCIThreadMutexAcquire(envhp,errhp,op_data->mutex1); 获得互斥锁

   op_data->start_read=1; 告诉显示线程,读线程已使用缓冲区

   printf("read data  into buffer1 ...n");

在实际应用中,此处应调用“读数据进缓冲区1”的函数。

   OCIThreadMutexRelease(envhp,errhp,op_data->mutex1); 释放互斥锁

在实际应用中,此处可为:当所有数据都读完时,使op_data->flag=1;并退出循环体

   OCIThreadMutexAcquire(envhp,errhp,op_data->mutex2);

   printf("read data  into buffer2 ...n");

在实际应用中,此处应调用“读数据进缓冲区2”的函数。

   if(n==0) while(op_data->start_disp==0); 循环第一次结束时要等待显示线程启

   n=1;                                    动并使用缓冲区

   OCIThreadMutexRelease(envhp,errhp,op_data->mutex2);

   if(k==2) {          这里的代码段,是为了能演示框架程序;

     op_data->flag=2;  在实际应用中,此处可为:

     break;            当所有数据都读完时,使op_data->flag=2;

   }                   并退出循环体

 }

}

 

void disp_fun(dvoid* arg) {  处理和显示数据函数

 struct thrs_data *op_data;

 op_data=(struct thrs_data *)arg;

 

 for(;;) {

   while(op_data->start_read==0); 开始时保证读数据线程先使用缓冲区

   OCIThreadMutexAcquire(envhp,errhp,op_data->mutex1);

   op_data->start_disp=1;  告诉读数据线程,显示线程已开始使用缓冲区

   printf(" display buffer1 ...n");

在实际应用中,此处应调用“使用缓冲区1中数据,解压,图象处理和显示”的函数。

   OCIThreadMutexRelease(envhp,errhp,op_data->mutex1);

   if(op_data->flag==1) break;  退出循环体,返回

   OCIThreadMutexAcquire(envhp,errhp,op_data->mutex2);

   printf(" display buffer2 ...n");

在实际应用中,此处应调用“使用缓冲区2中数据,解压,图象处理和显示”的函数。

   OCIThreadMutexRelease(envhp,errhp,op_data->mutex2);

   if(op_data->flag==2) break; 退出循环体,返回

 }

}

   thrs_data结构中的几个变量用于读数据线程和显示线程的开始控制和结束控制。start_read:当二个线程同时启动或显示线程先启动时,保证读数据线程先使用缓冲区,=1表示读数据线程已使用了缓冲区;start_disp:在读数据线程对缓冲区进行第一轮操作时,当它已将2个缓冲区写满,而此时显示线程还没有启动或还没有使用过缓冲区,这时应将读数据线程阻塞住,防止它覆盖掉缓冲区中未显示的数据,=1表示显示线程已启动并已使用了缓冲区。在后续交替读数据和显示数据的过程中,由互斥锁来协调二个线程之间的关系。Flag:用于标识数据的结束,=1表示在缓冲区1上结束,=2表示在缓冲区2上结束。

    在PC机LINUX下,使用ORACLE 8i数据库,框架程序的编译连结命令为:

gcc -g -o thread thread.cpp

-I$ORACLE_HOME/rdbms/demo -I/usr/i386-glibc20-linux/include

-I$ORACLE_HOME/rdbms/public -I$ORACLE_HOME/network/public

-L$ORACLE_HOME/lib -lclntsh

 

参考文献:

oracle 技术资料:《Oracle Call Interface Programmer’s Guide


04 02, 2005
最有趣的c程序[转]
作者 xzh2000 10:55 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

下面的这段程序是我见过的最有趣的程序之一,如果你编译运行的话,

它能够计算PI的前800位数值。到现在还没见过懂这段程序的人。

int a=10000,b,c=2800,d,e,f[2801],g;

main() {

for(;b-c;)

    f[b++]=a/5;

for(;d=0,g=c*2;c -=14,printf("%.4d",e+d/a),e=d%a)

    for(b=c; d+=f[ b ]*a,f[ b ]=d%--g,d/=g--,--b; d*=b);

}

而结果是这样的:

31415926535897932384626433832795028841971693993751 05820974944592307816406286208998628034825342117067 98214808651328230664709384460955058223172535940812 84811174502841027019385211055596446229489549303819 64428810975665933446128475648233786783165271201909 14564856692346034861045432664821339360726024914127 37245870066063155881748815209209628292540917153643 67892590360011330530548820466521384146951941511609 43305727036575959195309218611738193261179310511854 80744623799627495673518857527248912279381830119491 29833673362440656643086021394946395224737190702179 86094370277053921717629317675238467481846766940513 20005681271452635608277857713427577896091736371787 21468440901224953430146549585371050792279689258923 54201995611212902196086403441815981362977477130996 05187072113499999983729780499510597317328160963185

最详细的解释:

http://purec.binghua.com/Article/Class6/Class9/200410/290.html


03 02, 2005
oracle进程与共享内存关系
作者 xzh2000 17:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

oracle进程与共享内存的关系
环境:ads3+9204
硬件:4cpu+8ram

如果设置sga>1.7G,这时的oracle的后台进程smon/dbwr/reco/cjq0进程用的
共享内存都在500m以上,当时老以为是ads3+9204上存在有内存泄露,虽然进程的
共享内存(TOP)中看到的比较大,而且free空间也不多,但数据库速度并不受影响;
有段时间曾经将9204升级到9205,不过在ads3上进程的共享内存显示得更奇怪,每
个进程的共享内存都是400m左右,在9204时smon/dbwr/reco/cjq0都是渐渐增
大,在9205数据库一启动所有的进程显示共享内存都在400m左右,连接数一多,用
户都投诉数据库很慢,只好降级到9204啦。
现在问题基本上已经搞清楚啦,RSS显示大是正常的,只要将SGA降到1.7G以下,进
程的共享内存会适当于下降,特别是RECO/CJQ进程,SGA超过2.7G后,这两个进程通
常是很大的,SGA降到1.7G以后,RECO/CJQ进程就很小了,现在只有dbwr/smon这2
个进程共享内存还是比较大.
dbwr较大应该是物理读较多造在的/smon较大多应该是user rollback造成的。

12:45:35  up 28 days, 11:36,  1 user,  load average: 1.19, 1.31, 1.19
61 processes: 60 sleeping, 1 running, 0 zombie, 0 stopped
CPU states:  cpu    user    nice  system    irq  softirq  iowait    idle
           total   10.5%    0.0%    5.6%   0.0%     0.1%    0.6%   82.9%
Mem:  8062860k av, 8028240k used,   34620k free,       0k shrd,   23936k buff
                   6120316k actv,   91192k in_d,  164732k in_c
Swap: 4192956k av,       0k used, 4192956k free                 7581276k cached
  PID PRI  NI SWAP  RSS   A   D LC STAT %CPU %MEM   TIME CPU COMMAND
15260  15   0 1140 602M NYI  0M  2 S     0.0  7.6   0:47   2 ora_smon_esal
15248  15   0  456 468M NYI  0M  5 S     0.0  5.9   3:59   5 ora_dbw0_esal
15250  15   0  456 467M NYI  0M  0 S     0.0  5.9   3:31   0 ora_dbw1_esal
15246  15   0  448  36M NYI  7K  7 S     0.0  0.4   2:02   7 ora_pmon_esal
15254  15   0  468  34M NYI  7K  5 S     0.0  0.4   2:13   5 ora_ckpt_esal
15262  15   0  392  28M NYI  5K  7 S     0.0  0.3   0:00   7 ora_reco_esal
15268  15   0  388  22M NYI  3K  1 S     0.0  0.2   0:56   1 ora_cjq0_esal
15270  15   0  468  14M NYI  2K  1 S     0.0  0.1   1:16   1 ora_arc0_esal
15272  15   0  468  13M NYI  1K  6 S     0.0  0.1   1:09   6 ora_arc1_esal
15252  15   0  468  10M NYI  1K  2 S     0.0  0.1   7:54   2 ora_lgwr_esal
16306  25   0    0 4088 NYI  40  5 S     0.3  0.0 117:10   5 tnslsnr LISTENER


03 02, 2005
standby库managed recover时的03113错误
作者 xzh2000 16:06 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

偶的physical standby database在每晚3点钟从open read only
状态由crontab调度进入managed recover状态,通常都是可以的,但
有时会发生03113错误,然后数据库就出问题了.
 * 从top中可以看到数据库进程还在
 * 用sqlplus连接,显示是空闲实例
 * 用shutdown abort停下数据库
 
按就每次从open read only状态到managed recover由
alter database recover managed standby disconnect from session;
就可以完成,但有时会后03113,如何才能万无一失呢?

最后决定每次无论数据库是否正常,都用shutdown abort停数据库,
因为备用库在open read only状态,所以无妨。
sqlplus / as sysdba<<!
shutdown abort;
startup nomount;
alter database mount standby database;
alter database recover managed standby disconnect from session;
这样一来,以后主没有发生过03113的问题啦。


02 02, 2005
关于优化器知识的整理(3)
作者 xzh2000 10:51 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

CBO与RULE的区别在于CBO基于开销

rule 基于规则(优化器会尽可能多的使用索引,而不考虑索引是否有助于性能的提高).

要使用CBO必须在参数文件中设制optimizer_mode 为choose,first_rows或all_rows (某些版本有first_row_n 的参数,好像最近的版本中没有这个参数了),如果为choose ,表有分析的数据就使用cbo,否则用rule ,如多表查询只要有一个表有分析数据就使用cbo.

 

oracle 的很多新功能必须运行在cbo 下才可以完成,这些功能为:

A.分区表,不管数据文件定义何种优化器,对分区表必定是用cbo 的,所以必须分析分区表和它的一些相关表.

B.函数索引,必须运行在cbo ,query_rewrite_enabled 参数为true.

C.bitmap index 好像也须cbo .

D.使用柱状图

E.cbo 下,oracle 才会使用hash join.

F.除了/*+ rule*/ 的hint ,所有的hint 都运行在cbo 下.

G. 物化视图,query_rewrite_enabled 参数为true.

H.固化执行计划

 

Link:
http://www.eygle.com/sql/OPTIMIZER_INDEX_COST_ADJ.htm
OPTIMIZER_INDEX_COST_ADJ
这个初始化参数代表一个百分比,取值范围在1到10000之间.
该参数表示索引扫描全表扫描成本的比较,

缺省值100表示索引扫描成本等价转换与全表扫描成本。

这些参数对于CBO的执行具有重大影响,其缺省值对于数据库来说通常需要调整。
一般来说对于OPTIMIZER_INDEX_CACHING可以设置为90左右
对于大多数OLTP系统,OPTIMIZER_INDEX_COST_ADJ可以设置在10到50之间。对于数据仓库和DSS系统,可能不能简单的把OPTIMIZER_INDEX_COST_ADJ设置为50,通常我们需要反复调整取得一个合理值.更为具体的可以根据统计信息,db file scattered reads/db file sequential reads来计算.

本文通过实验对该参数的使用作出探讨和说明.
我们看到optimizer_index_cost_adj的缺省值为100.

Oracle在选择不同的访问路径时,会对全表扫描和索引扫描进行比较评估.
在比较的时候,Oracle会把索引扫描的成本转换为全表扫描的成本,和全表扫描的COST进行比较.这个转换需要一个转换因子.
就是optimizer_index_cost_adj:


optimizer_index_cost_adj * (Index Scan Cost) = 等价的 Full Scan Cost
这个 等价的 Full Scan Cost 就是来和全表扫描成本进行比较的.
而这个转换因子的临界值实际上就是Full Scan Cost 和 Index Scan Cost的比值.即:

optimizer_index_cost_adj = Full Scan Cost / Index Scan Cost

SELECT EVENT,AVERAGE_WAIT

FROM V$SYSTEM_EVENT
WHERE EVENT LIKE ‘db file s%’;

EVENT AVERAGE_WAITS
========================= ==============
db file sequential reads .33178629
db file scattered reads 2.190087

可以得到optimizer_index_cost_adj =0.33/2.1*100=15。

http://www.evdbt.com/SearchIntelligenceCBO.doc

gressball的文章:

http://www.itpub.net/showthread.php?s=&threadid=235922&perpage=15&pagenumber=1

主要分为两部分:
1)RBO如何工作的:
工作原理;举例论证;得到的结论
2)CBO如何工作的:
cost的计算;physical and logical I/O的比较;
部分参数的介绍;

 

第一部分
RBO怎样工作的?
RBO只借助很少量的信息决定一个SQL语句的执行计划,比如:
1)sql语句本身
2)sql中涉及到的table、view、index等的基本信息
3)本地数据库中数据字典中的信息(远程数据库数据字典信息对RBO是无效的)

RBO首先从下往上察看WHERE子句,按照以下10个标准(删掉了原文中关于CLUSTER的部分,因为很少用到),为每个子句打分:
1. Single row by ROWID
4. Single row by unique index
8. Composite key
9. Single-column non-unique index
10. Bounded range search on indexed columns
11. Unbounded range search on indexed columns
12. Sort-merge join
13. MAX or MIN of indexed column
14. ORDER BY on indexed columns
15. Full table-scan

可以看到,分数越高的,运行的效率越低。所以FULL TABLE-SCAN排在最高。但是很多情况下,全表扫描要比索引扫描效率高很多,比如对于小表;
相反,使用索引也不一定是最好的执行计划;但是RBO则把这些情况认为是定律,这样难免会得到不好的结果。

小结:从上面的实验中可以看到,
1)RBO自动认为索引是好的。
2)RBO使用一种不理智方法来对待分数相同WHERE,即从FROM(或者OBJECT_ID)判断
3)这几个例子都有几乎100%的 Buffer Cache Hit Ratio(BCHR),也就是几乎没有physical I/O。可是速度有的近乎20秒,有的只有1,2秒。
所以,BCHR在系统调优的过程中是几乎没有意义的。关键是减少Logical I/O,而不是花很多功夫将他们保持在内存中。

CBO怎样工作的呢?
CBO检查所有可能的执行方法,运用数据字典中的信息,加上对数据的信息(比如,行数,表和索引的大小,数据在列中的分布情况等)。
然后对每种方法都计算出Logical I/O的大小,从而转换成cost,取cost最小的方法。
oracle 使用 OPTIMIZER_MAX_PERMUTATIONS 参数限制最多计算多少种可能的执行方法,默认值是80000。
你可以通过设置EVENT查看ORACLE尝试过的所有执行计划:

ALTER SESSION SET EVENTS '10053 trace name context forever, level 1';

怎样计算? COST=IO + CPU/1000 + NetIO*1.5

IO 代表physical I/O;CPU代表logical I/O; NetIO 代表对远程数据库访问的logical I/O;
其中logical I/O= consistent gets + db block gets
通过公式可以看出,physical I/O的花费是最高的。

logical I/O 与 physical I/O 的区别:
1)logical I/O是指对cache到 Buffer Cache 中的数据块(db block)的访问请求。
又分为:consistent gets 和 db block gets(current gets)
consistent gets代表对特定版本或时间的block的访问select
db block gets代表对最新的或当前的block的访问,通常用于Insert,update,delete
2)physical I/O是指通过底层的I/O系统,对没有cache到 Buffer Cache 中的数据块(db block)的访问请求。
其实就是oracle在buffer cache中没有发现需要的block,而去访问datafile,并且将block populate到buffer cache中的过程。

LRU算法:
Buffer Cache 使用least recently used 算法安排Buffer的使用。最经常使用到的buffer放在lru-link的最末端,也就是MRU的那端;
最新读到的block放在MRU端的cache里面。如果这些cache不被访问,就逐渐向前移动,一直到lru-link的最前端,此时他将会被新读到block覆盖。

关于SMALL_TABLE_THRESHOLD:
为了防止因为使用全表扫描,将原来BUFFER CACHE中的BLOCKS全部清空,ORACLE规定全表扫描使用的BUFFER CACHE始终放在LRU-LINK的最前端,
这样他们就会马上后读入的BLOCK覆盖掉,因为毕竟全表扫描时不常用的。
活来,ORACLE设计了SMALL_TABLE_THRESHOLD参数,允许必须要使用全表扫描的小表,可以放到LRU-LINK的最末端,就是MRU端。

关于OPTIMIZER_INDEX_COST_ADJ:
表示暗示CBO使用索引与使用全表扫描的相对cost
PREVIOUS_COST * (OPTIMIZER_INDEX_COST_ADJ / 100) = FINAL_COST
默认是100,表示两种cost是一样的。
如果调整这个参数,比如15,表示使用索引的cost只是使用全表扫描的15%
我的例子不是很明显了,大家自己尝试一下:
alter session set OPTIMIZER_INDEX_COST_ADJ=15;

db file sequential reads -------- 往往象征(不是等价于)了索引扫描的等待
db file scattered reads --------- 象征了FTS(不是等价于)的等待
由于 optimizer_index_cost_adj 是一个衡量索引与全表扫描之间的分界点的平衡参数,于是,假定现在 全表扫描 产生的等待 就是其 cost ,假定索引查询的等待就是其 cost 。在系统级来观察,近似地认为就是这两个事件来衡量系统的这个参数。
optimizer_index_cost_adj = 100 的时候,观察系统的这两个等待事件,就可近似的认为:
全表扫描的代价 : 索引扫描的代价 = db file scattered reads : db file sequential reads 针对当前系统的事实,optimizer_index_cost_adj 本质上就是为了描述 索引扫描成本占全表扫描的成本的百分比。这个值越接近真实,则越能更好地给优化器提供选择执行计划的依据。所以正好可以参考下面的计算来设置这个值optimizer_index_cost_adj = 索引扫描代价 / 全表扫描代价 = file sequential reads / db file scattered reads
注意这里的这个等式的含义和 eygle文章中 的 优化器选择的表达式并不是矛盾的,表达了不同的含义。这里是要设置的数据,使得和系统真实状况尽力一致,他那里是利用这个设置好的参数来评估执行计划的选择

 

表示暗示CBO使用索引与使用全表扫描的相对cost
PREVIOUS_COST * (OPTIMIZER_INDEX_COST_ADJ / 100) = FINAL_COST
默认是100,表示两种cost是一样的。
如果调整这个参数,比如15,表示使用索引的cost只是使用全表扫描的15%
我的例子不是很明显了,大家自己尝试一下:
alter session set OPTIMIZER_INDEX_COST_ADJ=15;

这个说法是不确切的,这里的含义指的是,根据索引去的一次 read 的代价 占 全表扫描的一次 读 的代价的比例这个读可以理解为一次 IO request 因为全表扫描的一次 IO request 可能读 多个 block (和extent 边界/os max io size / db_file_multiblock_read_count有关 ) ,而根据索引,一般认为一次io request 是读一个 block 由于实际上 os 的io request 的代价和 实际读了多少 block 关系不是很大
所以我们允许认为两种读代价是一样的当然实际上是存在差异的

io 的代价,实际上还和 是否是文件系统,是否做 raid ,硬件状况等因素相关
由于影响因素很多,所以实际上 一次IO 一个 block 和一次 IO 多个block 的代价的比例,是不确定的。但通常,只能从大量系统信息的宏观表现来做参考,而不能从特定环境的该参数设置来作为评判标准
等待事件 和 代价比例是两码事,在同一系统环境中无法量化,甚至根本难以量化cost 并不等价于等待时间系统是复杂的,影响系统的因素是复杂的,涉及到 cpu/io 等等因素即使你修改了这个值,也难以说明具体问题因为这还决定于,到底有多少查询因为这个值的变化而产生 fts and index scan 之间的切换如果没有这个执行路径的切换,那这个值是多大根本没有意义在宏观上的表现,是 观察系统性能的变化而要量化这个值,却是几乎不可能的

比如这个值变化 x ,系统等待时间减少 y 要使系统变化时间减少到 2y ,绝对无法量化出 这个值该为多少这个时候除了依赖于类似环境的经验,或者说在不同值下长期稳定运行观察性能以积累经验,是没有什么其他办法的
你查询的这个值,跟这个参数本身,应该是有影响关系的,这个参数影响到全表扫描和索引扫描之间的比例,但如果说全表扫描和索引扫描的等待时间,却并不和这个比例有简单的线性关系,想用初等数学的方法来描述是不现实的

 

又有2个问题:
1)对于索引,还有一个调整的参数:OPTIMIZER_INDEX_CACHING,能否对它给我一个理解上的提示?
2)原文中讲对于全表(大表)扫描的cost,可以直接把logical I/O(就是表的blocks的数目,因为直接访问磁盘上的数据文件) 除以DB_FILE_MULTIBLOCK_READ_COUNT,就可以得到physical reads。这句话理解的对吗?这样说来,physical reads指的是读取的次数,对吗?

查询的优化我们是无法调整的,oracle根据内部的代价模型自动计算这个查询语句不同方案下的执行代价,而实际上有时候方案是非常多的,因此查询的优化方案通常也参照一些规则,所以一方面代价模型的不准确,另一方面优化方案并非完全是基于代价模型的,因此执行计划并非最优的。而且oracle内部的优化是针对语句的,如果我们的查询逻辑有问题,那么oracle再优化是没有用的,总之,我们所说的性能优化往往是在查询的业务逻辑上做文章,而非对oracle内部查询优化机制。不过理解了oracle的优化机制对我们进行业务逻辑的设计很有帮助。呵呵,不知道我的理解对不对了!optimizer_index_caching: 说明: 调整基于成本的优化程序的假定值, 即在缓冲区高速缓存中期望用于嵌套循环联接的索引块的百分比。它将影响使用索引的嵌套循环联接的成本。将该参数设置为一个较高的值,

可以使嵌套循环联接相对于优化程序来说成本更低。
值范围: 0 - 100 %。
默认值: 0
nested loop join 时候将可能大量重复地使用索引块,所以cache是有可能避免给换出去的 你这里说的 phisical reads 是 操作系统的 READS ,是一次 io request ,而不是 数据库中的 物理读的概念
数据库中物理读统计的是 blocks
而操作系统中是 io requests ,一次 request 可能是 128k/256k/1024k 等等数据,当然也可能是几十k 或者更少的,取决于数据库的要求。 io request 次数,简单点说是 table blocks / DB_FILE_MULTIBLOCK_READ_COUNT
但是实际上还决定于:
1: 不同 os + 硬件 ,每次IO 有一个极限值,比如hp unix 极限值 是 256k ,sun 的可能高达 1---8m ,若 DB_FILE_MULTIBLOCK_READ_COUNT* block_size > 这个极限值自然就被拆分为多于一个的 io request
2: 一次 io request 不能跨越 extent 边界,所以 extent 大小也影响 IO request
3:对于文件系统来说,连续的 block_id 并不意味着连续的 os block block

4:对 disk array 等设备类说,对于做了 raid 的设备来说,对于很多存储设备来说 , IO 在从 os 抵达这里的时候又重新做了优化重整的 ,还存在cache的,这样代价就不好评估
5: 对于 AIO 来说,os 的读写请求被重整优化过,更复杂一些
在数据库层来说,不考虑上面阐述的这些复杂的东西,做个例子就可以看出来,参考
http://www.itpub.net/showthread.php...ight=multiblock


02 02, 2005
用最新的武器装备自己[转]
作者 xzh2000 10:13 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
Oracle9i数据库

用最新的武器装备自己

作者:Jonathan Genn

在Oracle9i中,历史悠久的SQL*Loader实用程序实现了许多提取、转换和装载的新特性。

如果想把大量数据快速载入Oracle数据库,则您首先能想到的恐怕便是SQL*Loader。到目前为止,这一想法在很大程序上仍是正确的。不过,Oracle9i数据库提供的几项有趣的新特性,可能(或许应该)改变您进行数据装载和转换的方式。这些新特性属于Oracle称为“提取、转换和装载”(Extraction 、Transformation和Loading,ETL)类别,它们共同为您提供了一个功能强大的ETL工具箱。我感觉特别有趣的三个ETL特性是:

  • 外部表
  • 表函数
  • MERGE语句

在本文中,我打算以一个典型的数据装载问题为例,向大家说明这些特性。假定有以下人口普查数据需要载入数据库,您按以下标准对这些数据进行了处理:用一行来存放每个城市/年的组合数据:

City19902000
Baraga12311285
Ishpeming7200  
Munising2783 2539

使用Oracle8i,您需要使用至少两个单独的步骤来完成数据的装载与转换。图1向您展示的便是一种可能的操作方式。然而,利用Oracle9i的ETL特性,您可用一种更有趣的方式来完成这项任务--只需一个步骤,便能完成装载与转换。

图1:装载和转换

 Loading and Transforming
图1:一个多步骤、单线程的装载过程

外部表

Oracle9i的新特性之一是外部表的概念。这是在数据库的数据字典中定义的一个表,但数据本身却存储在数据库的外部。例如,您可定义一个外部表,它的数据来自用SQL*Loader装载的文本文件。这样其实正好,因为您需要装载的人口普查数据就放在这样一个文本文件中。创建外部表之前,需要先创建一个Oracle目录对象,该Oracle目录对象指向您的文本文件所在的操作系统目录。

CREATE DIRECTORY census_data AS '/data/census';

现在,您可使用一种新形式的CREATE TABLE语句,它看起来就像SQL语句和SQL*Loader控制文件的混合:

CREATE TABLE city_populations_ext (
city_name VARCHAR(9),
pop_1990 NUMBER,
pop_2000 NUMBER
)
ORGANIZATION EXTERNAL (
TYPE oracle_loader
DEFAULT DIRECTORY census_data
ACCESS PARAMETERS (
RECORDS FIXED 20
LOGFILE census_data:
'city_populations.log'
BADFILE census_data:
'city_populations.bad'
FIELDS
MISSING FIELD VALUES ARE NULL (
city_name (1:10) CHAR(9),
pop_1990 (11:15) INTEGER
EXTERNAL(4),
POP_2000 (16:20) INTEGER
EXTERNAL(4)
)
)
LOCATION ('city_populations.dat')
)
PARALLEL 4 REJECT LIMIT UNLIMITED;

当创建一个外部表时,实际只创建了一些数据字典项。您可像对其他任何SQL表那样对外部表进行查询。现在,假定您有下面这张工作表:

CREATE TABLE city_populations (
city_name VARCHAR(9),
census_year NUMBER,
population NUMBER,
CONSTRAINT city_populations_pk
PRIMARY KEY (city_name,
census_year));

有了这张表后,您可用下列INSERT...SELECT FROM语句以标准化格式从外部数据文件中提取人口普查数据,并将其插入工作表。

INSERT INTO city_populations (city_name,
census_year, population) SELECT city_name, 1990, pop_1990
FROM city_populations_ext
WHERE pop_1990 IS NOT NULL
UNION ALL
SELECT city_name, 2000, pop_2000
FROM city_populations_ext
WHERE pop_2000 IS NOT NULL;

创建外部表时,由于将并行度设为4,所以数据库将对文件进行划分,使其由4个并行运行的进程读取。并行处理是自动进行的,不需要由您采取额外的操作,这确实相当方便。要用SQL*Loader并行进行装载,您必须将输入文件人工分割为多个较小的文件。

图2: 表函数示例

Table Function Example
图2: 表函数以一系列行作为输入,返回的是一个不同的行集合

外部表性能

用SQL*Loader进行原始数据装载和通过一个外部表进行相同的装载,两者的性能有何差异呢?这个问题实际上是当我听说Oracle新的外部表特性时所首先想到的,而且我相信,它也是大多数人关心的问题。我向Oracle公司的Herman Baer提出这一问题时,他的答复是假如将一个外部表作为数据源,那么一个INSERT /*+ APPEND */语句采用的是同SQL*Loader相同的内部直接路径插入机制。

按我的设想,在比较外部表同SQL*Loader的性能时,需要关心的并不仅仅是完成原始数据装载所需花费的时间,应考察整个装载和转换过程的性能。使用SQL*Loader,如果在装载期间需要使用任何类型的SQL函数,那么必须采用常规。如您所知,常规路径装载的性能通常远不及直接路径装载的性能。采用外部表时,则不会在使用SQL函数时出现对性能的影响。同样,在某些情况下,使用外部表使您能避免创建一个中间工作表。如果正在对数据进行归纳,则可用外部表一次完成归纳与装载。但如果使用SQL*Loader,则必须将数据载入一个工作表,进行归纳,再将归纳结果插入到目标表。最后 ,从易用性的角度出发很重要的一点是,外部表使您能"透明地"并行访问外部数据文件。

不管怎样,在您考察外部表的性能,或在考察任何Oracle9i的新ETL(提取、转换和装载)特性性能时,一定要综合考察整个过程,而不是仅仅考察这个过程中的单独一个步骤。

表函数

前面展示的INSERT语句是通过联合两条SELECT语句而实现的。这意味着外部数据文件被读了两遍--每条SELECT语句都要读一遍。但是,读两遍输入文件并不合人心意,特别是在文件非常大的情况下。幸运的是,用表函数可以解决这方面的问题,这是我在本文中将要介绍的第二个ETL特性。可将表函数想象成一个高度简化的转换引擎。如图2所示,表函数将一组行作为输入,然后返回一组不同的行作为输出。和传统函数不同的是,表函数可从SELECT语句的FROM子句中调用。

对于人口普查数据来说,您打算取得每一个输入行,并将其转换成两个输出行。每个输入行都拥有来自两个不同的人口普查年度的数据,但是,标准目标表要求每一年的数据占一行,所以表函数必须能将来自每个输入行的两次人口计数转换成两个单独的输出行。

创建表函数之前,您需要创建一些类型。表函数返回的总是一个记录集,所以在最开始的时候,请创建一个表类型,令其对应于目标数据表的定义。为此,首先创建一个对象类型来定义记录,然后根据那个对象类型创建一个表类型。

CREATE TYPE city_populations_row AS OBJECT (
city_name VARCHAR2(9),
census_year NUMBER,
population NUMBER
);
/

CREATE TYPE city_populations_table
AS TABLE OF city_populations_row;
/

函数的输入是由对外部表city_populations_ext执行一条SELECT语句而返回的数据行,因此,您需要一个恰当的REF CURSOR类型。下面的语句将创建一个包,其中包含一个名为pop_cursor_type的REF CURSOR类型,它与city_populations_ext表的记录结构相匹配。这个包还定义了一个表函数,该表函数将这样一个游标作为输入参数。注意您首先必须创建表类型city_populations_table,以便可在表函数的RETURN子句中使用那种类型:

CREATE OR REPLACE PACKAGE census_package
AS
TYPE pop_cursor_type IS REF CURSOR
RETURN city_populations_ext%ROWTYPE;
FUNCTION census_transform (
indata IN pop_cursor_type)
RETURN city_populations_table
PARALLEL_ENABLE (PARTITION indata
BY ANY)
PIPELINED;
END;
/

函数中的PARALLEL_ENABLE子句使数据库可并行执行函数。PARTITION indata BY ANY子句指出输入行可被分割为任意数量的数据桶,然后便可对其进行并行处理。PIPELINED子句使函数能递增地返回结果集,同时其他输入数据仍能得到处理。在调用函数的查询执行期间,可设想数据行都“经过(flowing through)”此函数。在清单1中,在包主体(PACKAGE BODY)中定义的函数代码负责将每个输入行转换成要求的两个输出行。

我知道这些设置起来似乎比较复杂。但它最终带来的好处可以说明这些麻烦是完全值得的,特别是对那些需要经常重复的有相同规律的装载操作来说。通过启用并行DML,然后使用表函数,现在只需一次操作,即可实现人口普查数据的装载和转换:

ALTER SESSION ENABLE PARALLEL DML;
INSERT /*+ APPEND PARALLEL (t,4) */ INTO city_populations t
SELECT *
FROM TABLE(census_package.
census_transform(
CURSOR(SELECT city_name, pop_1990,
pop_2000
FROM city_populations_ext)));

图3: 并行装载和智能更新/插入

Parallel Loading and Smart Updating/Inserting
图3: 一个单步、流水线的和并行的装载过程

人口普查数据将从外部表读取,采用文件内的并行机制,这一过程将被并行化处理。每个并行操作的输出结果都会送入单独的进程,这些进程也是并行运行的,可将每个输入行转换成您希望的两个输出行。由于表函数负责进行转换,所以只需对外部文件遍历一次即可。在此,还应提醒您注意的是不必用任何形式的工作表来暂存数据,数据以流水线的方式从外部数据文件提取,经过表函数的处理,然后直接传送给目标表。由于减少了数据复制的次数,所以有效地减少了对磁盘空间的占用。

MERGE语句

MERGE语句解决了长期存在的一个问题,那就是如何对以前装载过的数据进行重新装载。在Oracle9i问世之前,您需要编写过程代码来判断一行是否已经存在,然后相应地执行INSERT或UPDATE语句。而在Oracle9i中,只需使用MERGE 语句,然后让数据库处理所有细节。

最后,让我们考虑一下和我们目前假设的情况有关的非常常见的数据装载问题。假定我们以前已将人口普查数据装载到city_population表中,而且当前的输入文件下包含了新数据和对已有数据的更新。在这种情况下,对于文件中作了更新的数据,我们希望更新city_population表中已存在的行;对于文件中的新数据,我们希望在city_population表中插入新行。这是一个极其常见的问题,通常通过执行用PL/SQL编写的过程逻辑来处理。例如,清单2中的PL/SQL代码每次可从city_population_ext中读取一行,然后根据情况执行UPDATE或INSERT语句。

但是,这样的处理方式会带来几方面的问题。首先,由于不再使用表函数,所以不能对装载过程的"转换"部分进行并行处理。另外,还不得不为每一条输入记录都执行多达两条DML语句。另外,我们不得不去关心最有可能的情况是UPDATE;还是INSERT。最后,由于要为这种类型的逻辑编制代码,所以对我们来说无疑是一个痛苦的过程。那么,有没有单独一条语句即可做完所有这些工作呢?在Oracle9i中,终于出现这样的语句,这便是MERGE(合并)语句。它可根据情况要么INSERT(插入)新行,要么UPDATE(更新)已存在的行。

编写一条MERGE语句时,必须指定下述项:

  • 目标表的名称
  • 一条SELECT语句,用作数据源
  • 一个条件,用于标识对现有数据进行更新的输入行
  • UPDATE和INSERT子句

下述MERGE语句可从外部表将数据正确地合并到city_populations表中。其中,ON子句引用了目标表的主键列。数据库从源查询读一个数据行时,它会考察目标表中的每一行(本例通过主键索引),对其ON条件求值。如果在目标表中发现一行的ON条件为TRUE,那么数据库会对源行作更新。

MERGE INTO city_populations dest
USING (SELECT * FROM TABLE (census_package.census_transform(
CURSOR(SELECT city_name, pop_1990, pop_2000
FROM city_populations_ext)))) src
ON (dest.city_name = src.city_name
AND dest.census_year = src.census_year)
WHEN MATCHED THEN
UPDATE SET
dest.population = src.population
WHEN NOT MATCHED THEN
INSERT (city_name, census_year, population)
VALUES (src.city_name, src.census_year, src.population);

这太令人激动了!只需一个语句,便可从外部数据文件读取数据,通过表函数,对其进行转换以符合我们数据表的要求,然后在我们数据库表中相应地要么更新现有的行,要么插入新行。图3对这个过程进行了图示。另外,整个过程中不需要创建临时表,所有这些工作可按您的愿望进行任何程度的并行化处理。

总结

合并数据是一个由来已久的问题,令人高兴的是,现在终于有了一个方法能够在数据库一级解决它,同时还能充分利用数据库的伸缩性。我预计,尽管表函数是为简化装载过程而设计的,但它将会还有许多其他用途。现在想起来,在我过去几年写的数份报告中,其实都可利用它把事情做得更好。外部表承诺可以消除外部和内部数据之间的界限,以便更容易地将数据从外部系统载入数据库。使用这些崭新的ETL特性,一个多步骤的、单线程的装载过程(如图1所示)可以转换成单步骤的、流水线的以及高度并行的装载过程(如图3所示)。

Jonathan Gennick (jonathan@gennick.com) 是一名经验丰富的Oracle 数据库管理员,也是一名获得Oracle认证的专家,非常喜欢探索新的Oracle技术。他是最近出版的新书《SQL*Loader: The Definitive Guide》(O'Reilly & Associates, 2001)的作者。


02 02, 2005
关于scn的理解的整理贴
作者 xzh2000 09:47 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

关于scn的理解

系统检查点scn(v$database(checkpoint_change#))
数据文件检查点(v$datafile(checkpoint_change#)
数据文件终止scn(v$datafile(last_change#))

数据文件中存放的检查点
启动scn (v$datafile_header(checkpoint_change#)

1、系统检查点scn
当一个检查点动作完成之后,Oracle就把系统检查点的SCN存储到控制文件中。
select checkpoint_change# from v$database
2、数据文件检查点scn
当一个检查点动作完成后,Oracle就把每个数据文件的scn单独存放在控制文件中。
select name,checkpoint_change# from v$datafile
3
、启动scn
Oracle
把这个检查点的scn存储在每个数据文件的文件头中,这个值称为启动scn
因为它用于在数据库实例启动时,检查是否需要执行数据库恢复。
select name,checkpoint_change# from v$datafile_header
4、终止scn
每个数据文件的终止scn都存储在控制文件中。
select name,last_change# from v$datafile
在正常的数据库操作过程中,所有正处于联机读写模式下的数据文件的终止scn都为null.
5、在数据库运行期间的scn
在数据库打开并运行之后,控制文件中的系统检查点、控制文件中的数据文件检查点scn
和每个数据文件头中的启动scn都是相同的。控制文件中的每个数据文件的终止scn都为null.

在安全关闭数据库的过程中,系统会执行一个检查点动作,这时所有数据文件的终止scn
都会设置成数据文件头中的那个启动scn的值。在数据库重新启动的时候,
Oracle
将文件头中的那个启动scn与数据库文件检查点scn进行比较,
如果这两个值相互匹配,oracle接下来还要比较数据文件头中的启动scn和控制文件
中数据文件的终止scn。如果这两个值也一致,就意味着所有数据块多已经提交,所有
对数据库的修改都没有在关闭数据库的过程中丢失,因此这次启动数据库的过程
也不需要任何恢复操作,此时数据库就可以打开了。当所有的数据库都打开之后,
存储在控制文件中的数据文件终止scn的值再次被更改为null
这表示数据文件已经打开并能够正常使用了。

------------------------------------------

澄清几个概念
1)
系统当前SCN并不是在任何的数据库操作发生时都会改变,SCN是在事务提交或回滚时改变,
2)
在控制文件,数据文件头,数据块,日志文件头,日志文件change vector中都有SCN,但其作用各不相同数据文件头中包含了该数据文件的checkpoint SCN,表示给数据文件最近一次执行检查点操作时的SCN.日志文件头中包含了low scn,next scn,表示给日志文件包含有从low scnnext scnredo record.控制文件中包含了每个数据文件的checkpoint SCN,stop SCN,每个日志文件的low scn,next scn.控制文件中checkpoint scn同数据文件头中checkpoint scn相同,除非数据文件被手工替换掉.控制文件中的low scn,next scn同日志文件中low scnnext scn相同在数据库正常运行时,控制文件中对应数据文件的stop SCN都是最大值.在正常关闭数据库的情况下,在关闭前会执行一次检查点工作当oracle会将数据缓冲区上的内容全部写回到磁盘中,然后更新控制文件中对应数据文件的stop SCN,使其等于checkpoint SCN

但在异常当机的情况下,由于最后一次检查点未进行或进行中间被中止,因而在控制文件,就存在部分的数据文件stop SCN为最大值,在数据库重新启动后,会检查控制文件中对应每个数据文件的stop SCN,如果stop SCN不等于控制文件中对应每个数据文件的checkpoint SCN,就会使用日志文件redocheckpoint SCN开头到stop SCN为止的全部数据库操作.在定位到底是使用哪一个redo log文件时,就用到了日志文件头中的low scn,next scn,也就是说要使用的redo log low scn ,next scn必须包含数据文件重做所须的change vector.

在确定了哪个数据文件须redo,oracle会比较change vector中的SCN和数据文件数据块中的SCN,如果change vectorSCN小于数据块的scn,则跳过此change vector,否则redo
数据块中ITL中还有SCN,但它的作用是用于产生一致性读快照

-----------------------------

1: SCN 并不仅仅在 提交或者回滚的时候才改变,DML 发生的时候会改变,提交的时候也会变,还有很多的变化都会改变, 有兴趣请去 www.ixora.com.au 看看 。证明方法也很容易。

2:
在定位到底使用哪个日志文件的时候,并不是用 数据文件中的 low scn 去框,在日志文件的low scn and next scn 之间就利用该日志文件。而是在数据文件头中有 RBA 的记录,RBA 包含了日志序号、block number slot number 这样可以直接定位到日志文件(归档日志文件)和具体的位置

如果你有兴趣,大可去实验,dump出来看看。

 

--------------------------------

 

1SCN存在redo log文件,control文件、数据文件;
2
oracle正常运行时,control文件的SCN是个很大的数,与redo log文件、数据文件的SCN不同,正常关闭时,做完checkpoint后,三者的SCN值相同;
3
、当一个事务commit成功时,redo log文件中的SCN+1,当该事务所做的修改写入数据文件后,数据文件的SCN+1
4
、所以,当数据库发现SCN不一致,应该是
redo log
文件中的SCN>=数据文件中的SCN
5
、疑问:
是不是如果一个事务比较大,在事务提交前就发生redo log entriesdata buffer的写入,此时断电,则数据文件、redo log文件的SCN没有+1,且相同,但控制文件SCN不同,数据库startup时发生回滚。

 

 

2oracle正常运行时,control文件的SCN是个很大的数,与redo log文件、数据文件的SCN不同,正常关闭时,做完checkpoint后,三者的SCN值相同;
日志文件中scn有起始和结束2个(高低),在current log中高scn同样为 无穷大
3
、当一个事务commit成功时,redo log文件中的SCN+1,当该事务所做的修改写入数据文件后,数据文件的SCN+1
commit
的时候加一,其他很多时候也会加1,只要数据库发生了变化都会增加。 数据写入数据文件scn不是加1而是ckpt 更新,检查点发生的时候才修改数据文件头的 检查点计数和更新scn
5
、疑问:
是不是如果一个事务比较大,在事务提交前就发生redo log entriesdata buffer的写入,此时断电,则数据文件、redo log文件的SCN没有+1,且相同,但控制文件SCN不同,数据库startup时发生回滚。
数据文件是由ckpt进程更新文件头的,scn不是加1,而是更新为检查点发生那时的scn,回滚是根据回滚段头的事务表状态来进行的

 

-----------------------------------------------

 

数据写入数据文件scn不是加1而是ckpt 更新,检查点发生的时候才修改数据文件头的 检查点计数和更新scn

是不是应该这么说?:
ckpt 更新时发生数据写入,同时修改数据文件头的 检查点计数和更新scn 。当出现其他情况下的数据写入时(如无空闲缓冲等),不发生ckpt ,但SCN会增加。

commit
的时候加一,其他很多时候也会加1,只要数据库发生了变化都会增加。
很多时候,能否举一些例子

另,我相信很多人对SCNCHECKPOINT不太清楚,能否给我们讲讲,就像回滚段一样。呵呵,不好意思了。

 

数据写入数据文件scn不是加1而是ckpt 更新,检查点发生的时候才修改数据文件头的 检查点计数和更新scn
是不是应该这么说?:
ckpt 更新时发生数据写入,同时修改数据文件头的 检查点计数和更新scn 。当出现其他情况下的数据写入时(如无空闲缓冲等),不发生ckpt ,但SCN会增加。
这个时候修改的是数据块但不是数据文件头,只有检查点发生的时候才更新数据文件头,也就是说只有 ckpt 进程更新数据文件头(oracle8以前如果没有ckpt进程就是lgwr更新),dbwr只写数据块
commit
的时候加一,其他很多时候也会加1,只要数据库发生了变化都会增加。
很多时候,能否举一些例子
dml
一发生即使没有提交也会增加scn, job进程一样产生scn,只要对数据库中文件发生任何的改变都有可能产生scn,SCN: system change number, not system commit

02 02, 2005
关于优化器知识的整理(2)
作者 xzh2000 09:45 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

General Optimizer Notes 优化器的一般注意事项

~~~~~~~~~~~~~~~~~~~~~~

在看待优化器问题的时候,应考虑如下几点:

- ALL_ROWS 倾向于全表扫描(full table scans)。

- FIRST_ROWS 倾向于索引访问( index access)。

- CBO缺省使用ALL_ROWS计算成本。

- Oracle 7.3之前,CBO不会为了迎合并行查询( Parallel Queries)而调整成本。

- Oracle 7.3之前,CBO认为字段的值载最大和最小之间是均匀分布的;这之后,可以根据请求存储柱状图统计。

- 所有等于RBO的情况,以表在FROM子句中从右到左的顺序为驱动顺序(Driving Order)

   CBO根据由收集到的统计信息而导出的成本,来确定连接顺序(Join Order).

   如果没有统计信息,CBO就将以表在FROM子句中从左到右的顺序为驱动顺序(Driving Order),正好和RBO相反。

 - CBO将结合当前表的高水位信息使用ANALYZE信息。因此,一个语句的执行计划是可能因时间的不同而改变的。

- 注意:TRUNCATE重置了表的“高水位”,但是不修改表的统计信息,而是留下了该表的旧的CBO信息。

 - 当执行各种连接时,一些连接组合将被排除以降低确定一个执行计划所需要的整体时间花费。总之,每个连接顺序都要和目前为止最好的一个做比较,显然部分优化的方案将被排除。

 Problem SQL Statements 问题SQL语句

如果 CBO返回的是个部分优化的执行计划,对于这样的问题SQL语句,应采取如下的处理步骤:

a) 检查你是否真的ANALYZE过所涉及的表,这样CBO才有可依据的有用信息。

b) 检查分析的信息是否精确

     例如:使用COMPUTE选项,和比较重新分析前后的表的统计信息。

c)检查你是否涉及到了字典表。字典表缺省情况时不被分析的,所以,在CBO方式下SQL访问他们可能产生非常差的计划。

d) 确定你是否希望使用RBO, ALL_ROWS FIRST_ROWS 作为你的优化目标(OPTIMIZER_GOAL)。

e) 使用提示(hint)帮助指导优化。

 如果你有有问题的SQL语句,并且指引CBO的尝试也没有结果,首先的行动应该是隔离问题语句,在SQL*PLUS 中使用语句的最简单的形式。然后使用EXPLAIN命令或TKPROF来确定实际的执行计划,并改进它。

如果它突然在SQL*PLUS中运行的很好,那么要注意后续章节中表明的一般的错误。

 Explain Plan  TKPROF

EXPLAIN PLAN 一个SQL语句和TKPROF一些trace文件对于确定给定语句的执行计划是非常有用的,但要注意以下的限制:
a)他们使用当前信息来推导执行计划,不能在必要时显示原来采用的计划。

例如:如果你分析过任何一个表或创建/删除了一个索引,计划将不会相同。如果OPTIMIZER_MODE 不同,也将产生不同的计划。

b) 他们不知道绑定变量(bind variable)的类型,将所有的绑定变量都假设为字符类型。因此,你可能得到错误提示或者误导的结果。

Eg:   SELECT 1 FROM DUAL WHERE sysdate < :b2 + 1

这将导致一个错误,因为将把':b2' 解释为一个字符类型的。

为了避免这类的问题,你应该用相应的类型转换函数来包起这样的绑定变量来。

Eg: SELECT 1 FROM dual WHERE sysdate < to_date(:b2) + 1;

这是避免隐式类型转换的好方法。

Making Comparisons 比较

SQL语句和PL/SQL的比较:

PL/SQL当在SQL语句中引用一个PL/SQl比变量时使用绑定变量(bind variables)。这是非常重要的,因为绑定变量的解释影响到执行计划的确定。

 Eg:  PL/SQL中的部分语句:

  SELECT ename FROM emp WHERE empno > myempno;

其中, 'myempno' 是一个PL/SQL 变量, 所以语句实际上等同于:

  SELECT ename FROM emp WHERE empno > :bind1;

绑定变量(Bind Variables:   通常我们会把问题SQL语句拿到SQL*PLUS中,并用常量替换绑定变量。多数情况下这是无效的比较。

 Eg: 比较:

SELECT ename FROM emp WHERE empno > 9999;

SELECT ename FROM emp WHERE empno > :bind1;

 假设表已经被分析过,CBO知道EMPNO的最大最小值。对于第一句,CBO可以确定子句'WHERE empno > 9999'的选择性(selectivity),而对于第二句,CBO不知道':bind1' 是否介于1-9999之间,因此使用缺省的选择性- 例如:他假设子句将返回表的四分之一记录。即使对于使用柱状图的oracle 7.3以上的版本也是这样,如果CBO不知道绑定变量的值的话。因此得出的执行计划是完全不同的。

 一般来说,如果使用绑定变量,所有的RANGE SCANSLIKE比较操作使用缺省的选择性。构成无效的比较。你应该在SQL*PLUS中也使用BIND variable

例如:

  VARIABLE bind1 varchar2(10)

  EXPLAIN PLAN FOR SELECT ename FROM emp WHERE empno > :bind1;

而不是:

  EXPLAIN PLAN FOR SELECT ename FROM emp WHERE empno > 9999;

数据库之间的比较:

如果你有分离的两个数据库,表的基本统计也会不一样。你不能把统计从一个数据库传到另外一个数据库。影响到数据库比较的主要因素是:

- 数据库块的大小(DB_BLOCK_SIZE)。这是CBO计算的基础,所以你不能比较DB_BLOCK_SIZE值不同的数据库。

-DB_FILE_MULTIBLOCK_READ_COUNT.  这是Oracle 7.1以上的init.ora参数,用于确定全表扫描的成本。

- DB_FILE_MULTIBLOCK_READ_COUNT. This init.ora parameter is used in determining the cost of full table scans in Oracle 7.1 onwards.

- /索引的统计。卸出再导入数据将会导致表和索引占用不同数目的数据块。这影响到计算出的或估计出的统计信息,因而影响到CBO执行计划。(Oracle8i允许导出实际的统计信息,从而解决这个问题。)

 Init.ora 参数:

下列的 init.ora参数会影响到成本计算:

 
版本之间的比较:

Oracle的不同的版本之间,成本算法和缺省成本目标又一些细小的变化。因此,在升级时,执行计划可能发生变化。比如,带绑定变量的LIKE子句的缺省选择性的变化就是个很好的例子。

 RBO相比较:

RBO计划相比,执行计划只有相同的很少,你会得到一个不同的执行计划。幸运的是,现在很清楚了:CBO使用各执行计划的相关成本来选择执行计划。

There is little point comparing an execution plan to the RBO plan and being surprised if you get a different execution plan. Hopefully it is fairly clear by now that the CBO uses relative 'costs' of execution plans to determine an execution plan.

例如:

对于RBO,一个索引存在,就是使用它的足够理由。(如果它是和查询相关的话)

而对于CBO,仅仅索引存在还不够充分,还要比较通过索引访问期待数量的数据的成本和其他方法(如:全表扫描)的成本。

如果RBO已经给出了最佳计划,你应该使用'RULE'提示或其他形式的提示来指定访问路径。

RBOCBO之间的主要区别是:CBO不使用索引。没有使用那些期望被使用的索引的主要原因是:

a) 索引不具有‘选择性。通过计算访问期望数量的数据的成本,CBO发现使用索引块的查找这种方法的成本比多块读(multi-block reads)方式的全表扫描的成本更高。

b)CBO期望返回的'值的范围'和相应的记录数不正确,可能是由于不正确的统计或使用BIND值来限制范围。

注意:如果RBOCBO返回的结果数据物理上不相同,就是个严重的问题,请作为一个bug报告Oracle

 解析时间的比较:

 如果解析时间占了执行时间的很大的比例,建议你检查一下是否执行了一个连接很多表的查询。如果是这样,使用ORDERED提示来设定访问表的顺序,以降低连接时考虑的表的数目,是个很明智的做法。一旦你有了一个好的执行计划,你可以很快地通过重新排列FROM 子句的顺序并使用ORDERED提示来实现同样的计划。

 Hints 优化提示

提示使你可以给CBO提供应如何访问数据的信息。不幸的是,无效的提示会使得提示再没有任何警告的情况下被忽略 ,所以大家必须非常注意它的语法。使用提示时,需要记住的几点是:

- 提示必须在注释中并以这个严格的格式开始/*+ ... */

- 所有的提示(RULE除外)将使你使用CBO。因此,除非这些表都被分析过或你给了查询完全的提示,使用提示不是个好办法。

- All hints (except RULE) cause you to use the CBO. Hence, it is not a good idea to use hints unless the tables are analyzed or you are fully hinting the query.

 - 在提示中不要引用模式(用户)名。

例如:SELECT /*+ index(scott.emp emp1) */  是不对的, 应给表起别名并在提示中使用别名。

 - 如果表使用了别名,在提示中必须使用别名。

例如:

错误写法:

SELECT /*+ FULL ( emp ) */ empno FROM emp myalias

    WHERE empno > 10;

正确写法:

SELECT /*+ FULL ( myalias ) */ empno FROM emp myalias

    WHERE empno > 10;

 - PL/SQL块中的提示,在'+'后面必须跟一个空格。这是很重要的,否则提示可能会被忽略,因为一些版本的PL/SQL在把查询传给SQL引擎的时候,会忽略掉'+'号后面的第一个字符。

例如:使用 "SELECT /*+ FULL(a) */" 而不是"SELECT /*+FULL(a)*/"

 - 被提示的访问路径必须是有效的访问路径。例如:

AB都在可空列IND_COL上有索引。给定的索引建议应该使用这些索引。两表中的VALUE 字段都未被索引。

Tables A & B both have indexes on the nullable IND_COL column. A hint has been supplied suggesting that these indexes should be used. The VALUE column in both tables is unindexed.

SELECT /*+ index(A) index(b) */ *

FROM A,B

WHERE A.ind_col = B.ind_col

AND A.value = 1

AND B.value = 2

            Query Plan  执行计划

----------------------------------------------------------

SELECT STATEMENT [CHOOSE] Cost = 83

  NESTED LOOPS

  TABLE ACCESS FULL A

  TABLE ACCESS BY ROWID B

  INDEX RANGE SCAN B1

如果这个查询从A驱动,我们不能使用A.IND_COL上的索引,因为可空列的索引会使我们丢掉一些记录。所以提示'index(A)' 是无效的,因而被忽略。B上的索引可以被使用,因为它是访问B表的有效的方式。

If we drive the query from A, then we cannot use the index on A.IND_COL as the column is nullable as we may miss some rows. Hence the 'index(A)' hint is invalid and is ignored. The index on B can be used as it is a valid way to access table B.

 - 无效的提示可能不是立即明显地表现出来的。

例如: 在有ORDER BY 子句的语句中使用FIRST_ROWS提示。(你以为起了作用其实没有)

- 在不支持HINTS的第三方工具(和老版本的PLSQL V1)中,解决这个问题的方法是将提示嵌入到视图中,并在工具中引用视图。

例如: 对于语句:

  SELECT /*+ FULL( mytab ) */ col1, col2

  FROM mytab  WHERE col1 > var1;

你可以创建一个视图:

  CREATE or REPLACE VIEW myview AS

  SELECT /*+ FULL( mytab ) */ *  FROM mytab;

并将语句改为:

  SELECT col1, col2 FROM myview WHERE col1 > var1;

Summary 总结

要有效的使用CBO,我们必须:

-定期的分析所有的表

- 设置要求的优化目标 OPTIMIZER_GOAL (FIRST_ROWS  ALL_ROWS).

- 在必要的地方,使用提示指导CBO

- PL/SQL中使用提示,以使期望的优化器被使用。

- 使用绑定变量时要注意

 

对于即席的查询(ad-hoc query),CBO工作的很好。对于硬编码的,

重复执行的SQL语句,应该进行调优以获得可重复的优化的计划。

你必须经常的监控执行效率,在RDBMS 版本升级的时候进行认真的测试。

知道你的应用的关键联机语句和对他们你所期望的执行计划是什么,这是非常重要的。


02 02, 2005
关于优化器知识的整理(1)
作者 xzh2000 09:26 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

CBOCOST的计算公式

CBO9i开始引入CPU成本评估,这个评估不是动态的,不会根据系统负荷变化

其成本评估公式大致如下,供参考:

 COST = ( #srds * sreadtm + #mrds * mreadtm + #cpucycles / cpuspeed ) / sreadtm

 各参数含义:

 #srds number of single block reads
sreadtm single block read time
#mrds number of multi block reads
mreadtm multi block read time
#CPUCycles number of CPU Cycles
CPUspeed CPU cycles per second

  CBOCOST的计算公式2

CBO的成本计算主要由物理I/O组成,实际公式为:

 COST = Phyiscal Disk IO + CPU/1000 + NetIO*1.5

 IO表示物理I/O请求,

CPU表示逻辑I/O请求,

NetI/O表示通过数据库连接访问远程数据库的逻辑I/O请求.

CBO会尝试计算所有可能执行计划的物理I/O,保留只需要最小物理I/O的计划.

 关于CBO的一些实验:

http://www.itpub.net/250228.html

  关于RBO的运算优先级

http://blog.csdn.net/lovexueer/archive/2003/12/31/21856.aspx

RBO遵循简单的分级方法学,RBO使用15种级别要点,当接收到查询,优化器将评估使用到的要点数目,然后选择最佳级别(最少的数量)的执行路径来运行查询,15个要点级别如下:

规则1   .使用ROWID的单独记录

规则2   .使用簇连接的单独记录.

规则3   .使用散列(hash)簇主键的单独记录.

规则4   .使用主键的单独记录.

规则5   .簇连接.(cluster table)

规则6   .散列簇连接

规则7   .索引簇主键.

规则8   .复合主键.

规则9   .单列主键.

规则10  .索引列的结合范围查找.index range scan

规则11  .索引列的非结合范围查找.

规则12  .排序合并连接.

规则13  .索引列的最大maxmin

规则14  .索引列的order by.

规则15  .全表扫描.

 关于CBO/RBO一些需要特别关注的地方:

http://www.irisbay.com/oracle/tuning/cbo.htm

 关于oracle 10g的统计信息

http://otn.oracle.com/global/cn/pub/articles/lewis_cbo.html

    Cost Based Optimizer - Common Misconceptions and Issues

基于成本的优化器 —— 一般错误概念和问题

Introduction 介绍

本短文着意于消除一些关于基于成本的优化器(CBO)的错误说法,强调一般的错误和问题。

Background 背景
为了执行任何一个SQL语句,Oracle都要先导出一个“执行计划(execution plan)”。

它基本上就是Oracle如何检索出符合给定SQL语句要求的数据的执行计划。

Oracle7Oracle8 都有两种可以为SQL语句导出执行计划的优化器:

- 基于规则的优化器(RBO

  继承自Oracle6,它使用一系列严格的规则来决定每个SQL语句的执行计划。

如果你知道这些规则,你可以构造一个SQL查询使其以指定的方式访问数据。

表的内容对于执行计划没有影响。

  这个优化器已经不再被增强了,所以不能使用很多oracle8的特性。

- 基于成本的优化器(CBO

   Oracle7开始引入,该优化器尝试找到最低成本的访问数据的方法,

为了最大的吞吐量或最快的初始响应时间。计算使用不同的执行计划的成本,

并选择成本最低的一个。关于表的数据内容的统计被用于确定执行计划。

Fundamental Points 基本点

对于每个SQL语句,都有很多可能的执行计划。

“最佳计划”永远是“最佳计划”,无论它如何到达。

 最佳计划可以由两个意思:

   1  此计划使用最小的资源来处理此语句涉及到的所有行。 [叫做ALL_ROWS]

       2  此计划以最短的时间返回这个语句的第一行    [叫做FIRST_ROWS]

   CBO不理解应用的相关特性,也不能完全理解关联表之间的复杂关系的影响。

仅有有限的信息可以用来确定最佳计划。

 CBO通过计算不同执行方案的估计成本来确定最佳计划,并选用最低成本的计划。因为这个关系到相关成本的假设,所选的计划不一定是真的最好的计划。这种情况经常被当作BUG报告给oracle 技术支持,因为 CBO没有为一个指定方案选择一个最佳的计划。人们通常可以证实因为给定的输入统计试有效的并且缺省的“成本”被牵扯进来。所选中的计划被计算成最佳计划,虽然它不是。无论CBO如何改进提高,总也会有所选的计划不是最优的这种情况。所以,你必须经常地准备优化语句。

  RBO的功能已经不再增强。这就意味着一些执行计划只对CBO有效。然而,RBO还将在Oracle 8中继续存在。

Before you Continue 在你继续之前

不建议你在Oracle releases 7.0.X中使用CBO.

本文中的信息适用于Oracle releases 7.1 以上(包括Oracle 8.0)。

Base Statistics 基础统计

~~~~~~~~~~~~~~~

  为了要给CBO最多的信息(有机会选择好的执行计划),你必须对所有将被查询的表做ANALYZE

  带有ESTIMATE选项的ANALYZE操作对于一些表能够产生不正确的结果,

尤其是那些取样较小的表。这不是个BUG,而是每个统计取样方法的特性。

如果所选取样不能代表整个数据集,你就不能期待产生正确的统计。

  Oracle 7.1 7.2 中,列的值被假定为是均匀分布的。这是在这些版本中的一个重要的限制,完全和精确的统计也不能指出实际数据的分布情况。这一限制在Oracle release 7.3 以上版本被部分解决了,能够保存列值的分布信息 - 但是这些额外的信息可能对某些类型的查询没有实际的帮助,请看后面的章节中关于Bind Variables 的注意事项。

  在考虑使用ANALYZE时,要考虑如下的重要问题:

- 对一个带索引的表的ANALYZE,将分析其相关索引。 (在Oracle 7.3 中可能值分析表而不分析索引。)

- 如果你对一个表进行ANALYZE ... ESTIMATE 分析,那么然后在其相关索引上做ANALYZE COMPUTE分析是很明智的。这样可以确保被索引字段的统计是准确的。

 

- 分析索引不用到临时表空间

- 如果分析一个索引而不分析其基表,在这一单一基础上CBO不会被选中。

 

- 如果你需要使用ESTIMATE- 估计(例如,由于时间的限制),建议你在几个不同的取样大小上进行 ANALYZE ... ESTIMATE 来确定每个对象的理想的取样大小。总的目标是找到一个能在最短的时间内产生准确的统计的取样大小。较好的开始点是 10% - 15%

 

- 进行超过50%ANALYZE ... ESTIMATE 就会导致/变成ANALYZE ... COMPUTE

- 7.1.6 以前的版本在进行ANALYZE ... ESTIMATE 时,会有ORA 600 错。

 

- 不要分析数据字典表(SYS表)除非你有足够充分的理由。关于这一点有和一些文档或README文件相矛盾,他们说DBMS_UTILITY.ANALYZE_SCHEMA 可以用于分析SYS表。虽然DBMS_UTILITY.ANALYZE_SCHEMA 可以分析SYS用户,但Oracle没有对这些被分析的表进行衰退测试,可能会造成死锁或效率问题。

 

Optimizer Goal / Mode 优化目标和模式

采用什么样的优化器和其操作方式是由下面的因素决定的:

Object Type 对象类型

- 某些对象类型是基于规则的优化所不知道的。例如:索引表(IOTRBO根本不认识,在牵扯IOT的查询中将自动使用CBO.

 

Parallel Degree > 1 on a table 表上的并行度大于1

- 如果查询中的某个表的并行度大于一,CBO都将被采用而不管提示、OPTIMIZER_MODEOPTIMIZER_GOAL的值是否为"RULE"。适用于Oracle 7.3 以上。
- Oracle 8.0.5  Oracle 8.1.5 releases 中如果任何索引的并行度超过1,也将采用CBO。仅适用于Oracle 8.0.5Oracle 8.1.5

 

Hints 提示

- 除了RULE外的任何提示都会导致使用CBOHINT不能被任何参数关掉,这一点非常重要。

 

Session level会话级 OPTIMIZER_GOAL

- 如果没有给定以上的条件,优化器的选用由会话级的参数OPTIMIZER_GOAL决定。如果上面的一个条件给定了,OPTIMIZER_GOAL就不起作用了。

如果OPTIMIZER_GOAL设为RULE,将采用RBO,而不管任何表的统计。

如果OPTIMIZER_GOAL设为CHOOSE,对于只要有一个表被分析过的查询,都将选用ALL_ROWS

 Init.Ora OPTIMIZER_MODE 参数

- 会话级OPTIMIZER_GOAL参数缺省设置是init.ora文件中OPTIMIZER_MODE的值。


01 02, 2005
redhat增加apt管理[转]
作者 xzh2000 10:39 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

redhat采用了RPM软件包管理系统,RPM软件包管理系统具有强大的编译安装功能,但是由于历史原因,RPM软件包管理系统对软件之间的依存关系没有内部定义,造成安装RPM软件时经常出现令人无法理解的软件依赖问题。
debian系统则基于apt(Advanced Packaging Tool)工具进行软件包管理,可以自动解决并安装倚赖软件包,因此debian linux被认为是最容易管理和升级的系统,apt工具也被认为是目前最好的软件包管理工具之一。为了解决redhat包管理系统的致命问题,Conectiva Linux将apt系统移植到了使用rpm软件包管理系统的Linux系统下,使得基于RPM软件包的系统可以利用apt工具提供的自动解决倚赖关系的能力。目前已经有很多为redhat linux提供apt方式升级管理软件包的站点,如http://freshrpms.nethttp://apt.unl.edu 等等,使得redhat也成为可以利用apt工具的发行版之一,本文介绍如何在redhat linux系统安装和使用apt软件包管理工具。

 查看全文

01 02, 2005
Linux.X86虚拟内存管理[转]
作者 xzh2000 10:24 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Linux支持很多硬件运行平台,常用的有:Intel X86,Alpha,Sparc等。对于不能够通用的一些功能,Linux必须依据硬件平台的特点来具体实现。本文的目的是简要探讨Linux在X86保护模式上如何实现虚拟内存管理功能。为简化和方便叙述,本文做如下限定:X86处理器为80486和其后的处理器,X86工作在保护模式,不采用物理内存扩展(使用32bits物理地址),不使用扩展页(页大小为4K)。凡是与限定模式无关的内容,本文都尽量略过。Linux的虚拟内存管理中与硬件平台无关的内容在本文中也被略过。本文所援引的Linux内核源代码版本为Linux 2.2.5。

 查看全文

29 01, 2005
使用dbms_profiler包的示例
作者 xzh2000 20:34 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

关于使用dbms_profiler package的例子
sql>@?/rdbms/admin/profload
创建相关packages
sql>@?/rdbms/admin/proftab
创建相关tables
sql>@?/plsql/demo/profrep
创建相关views及package

create or replace procedure test1
as
  numLoop number := 0;
begin
  for i in 1 .. 100000 loop
    numLoop := numLoop + 1;
    if mod(numLoop,1000) = 0 then
       null;
    end if;
  end loop;
end;
/
create or replace procedure test2
as
  numLoop number := 0;
begin
  for i in 1 .. 100000 loop
    numLoop := numLoop + 1;
  if numLoop = 1000 then
    null;
    numLoop := 0;
  end if;
 end loop;
end;
/
set line 5000 serveroutput on size 1000000
declare
  v_run number;
begin
  dbms_profiler.start_profiler(run_number=>v_run);
  test1;
  dbms_profiler.stop_profiler;
  dbms_profiler.start_profiler(run_number=>v_run);
  test2;
  dbms_profiler.stop_profiler;
end;
/
@?/plsql/demo/profsum

set linesize 131
col text format a24
col run_comment format a12
col run_system_info format a12
col run_comment1 format a12
col run_owner format a12
col spare1 format a12
select * from plsql_profiler_runs order by 1;

col unit_type format a18
col unit_owner format a12
col unit_name format a18
select * from plsql_profiler_units order by 1; 

declare
  v_run number;
begin
  dbms_profiler.start_profiler(run_number=>v_run);
  &procedure_name;
  dbms_profiler.stop_profiler;
  dbms_profiler.rollup_run(v_run);
  prof_report_utilities.print_run(v_run);
end;

如果输出信息混乱,清在plsql/demo/profsum.sql中添加如下内容
column owner format a11
column unit_name format a14
column text format a40
column runid format 9999
column secs format 99999.99
column hsecs format 999999.99
column grand_total format 9999.99
column run_comment format a40
column line# format 99999
column pct format 999.9
column unit_owner format a11

////////////////////////////////////////////////////////////////////////////////////

SQL> set line 5000 serveroutput on size 1000000
SQL> declare
  2    v_run number;
  3  begin
  4    dbms_profiler.start_profiler(run_number=>v_run);
  5    test1;
  6    dbms_profiler.stop_profiler;
  7    dbms_profiler.start_profiler(run_number=>v_run);
  8    test2;
  9    dbms_profiler.stop_profiler;
 10  end;
 11  /

PL/SQL procedure successfully completed.

////////////////////////////////////////////////////////////////////////////////////////////

执行profsum时最好把profsum.sql内的@profrep去掉

////////////////////////////////////////////////////////////////////////////////////////////


SQL> @?/plsql/demo/profsum

GRAND_TOTA
----------
       .60

Elapsed: 00:00:00.01

RUNID RUN_COMMENT    SECONDS
----- ----------- ----------
   30 29-JAN-05      .640777
   31 29-JAN-05      .501734

Elapsed: 00:00:00.00

RUNID RUN_COMMENT UNIT_OWNER  UNIT_NAME      SECONDS   PERCEN
----- ----------- ----------- -------------- --------- ------
   30 29-JAN-05   SCOTT       TEST1                .36   56.7
   31 29-JAN-05   SCOTT       TEST2                .24   47.5

Elapsed: 00:00:00.00

UNIT_OWNER  UNIT_NAME      SECONDS   PERCENTAG
----------- -------------- --------- ---------
SCOTT       TEST1                .36     60.35
SCOTT       TEST2                .24     39.63
          .00       .02

Elapsed: 00:00:00.01
    to_char(p1.max_time/p1.min_time,'999999.99') as "Max/min",
                       *
ERROR at line 9:
ORA-01476: divisor is equal to zero


Elapsed: 00:00:00.06

no rows selected

Elapsed: 00:00:00.07

SECONDS  UNIT_OWNER  UNIT_NAME       LINE# TEXT
-------- ----------- -------------- ------ ------------------------------------
      .2 SCOTT       TEST1               7 if mod(numLoop,1000) = 0 then
      .1 SCOTT       TEST1               5 for i in 1 .. 100000 loop
      .1 SCOTT       TEST1               6 numLoop := numLoop + 1;
      .1 SCOTT       TEST2               6 numLoop := numLoop + 1;
      .1 SCOTT       TEST2               7 if numLoop = 1000 then
      .1 SCOTT       TEST2               5 for i in 1 .. 100000 loop

6 rows selected.

Elapsed: 00:00:00.08

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.04

no rows selected

Elapsed: 00:00:00.01

no rows selected

Elapsed: 00:00:00.00

LINES_EXECUTED
--------------
             0

Elapsed: 00:00:00.01

LINES_PRESENT
-------------
            0

Elapsed: 00:00:00.00
==================trace info=================
========Results for run #30 made on 29-JAN-05 19:05:54 =======
(29-JAN-05) Run total time:       .64 seconds
Unit #1: . - Total time:       .00 seconds
Unit #2: SCOTT.TEST1 - Total time:       .36 seconds
1           0   .000007                          procedure test1
2                                                as
3           1   .000001  .000001                   numLoop number := 0;
4                                                begin
5     100,001   .095427  .00000095                 for i in 1 .. 100000 loop
6     100,000   .089174  .00000089                   numLoop := numLoop + 1;
7     100,000   .178602  .00000178                   if mod(numLoop,1000) = 0 then
8                                                       null;
9                                                    end if;
10                                                  end loop;
11           1   .000001  .000001                 end
========Results for run #31 made on 29-JAN-05 19:05:55 ======
(29-JAN-05) Run total time:       .50 seconds
Unit #1: . - Total time:       .00 seconds
Unit #2: SCOTT.TEST2 - Total time:       .24 seconds
1           0   .000007                          procedure test2
2                                                as
3           1   .000001  .000001                   numLoop number := 0;
4                                                begin
5     100,001   .07694  .00000076                  for i in 1 .. 100000 loop
6     100,000   .083937  .00000083                   numLoop := numLoop + 1;
7     100,000   .077514  .00000077               if numLoop = 1000 then
8                                                null;
9         100   .000081  .00000081               numLoop := 0;
10                                                end if;
11                                                end loop;
12           1   .000001  .000001                 end
================================================

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.07
========= Profiler report - all runs rolled up ========
Unit .:
Unit SCOTT.TEST1:
1           0   .000007                          procedure test1
2                                                as
3           1   .000001  .000001                   numLoop number := 0;
4                                                begin
5     100,001   .095427  .00000095                 for i in 1 .. 100000 loop
6     100,000   .089174  .00000089                   numLoop := numLoop + 1;
7     100,000   .178602  .00000178                   if mod(numLoop,1000) = 0 then
8                                                       null;
9                                                    end if;
10                                                  end loop;
11           1   .000001  .000001                 end
Unit SCOTT.TEST2:
1           0   .000007                          procedure test2
2                                                as
3           1   .000001  .000001                   numLoop number := 0;
4                                                begin
5     100,001   .07694  .00000076                  for i in 1 .. 100000 loop
6     100,000   .083937  .00000083                   numLoop := numLoop + 1;
7     100,000   .077514  .00000077               if numLoop = 1000 then
8                                                null;
9         100   .000081  .00000081               numLoop := 0;
10                                                end if;
11                                                end loop;
12           1   .000001  .000001                 end
=======================================


28 01, 2005
Linux各项系统开机服务的功能介绍
作者 xzh2000 10:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Linux各项系统开机服务的功能是什么?

Linux在启动时要启动很多系统服务,它们向本地和网络用户提供了Linux的系统功能接口,直接面向应用程序和用户。但是,开启不必要或有漏洞的服务则会给操作系统带来安全和性能上的影响。下面我们以BluePoint Linux 2.0的开机服务为例,列表说明各项服务的功能 。

  1. alsasound
    Alsa声卡驱动程序支持。Alsa声卡驱动程序本来是为了一种声卡Gravis UltraSound(GUS)而写的,该程序被证 明很优秀,于是作者就开始为一般的声卡写驱动程序。Alsa和OSS/Free 及OSS/Linux兼容,但是有自己的接口,甚至比OSS优秀。
  2. amd
    运行automount精灵程序,该精灵在必要时自动安装一些本地设备和NFS文件系统。
  3. apmd
    apmd用来监视系统用电状态,并将相关信息通过syslogd 写入日志。也可以用来在电源不足时关机。
  4. arpwatch
    该程序主要用来维护以太网物理地址和IP地址的对应关系。
  5. atalk
    AppleTalk精灵程序。注意不要在后台运行该程序,该程序的数据结构必须在运行其他进程前先花一定时间初始化。
  6. atd
    运行用户用At命令调度的任务。也在系统负荷比较低时运行批处理任务。
  7. autofs
    当您需要时自动转载文件系统,而当您不需要时自动卸载。
  8. bootparamd
    该服务允许老的Sun工作站从Linux网络启动,它和rarp现在很少使用,基本上被bootp和dhcp取代了。
  9. crond
    cron是Unix下的一个传统程序,该程序周期地运行用户调度的任务。比起传统的Unix版本,Vixie版本添加了不少属性,而且更安全,配置更简单。
  10. dhcpd
    该精灵提供了对动态主机控制协议(Dynamic Host Control Protocol)的访问支持。
  11. gated
    gated通过一个数据库提供了网络路由功能支持。它支持各种路由协议,包括RIP版本1和2、DCN HELLO协议、OSPF版本2以及EGP版本2到4。
  12. gpm
    gpm为文本模式下的Linux程序如mc(Midnight Commander)提供了鼠标的支持。它也支持控制台下鼠标的拷贝,粘贴操作以及弹出式菜单。
  13. httpd
    http是著名的www服务器,可用来提供HTML文件以及CGI动态内容服务。
  14. inetd
    因特网操作服务程序。监控网络对各种它管理的服务的需求,并在必要的时候启动相应的服务程序。通常,inetd管理的程序有telnet、ftp、rsh和rlogin。关闭inetd也就关闭了这些由它管理的服务。
  15. innd
    inn是最流行的用户组新闻服务器。它允许您建立起本地新闻服务器。配置有一定的难度,可以先阅读/usr/doc/ inn*文档获得帮助。
  16. keytable 该程序的功能是转载您在/etc/sysconfig/keyboards里说 明的键盘映射表,该表可以通过kbdconfig工具进行选 择。您应该使该程序处于激活状态。
  17. ldap
    LDAP代表Lightweight Directory Access Protocol,实现了目录访问协议的行业标准。
  18. linuxconf
    linuxconf是Linux下的一个有效的系统配置工具,该服务允许远程运行。
  19. lpd
    lpd是系统打印守护程序,负责将lpr等程序提交给打印作业。
  20. mcserv
    Midnight Commander服务进程允许远程机器上的用户通过Midnight Commander文件管理器操作本机文件。服务进程用PAM来验证用户,需要给出“用户名/口令”以通过验证。
  21. mysql
    一个快速高效可靠的轻型SQL数据库引擎。
  22. named
    域名服务器,将Internet主机名解析为点分的IP地址。
  23. netfs
    负责装载/卸载NFS、Samba、NCP(Netware)文件系统。

  24. network 激活/关闭启动时的各个网络接口。
  25. nfs
    NFS是一个流行的基于TCP/IP网络的文件共享协议。该服务提供了NFS文件共享服务,具体的配置在/etc/ exports文件里。
  26. nscd
    该服务负责密码和组的查询,并且缓冲查询结果。如果您的系统有比较慢的服务(如NIS和NIS+),则应该启动该服务。
  27. pcmcia
    pcmcia主要用于支持笔记本电脑。
  28. portmap
    portmap用来支持RPC连接,RPC被用于NFS以及NIS等服务。
  29. postgresql
    PostgreSQL关系数据库引擎。
  30. proftpd
    proftpd是Unix下的一个配置灵活的ftp守护程序。
  31. radvd
    路由广播程序。
  32. random
    保存和恢复系统的高质量随机数生成器,这些随机数是系统一些随机行为提供的。
  33. routed
    该守护程序支持RIP协议的自动IP路由表维护。RIP主要使用在小型网络上,大一点的网络就需要复杂一点的协议。
  34. rstatd
    Rstat协议允许网络上的用户获得同一网络上各机器的性能参数。
  35. rusersd
    该服务使网络用户可以定位同一网络上的其他用户。
  36. rwalld
    Rwall协议允许远程用户向在同一系统中活跃着的终端发送消息,类似wall的本地行为。
  37. rwhod
    允许远程用户获得运行rwho精灵的机器上所有已登录用户的列表,与finger类似。
  38. sendmail
    大名鼎鼎的邮件服务器。
  39. smb
    启动和关闭smbd和nmbd精灵程序以提供SMB网络服务。
  40. snmpd
    简单网络管理协议(SNMP)的守护精灵。
  41. syslog
    syslog是操作系统提供的一种机制,守护程序通常使用这种机制将各种信息写到各个系统日志文件。通常应该启动该服务。
  42. xfs
    X的字体服务器。
  43. ypbind
    NIS/YP的客户端守护程序。如果您需要使用NIS/YP机器,请启动这项服务,否则,关闭这项服务。
  44. yppasswd
    让NIS用户能够修改密码。运行在NIS域的服务器上。客户端程序同样也叫yppasswd。
  45. ypserv
    标准NIS/YP网络协议的一个实现。允许主机名,用户名和其他信息分布于网络各端。运行在NIS服务器上,客户端不需要。

28 01, 2005
系统平均负载(Load average)释疑[转贴]
作者 xzh2000 10:21 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
在Linux系统中,uptime、w、top等命令都会有系统平均负载load average的输出,那么什么是系统平均负载呢?
系统平均负载被定义为在特定时间间隔内运行队列中的平均进程树。如果一个进程满足以下条件则其就会位于运行队列中:
- 它没有在等待I/O操作的结果
- 它没有主动进入等待状态(也就是没有调用'wait')
- 没有被停止(例如:等待终止)
例如:
[root@www2 init.d]# uptime
7:51pm up 2 days, 5:43, 2 users, load average: 8.13, 5.90, 4.94
命令输出的最后内容表示在过去的1、5、15分钟内运行队列中的平均进程数量。
一般来说只要每个CPU的当前活动进程数不大于3那么系统的性能就是良好的,如果每个CPU的任务数大于5,那么就表示这台机器的性能有严重问题。对于上面的例子来说,假设系统有两个CPU,那么其每个CPU的当前任务数为:8.13/2=4.065。这表示该系统的性能是可以接受的
27 01, 2005
消除temp ts暴涨的方法
作者 xzh2000 18:06 | Permalink 静态链接网址 | Comments 最新回复 (8) | Trackback 引用 (0) | 技术交流

关于消除temp ts暴涨的方法
经常有人问temp表空间暴涨的问题,以及如何回收临时表空间,由于版本的不同,方法显然也多种多样,但这些方法显示是治标不治本的办法,只有深刻理解temp表空间快速增加的原因,才能从根本上解决temp ts的问题。

是什么操作在使用temp ts?
- 索引创建或重创建.
- ORDER BY or GROUP BY
- DISTINCT 操作.
- UNION & INTERSECT & MINUS
- Sort-Merge joins.
- Analyze 操作
- 有些异常将会引起temp暴涨

 查看全文

27 01, 2005
toad8及spotlight试用体验
作者 xzh2000 12:07 | Permalink 静态链接网址 | Comments 最新回复 (5) | Trackback 引用 (0) | 技术交流

toad8及spotlight试用体验
下载了一个toad8,安装完后竟然用了近1g的空间,好家伙,可真不少东西,
从lisence上看,是由很多模块组成的,而且还有db2/sqlserver等东西,
不太感兴趣,发现里边还有SpotLight,这个东西以前没有用过,赶紧打开
看看,发现果然有点意思。
Site: hotpig
Key :
 Database Analysis (Oracle)                      : 295710024449229169750
 Knowledge Xpert for DB2                         : 295713301249277161750
 IBM DB2                                         : 147850012424594491327
 Knowledge Xpert for Oracle Administration       : 147850012424628499327
 Spotlight On Oracle                             : 038884508756328128343
 Knowledge Xpert for PL/SQL                      : 147854927624628490327
 Knowledge Xpert for SQL Server                  : 295710024449275160750
 Data Generator for DB2                          : 147851650824582491327
 Data Generator for Oracle                       : 075203283046083416055
 Load Generator for DB2                          : 295710024449167160750
 Load Generator for Oracle                       : 075200825446109418055
 Space Management (Oracle)                       : 295713301249261164750
 Quest Central for SQL Server                    : 295713301249189163750
 TOAD                                            : 147851650824610493327
 SQL Tuning (Oracle)                             : 147850012424618498327
还是先说说toad8,显示quest公司收购了不少公司,它们的产品却没有很好地集成在一起,比如
说收购珠海的lecco(灵高科技),但lecco的产品并没有集成在toad中一块发售,而且toad8中
比如sql navigate、spotlight很多东西都与toad有重叠现象.

第一次用spotlight,感觉这个东西做得很精致,而且也有很多独到之处,数据库的方方面面几乎
是一目了然,以华丽的图表形象准确地显示数据库、操作系统的若干dba较感兴趣的信息,但对新
手来说,无疑是自杀,过度的依赖gui的后果,必须导致对数据库体系结构深入理解的莫视.

在数据库监控方面,spotlight的确是技高一筹,但在数据库调优方面,非lecco莫属啦,lecco
的软件在SQL收集、调优方面都显示了非凡的造诣,虽然spotlight也有sql tuning模块,但感
觉上没有lecco的sql truning模块好用,但spotlight在优化建议方面也有一个很显著的优化,
它的针对SQL的优化建议非常明显,优化于新手学习优化,lecco则注重于执行计划的分析,需要使
用者对调优很在行才可以,如果你想做优化的话,偶建议你用spotlight.

现在论到讲一下toad吧,想来quest也不是以toad起家的,toad从头到尾都没有什么独特的地方,
但比较前的版本在某些方面更人性化一些,提供了非常用的online help tools,即知识库之类
的两个软件(Knowledge Xpert for Oracle Administration/for PL/SQL),大部分开发
与管理方面的东西都可以在这两个软件中搜到,省去了到http://tahiti.oracle.com我麻烦。

在toad8中,值得一提的是ER Diagram/SQL Modeler/Code Road Map,老实讲,ER Diagram
图可以将数据库中的表显示成ER Diagram,还没有达到建模的能力,所以这个定位比较有问题,当
然还是值得表扬一下,希望再接再历;至于SQL Modeler应该是旧版本中就有的功能,但在taod8
中使用却极不顺手,功能还是不错的。


25 01, 2005
dba麻烦终结者之路(2)
作者 xzh2000 11:37 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

第一部分见http://blog.itpub.net/post/96/2265

基于等待事件的性能诊断方法

等待事件(wait event)是oracle核心代码的一个命名部分,有两种类型的等待事件:空闲事件(idle event)与非空闲事件(non-idle event),空闲事件指oracle正在等待某种工作,常见的空闲等待事件:client message、null event、pipe get、pmon/smon timer、rdbms rpc message及sql*net等;非空闲等待事件:buffer busy waits、db file scattered read、db file sequential read、enqueue、free buffer waits、latch free、log file sync、log file paralle write等。

 查看全文
25 01, 2005
给x公司的数据库优化方案
作者 xzh2000 11:22 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

数据库优化增值服务方案

为什么优化

       自从数据库诞生之后,性能问题一直都是数据库难以摆脱的枷锁,RDBMS厂商虽然提供了许多改进性能的办法,到目前为止,还没能什么数据库能够自我学习、自我优化;一个生产数据库随着业务数据的增长,系统的性能总是在恶化之中,假如DBA对数据库调优的速度跟不上数据库恶化的速度,那数据库崩溃将在意料之中。

       数据库性能不佳体现在什么地方呢?一般情况下表现在客户端响应速度极慢,或者速度有时正常、有时很慢。无论何种情况,对客户来讲,都是不能忍受的,所以提高业务系统的响应速度,数据库优化势在必行。

优化的方法

       性能良好的数据库是一样的,性能不佳的数据库各有各有缺陷,即是目前数据库没有问题,并不表示数据库就处于良构之中,因为很多情况下,好的硬件配置可以弥补数据库性能方面的不足;当业务增长或数据达到一定的数量,各种性能问题就会渐渐浮出水面,也就是说,如果问题存在,总有爆发的时候。

       如何诊断出问题所在呢?oracle提供了很多诊断方法。通常的情况下,用statspack可以发现数据库中绝大部分的问题,由于statspack是每隔一段时间对数据库的关键性能指标进行取样分析,如果间隔太短会增加系统的负载,太长则可能会收集不到一些性能不佳的SQL,所以系统调优是一个长期的过程。

1、为SQL创建或选择恬当的索引(复合索引或位图索引)

2、创建实体化视图(materialized view

3、将大表创建为分区表(partition table

4、基于等待事件的优化方法

5、用存储概要(stored outline)稳定SQL的执行计划

6、其它方法见附件<优化之路>>

优化的效果

数据库性能明显改善:

A、数据库监控工具statspack报表反映的指标明显改善:

    如图一所示,关键性能指标将较优化前将大大降低:

Logical Reads

Physical Reads

B、操作系统监控工具topassarvmstat等反映的指标明显改善

       topas中看到Disk I/O将有所降低

       vmstat中看到作业队列有所降低

四、成功案例

1、使用存储概要(stored outline)优化SQL

       具体案例http://blog.itpub.net/post/96/1548

2、关于实体化视图提高查询性能

       具体案例http://blog.itpub.net/post/96/7535

3、如何减少共享池的碎片

       具体安例http://www.itpub.net/298019.html

4、针对statspack的按例分析

       通常很难对调优进行量化,因为数据库有很多不可预测性,但可以对statspack收集的数据进行分析,建立数据库性能趋势图表;通过性能趋势图表,可以对系统调优起到前瞻式的指导作用,将潜在的性能问题绞杀于摇篮之中。

图一 负载状态

       在图一中,这些关键性能指标有两种量化标准:每秒或每事务,通常DBA对用秒所衡量的关键性能指标更关注一些,如每秒的physical reads1461.71 BLOCKS,由于知道标准块尺寸8Kbyes,那每杪的磁盘读就是1462 x 8192 / 1024 = 11.5M左右。

       磁盘是数据库服务器上最慢的设备,同等数量的logical reads比同等数量的physical reads大概要快100倍左右,所以减小physical reads等也是调优的关键性能指标,更小的physical readslogical reads表示着数据库的性能有所改善。

      

图二 命中率状态

       如图二所示,主要缺陷集中在Buffer Hit上,Buffer Hit在关键性能指标中有很重要的地位,它直接反映了业务系统的响应速度,图一中的physical reads可以证实,如果说Buffer Hit低于95%,通常表示DB CACHE较小,另一方面也说明SQL的性能不佳,每次执行SQL都需要大量的physical reads,导致业务的响应速度较差。

图三 TOP 5等待事件

       等待事件是系统调优的关键参考点,CPU time占了99.9%左右的CPU资源,但从下面其它的等待事件分析,应该是由于db file scattered readbuffer busy waits等事件引起的,所以必须更深入地分析,是什么操作导致了大量的db file scttered readbuffer busy waits事件的产生,找到了等待产生的根源,那就可以找出降低等待的方案,基于等待事件的诊断方法可以参考《dba优化之路》中介绍的方法。

我局oracle数据库目前存在的问题

       10月份曾对我局的数据库服务器做过一次数据收集工作,从我局反馈的报表来看,问题主要集在中SQL语句上面,由于系统中有很多SQL没有得到较佳的执行计划,所以很多SQLphysical readslogical reads都较大,调优的目标就集中在SQL的优化上。

       如图四所示,SQL1执行了40w次以上,使用了总CPU资源的33.6%SQL2/SQL3虽然执行次数不是很多,但它的Get per Exec较大,每次19wlogical reads左右;这3SQL共使用CPU资源的33.6+26.4+26.1=86.1%,如果优化合适的话,应该可以将它们消耗的CPU资源降到40%左右,那如图三中所示的CPU time总的等待时间就会大幅下降;也就是说数据库任何坏的征兆,都会在多个地方体现,调优的首要工作,就是找出主要矛盾,然后分析该SQL的执行计划,找出较恰当的执行效果。

图四 最繁忙的SQL

图五 最繁忙的SQL2

       图四与图五实际上内容是一样的,只不过它们是用不同的性能指标去分析而已。图四从logical reads去衡量SQL的执行效果,图五从physical reads去衡量SQL的执行效果,如果不管从那个方面分析,它们都是必须解决的核心矛盾。从报表上看,还有很多其它的SQL需要优化,在些就不一一列举,具体见附件。

优化增值服务的费用预算

按天付费 6000 /天,初步预计需20个工作日,总费用为120000元。


24 01, 2005
优化及其准备工作
作者 xzh2000 19:25 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

优化及其准备工作
吃饭洗手,大家都是知道的,数据库优化前dba通常要做些什么准备工作呢?
一个初级dba成长为一个资深dba,这其中的苦乐又有谁知呢?
开花结果,是每一粒种子的希望;做为dba,谁不憧憬着在数据库上叱咤风云呢?
调优需要dba拥有丰富的基础知识,从系统环境、数据库设计、业务实现、SQL编写等,
每一项都不是一天两天就可以熟悉的,但并不妨碍初级dba走上调优之路.
dba看起来是个枯燥无味的工作,只有静下心来,才能领略其中三味,
并不一定只有资深dba才可以做优化,只要你愿意,你就可以踏上优化之路.

基础知识的准备:
1 优化基础之类的书是必要的.
如果你需要买书,可以到偶的blog看看偶所推荐的那本《Oracle9i性能调整》,
虽然翻译的不好,但该书的内容确实不错,调优基础知识大部分都已经有啦.
http://blog.itpub.net/post/96/14758
2 有较好的pl/sql编写基础.
好的pl/sql编写能力不仅是你在数据库管理方面游刃有余,而且也可以培训
程序员不要将存储对象写得一塌糊涂.如果你的pl/sql不是很熟悉,最好照着
oracle的在线文档练一练.
http://blog.itpub.net/post/96/13123
3 不要怕麻烦要经常做测试.
网上有很多SQL调优的案例,在google上搜一搜,以及关注一些oracle论坛上的贴子,
然后自己也照着做一遍,消化吸收别人的经验,只有长此以往地积思广益,在真正做优
化时就可以避免犯一些常识性错误.

优化知识的重点:
1 理解CBO/RBO
http://blog.csdn.net/lovexueer/archive/2003/12/31/21856.aspx
2 理解执行计划
http://www.itpub.net/304412.html
http://blog.itpub.net/post/96/2265
http://www.itpub.net/245240,2.html
3 理解优化提示(hints)
http://www.adp-gmbh.ch/ora/sql/hints.html

优化前需要注意什么呢
1 确定出性能较差的SQL及该SQL实现的相关业务
 了解性能较差的SQL及其实现的业务,看看能否通过优化业务流程来达到优化SQL性能,
 如果你做过开发,那在与程序员交流时就比较容易沟通,有很多SQL都可以能过优化业务
 流程来实现的。
2 确定SQL涉及表的数据分布、增长、索引情况
 了解数据的分布为索引创建提供依据(创建b-tree index还是bitmap index),
 了解数据增长为优化表结构提供依据(http://blog.itpub.net/post/96/14657),
 确定该表是否需要创建成分区表,确定分区表上的索引类型,
 确定需要创建的索引,并为索引指定一个比较好记忆的名称,
3 确定SQL执行计划及逻辑读、物理读、执行计划
 可以为SQL产生执行计划(含常量的SQL与绑定变量的SQL),
 理解执行计划及其及统计信息,
 可以用指定hints的方式改变SQL的执行计划


21 01, 2005
9204上dbv的一个bug
作者 xzh2000 18:01 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在9204上dbv如果不带blocksize这个参数将会输出所有的块都是坏块
dbv file='/home/oracle/oradata/esal/undotbs01.dbf'
DBVERIFY: Release 9.2.0.4.0 - Production on Fri Jan 21 17:24:20 2005
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
DBVERIFY - Verification starting : FILE = /home/oracle/oradata/esal/undotbs01.dbf
Page 1 is marked corrupt
***
Corrupt block relative dba: 0x000000f9 (file 0, block 1)
Bad header found during dbv:
Data in bad block -
type: 0 format: 7 rdba: 0x00b631c2
last change scn: 0x320c.c4000523 seq: 0xb flg: 0x15
consistency value in tail: 0x5f000000
check value in block header: 0x4, computed block checksum: 0x5450
spare1: 0x5c, spare2: 0x2, spare3: 0x5d3e
***

在9205中,如果dbv不带blocksize参数,将会直接报dbv-00103并终止
dbv file='/home/oracle/esal/ITEM.dbf'
DBVERIFY: Release 9.2.0.5.0 - Production on Fri Jan 21 17:29:45 2005
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
DBV-00103: Specified BLOCKSIZE (2048) differs from actual (8192)

如果在dbv带了blocksize参数,在9204/9205中都是正确的
dbv file='/home/oracle/oradata/esal/undotbs01.dbf' blocksize=8192
DBVERIFY: Release 9.2.0.4.0 - Production on Fri Jan 21 17:24:20 2005
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
DBVERIFY - Verification starting : FILE = /home/oracle/oradata/esal/undotbs01.dbf

dbv file='/home/oracle/esal/ITEM.dbf' blocksize=8192
DBVERIFY: Release 9.2.0.5.0 - Production on Fri Jan 21 17:30:31 2005
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
DBVERIFY - Verification starting : FILE = /home/oracle/esal/ITEM.dbf


19 01, 2005
表结构优化实例
作者 xzh2000 16:14 | Permalink 静态链接网址 | Comments 最新回复 (5) | Trackback 引用 (0) | 技术交流

表结构优化实例
本方法适合表中存在大量的标志字段,如下表,很多字段就只存储Y/N或0/1/2/4等,

如结构如下,
create table agent_settime_onself
( agent_settime_onself_id number(11,0),
 agent_card_type_id number(11,0) not null enable,
 start_time_1 char(5) default '00:00' not null enable,
 start_time_1_enabled char(1) default 'N',
 stop_time_1 char(5) default '23:59' not null enable,
 stop_time_1_enable char(1) default 'N',
 start_time_2 char(5) default '00:00' not null enable,
 start_time_2_enabled char(1) default 'N',
 stop_time_2 char(5) default '23:59'  not null enable,
 stop_time_2_enable char(1) default 'N',
 start_time_3 char(5) default '00:00' not null enable,
 start_time_3_enabled char(1) default 'N',
 stop_time_3 char(5) default '23:59' not null enable,
 stop_time_3_enable char(1) default 'N',
 start_time_4 char(5) default '00:00' not null enable,
 start_time_4_enabled char(1) default 'N',
 stop_time_4 char(5) default '23:59' not null enable,
 stop_time_4_enable char(1) default 'N',
 start_time_5 char(5) default '00:00' not null enable,
 start_time_5_enabled char(1) default 'N',
 stop_time_5 char(5) default '23:59' not null enable,
 stop_time_5_enable char(1) default 'N',
 start_time_6 char(5) default '00:00' not null enable,
 start_time_6_enabled char(1) default 'N',
 stop_time_6 char(5) default '23:59' not null enable,
 stop_time_6_enable char(1) default 'N',
 start_time_7 char(5) default '00:00' not null enable,
 start_time_7_enabled char(1) default 'N',
 stop_time_7 char(5) default '23:59' not null enable,
 stop_time_7_enable char(1) default 'N')

表的访问SQL如下:
select a.*,sysdate now,to_char(sysdate,'D') as week
from agent_settime_onself a
where ((start_time_1_enabled = 'Y' OR start_time_2_enabled = 'Y'
OR start_time_3_enabled = 'Y' OR start_time_4_enabled = 'Y'
OR start_time_5_enabled = 'Y' OR start_time_6_enabled = 'Y'
OR start_time_7_enabled = 'Y')
OR (stop_time_1_enable = 'Y' OR stop_time_2_enable = 'Y'
OR stop_time_3_enable = 'Y' OR stop_time_4_enable = 'Y'
OR stop_time_5_enable = 'Y' OR stop_time_6_enable = 'Y'
OR stop_time_7_enable = 'Y'))

这么多用于判断的字段,如果都创建索引也是不合理的,再说这些字段的数据分布不均匀,
如何对这样的表结构进行优化呢?优化后的表结构如下:
create table agent_settime_onself
( agent_settime_onself_id number(11,0),
 agent_card_type_id number(11,0) not null enable,
 start_time_1 char(5) default '00:00' not null enable,
 start_time_enabled char(7) default 'NNNNNNN',
 stop_time_1 char(5) default '23:59' not null enable,
 stop_time_enable char(7) default 'NNNNNNN',
 start_time_2 char(5) default '00:00' not null enable,
 stop_time_2 char(5) default '23:59'  not null enable,
 start_time_3 char(5) default '00:00' not null enable,
 stop_time_3 char(5) default '23:59' not null enable,
 start_time_4 char(5) default '00:00' not null enable,
 stop_time_4 char(5) default '23:59' not null enable,
 start_time_5 char(5) default '00:00' not null enable,
 stop_time_5 char(5) default '23:59' not null enable,
 start_time_6 char(5) default '00:00' not null enable,
 stop_time_6 char(5) default '23:59' not null enable,
 start_time_7 char(5) default '00:00' not null enable,
 stop_time_7 char(5) default '23:59' not null enable)

create index idx_aso_sta_enabled on agent_settime_onself(start_time_enabled);
create index idx_aso_sto_enabled on agent_settime_onself(stop_time_enabled);

那以后访问该表的SQL如下:
select a.*,sysdate now,to_char(sysdate,'D') as week
from agent_settime_onself a
where start_time_enabled = 'YYYYYYY'

select a.*,sysdate now,to_char(sysdate,'D') as week
from agent_settime_onself a
where stop_time_enabled = 'YYYYYYY'


19 01, 2005
SGA是否越大越好
作者 xzh2000 14:51 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

SGA是否越大越好?如何用statspack的报表来验证?
如果你有足够的内存,你会不会将SGA开得足够大?
有位朋友的物理内存16G,将SGA开到9G左右,实际上他的数据库才13G,
数据库几乎全被缓存到SGA中,但下边的人还是说慢,
statspack的报表显示如下:
Load Profile
~~~~~~~~~~~~                            Per Second       Per Transaction
                                   ---------------       ---------------
                  Redo size:              6,679.72             15,071.00
              Logical reads:             80,724.11            182,132.26
              Block changes:                 23.75                 53.58
             Physical reads:                  0.70                  1.57
            Physical writes:                  1.48                  3.34

Instance Efficiency Percentages (Target 100%)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            Buffer Nowait %:  100.00       Redo NoWait %:              100.00
            Buffer  Hit   %:  100.00    In-memory Sort %:              100.00
            Library Hit   %:   99.74        Soft Parse %:               99.93
         Execute to Parse %:   31.87         Latch Hit %:               99.87
Parse CPU to Parse Elapsd %:   95.57     % Non-Parse CPU:               98.71

由于SGA足够的大,它的数据库中Buffer Hint是100%,其它的各项指标也非常好,
但在Load Profile项中可以看到Logical reads比较突出,
然后看statspack报表的TOP SQL部分,发现SQL的单次逻辑读都比较大,
通过优化SQL,系统速度明显提高,然后将SGA从9G依次调到3G,
通过报表观察,各项指标并没有显示下降,top 5 event也没有什么变化,
然后将SGA从3G调到1G这时,虽然Load profile及Instance Efficiency per
的各项指标没有明显下降,但top 5 event中等待事件的数量上升的较多.

从这也可以看出,运转良好的数据库,它的数据量与SGA有一定的比例关系,
如果数据量一定的情况下,SGA大大超过那个比例,系统的性能并不能有很大的提高.
随着业务及数据量的增加,数据库的性能应该是慢慢恶化,
如果性能调优的速度赶不上系统恶化的速度,那应用的速度就会让客户无法忍受


17 01, 2005
statspack的若干使用技巧
作者 xzh2000 19:59 | Permalink 静态链接网址 | Comments 最新回复 (4) | Trackback 引用 (0) | 技术交流

1 如何修改statspack的脚本产生自定义报表?
2 如何用statspack的报表确定热表及索引?
3 如何用statspack的报表确定keep池与default池的分配?
4 如何用crontab定期产生statspack的报表?

使用statspack有相当长的时间啦,从最初的推崇,到后来的否定,
再到现在的肯定,发现它已经是我工作中不可缺少的一部分,
每晚上读当天产生的statspack报表就成了一种习惯,
越是读得认真,越是觉得statspack妙用无穷,
现在本人就将一些心得告诉大家,希望对你有所帮助。

一 如何修改statspack的脚本产生自定义报表?
通常statspack报表可以满足大部分的需要,有时我们需要对产生报表的脚本
进行一些微小的修改,这样产生的报表就更有用途啦.
比如说某些SQL很多,但在statspack产生的报表中,每个SQL只显示5行,
结果有些比较长的SQL就只能看到一部分;
又如在top events部分,标准的报表只显示top 5,
其实我们可以显示更多的events,那如何修改呢?
用编辑工具(在linux下用vi)打开$ORACLE_HOME/rdbms/admin/sprepins.sql
define top_n_events = 5; // top 5 events
define top_n_sql = 65; // top sql
define top_n_segstat = 5; // top 5 segstat
define num_rows_per_hash=5; // 每个SQL显示5行
就看到在该脚本中已经定义了一些常数,我们只需要把它改为我们需要的值就可以啦.
define top_n_events = 10; // top 10 events
define top_n_sql = 65; // top sql
define top_n_segstat = 10; // top 10 segstat
define num_rows_per_hash=10; // 每个SQL显示10行
做过修改后,然后大家就可以看到自己要的效果啦.

二 如何用statspack的报表确定热表及索引?
如果想用statspack表确定热表及索引,必须修改statspack快照的收集级别,
8i中statspack共有三种快照级别,默认值是5
select * from STATS$level_DESCRIPTION;
SNAP_LEVEL DESCRIPTION
---------- ----------------------------------------------------------------
0 一性性能统计:包含回退段状态、字典缓存、SGA、系统事件、后台事件、会话事件、
系统统计、等待统计、锁统计、闩锁统计
5 增加了收集SQL的信息、并包括0级收集的信息.
10 增加了收集子闩锁的信息,并包括所有低级别的信息
在9i中statspack共有五种快照级别,默认值是5
select * from STATS$level_DESCRIPTION;
SNAP_LEVEL DESCRIPTION
---------- ----------------------------------------------------------------
0 一性性能统计:包含回退段状态、字典缓存、SGA、系统事件、后台事件、会话事件、
系统统计、等待统计、锁统计、闩锁统计
5 增加了收集SQL的信息、并包括0级收集的信息.
6 增强了在SQL收集信息方面的功能(列出占用资源较高的SQL),并包所有低级别的信息
7 增加了收集段级别的统计信息(如段的逻辑读与物理读、行锁、ITL及buffer busy waits),
并包括所有低级别的信息
10 增加了收集子闩锁的信息,并包括所有低级别的信息
如果你收用statspack确定热表及热索引,那就需要使用7/10的级别来收集快照。
//通过这样的设置,以后的收集级别都将是7级。
//如果你只是想本次改变收集级别,可以忽略i_modify_parameter参数。
SQL>execute statspack.snap(i_snap_level=>7,i_modify_parameter=>true);
SQL>execute statspack.snap(i_snap_level=>7);
修改完收集级别后,那大家就可以根据自己的需要设定收集的频率,
现在我们只需要注意statspack报表中的“段级别的统计信息”:
Top 5 Logical Reads per Segment for DB: ESAL Instance: esal Snaps: 2368 -2380
-> End Segment Logical Reads Threshold: 10000
Subobject Obj. Logical
Owner Tablespace Object Name Name Type Reads %Total
---------- ---------- -------------------- ---------- ----- ------------ -------
CYBERCAFE TS_CYBERCA AGENT_CARD_TYPE TABLE 115,220,864 18.07
CYBERCAFE TS_CYBERCA GAME_CARD_TYPE TABLE 79,103,600 12.40
CYBERCAFE TS_CYBERCA AGENT_TASK TABLE 57,030,304 8.94
CYBERCAFE TS_CYBERCA AGENT_PRICE_LEVEL_OW TABLE 46,393,968 7.28
CYBERCAFE TS_CYBERCA IDX_ASL_RESLOG_ID INDEX 23,261,600 3.65
-------------------------------------------------------------
Top 5 Physical Reads per Segment for DB: ESAL Instance: esal Snaps: 2368 -2380
-> End Segment Physical Reads Threshold: 1000
Subobject Obj. Physical
Owner Tablespace Object Name Name Type Reads %Total
---------- ---------- -------------------- ---------- ----- ------------ -------
CYBERCAFE TS_CYBERCA AGENT_GAME_CARD_GM13 TABLE 76,476 7.36
CYBERCAFE TS_CYBERCA AGENT_SALE_LOG ASL_200500 TABLE 61,270 5.89
CYBERCAFE TS_CYBERCA RESELLER_LOG RL_200412 TABLE 48,950 4.71
CYBERCAFE TS_CYBERCA AGENT_GAME_CARD_GM14 TABLE 46,259 4.45
CYBERCAFE TS_CYBERCA AGENT_CAPITAL_LOG ACL_200500 TABLE 45,476 4.37
-------------------------------------------------------------
Top 5 Buf. Busy Waits per Segment for DB: ESAL Instance: esal Snaps: 2368 -2380
-> End Segment Buffer Busy Waits Threshold: 100
Subobject Obj. Buffer Busy
Owner Tablespace Object Name Name Type Waits %Total
---------- ---------- -------------------- ---------- ----- ------------ -------
CYBERCAFE TS_CYBERCA AGENT_TASK TABLE 22 36.07
CYBERCAFE TS_CYBERCA AGENT_CARD_TYPE TABLE 9 14.75
CYBERCAFE TS_CYBERCA IDX_RESACC_UPDTIME INDEX 5 8.20
CYBERCAFE TS_CYBERCA AGENT_SALE_LOG ASL_200501 TABLE 4 6.56
CYBERCAFE TS_CYBERCA IDX_ACL_ACPITAL_LOGI INDEX 4 6.56
-------------------------------------------------------------
Top 5 Row Lock Waits per Segment for DB: ESAL Instance: esal Snaps: 2368 -2380
-> End Segment Row Lock Waits Threshold: 100
Subobject Obj. Row Lock
Owner Tablespace Object Name Name Type Waits %Total
---------- ---------- -------------------- ---------- ----- ------------ -------
CYBERCAFE TS_CYBERCA IDX_APL_GCTID2 APL_200501 INDEX 54 24.77
CYBERCAFE TS_CYBERCA IDX_RB_RESELLER_ID INDEX 41 18.81
CYBERCAFE TS_CYBERCA IDX_RL_RESLOG_ID INDEX 38 17.43
CYBERCAFE TS_CYBERCA IDX_ACT_ACT_ID INDEX 17 7.80
CYBERCAFE TS_CYBERCA IDX_SERVICE_ID INDEX 14 6.42
-------------------------------------------------------------
在这里可以看到逻辑读/物理读/缓存忙/行锁符合条件的一些对象,通过这些对象,
可以确定热的表及索引,然后分析如何对业务进行优化,降低对这些表的访问量等。
如果你觉得显示top 5 segment不够的话,可以按一所述修改top_n_segstat,
然后就可以显示更多的符合条件的对象,然后将这些热表放到keep池中。

三 如何用statspack的报表确定keep池与default池的分配?
如果你想使用default池与keep池,在9i中需要分配db_cache_size及
db_keep_cache_size参数,但如何确定它们的大小呢?我们可以根据2所示的一些
热表,计算热表放入keep池需要的内存,然后用将表放入相应的pool中.
alter table &table_name storage(buffer_pool &buffer_pool);
将确定的热表放入keep中之后,然后收集一段时间后再产生一个新的报表:
Buffer Pool Statistics for DB: ESAL Instance: esal Snaps: 2277 -2289
-> Standard block size Pools D: default, K: keep, R: recycle
-> Default Pools for other block sizes: 2k, 4k, 8k, 16k, 32k
Free Write Buffer
Number of Cache Buffer Physical Physical Buffer Complete Busy
P Buffers Hit % Gets Reads Writes Waits Waits Waits
--- ---------- ----- ----------- ----------- ---------- ------- -------- ------
D 128,128 99.7 482,298,597 1,557,980 265,662 0 0 88
K 32,032 100.0 372,560,023 13,951 42,405 0 0 17
-------------------------------------------------------------
确定keep池与default的需要内存时,可以根据这一部分对keep池与default池的大小进行评估,
如果K所标识的cache hit%比较小,说明keep池不足,如果D显示的cache hit%比较小,说明default池
分配怀足,如果K是的default显示是100%,那们可以将更多的热表放入到keep池中,
然后经过一段时间的调整,相信可以将default池与keep池调到一个相对比较合适的集团。

四 如何用crontab定期产生statspack的报表?
看了一段时间的statspack报表后,就懒于每天手工去产生一个报表,那如何产系统自动产生一个报表呢?
经过测试,用crontab可以方便地产生报表,然后通过sendmail直接发到相关人员的邮箱中.
[oracle@www1 sql]$ more backup/auto_send_perf.sh
#!/bin/sh
. ~oracle/.bash_profile

/home/oracle/product/9.2.0/bin/sqlplus -s aaa/bbb@ccc<<!
set head off
set timing off
spool /home/oracle/sql/backup/snap_begin.lst
select min(snap_id) snap_id
from stats$snapshot
where snap_time between trunc(sysdate) and trunc(sysdate)+1;
spool off
spool /home/oracle/sql/backup/snap_end.lst
select max(snap_id) snap_id
from stats$snapshot
where snap_time between trunc(sysdate) and trunc(sysdate)+1;
spool off
exit
!

BEGIN_SNAP=`cat /home/oracle/sql/backup/snap_begin.lst | tail -n 2`
END_SNAP=`cat /home/oracle/sql/backup/snap_end.lst | tail -n 2`
#END_SNAP=`expr $BEGIN_SNAP + 13`
REPORT_NAME=/home/oracle/sql/report/sp`date +%m%d`_ac

/home/oracle/product/9.2.0/bin/sqlplus -s aaa/bbb@ccc<<!
define begin_snap=$BEGIN_SNAP
define end_snap=$END_SNAP
define report_name=$REPORT_NAME
@?/rdbms/admin/spreport
exit
!

mail -s "perfstat report" ddd@eee.fff < /home/oracle/sql/report/sp`date +%m%d`_ac.lst

[oracle@www1 sql]$crontab -l
* 21 * * * /home/oracle/sql/backup/auto_send_perf.sh >> /home/oracle/sql/backup/perf.lst 2>&1

说明:从早上8点到晚上8点之间进行快照收集,9点执行cron进程启动,产生报表的快照也限于当天收集的快照,
将当天最小的snap_id与最大的snap_id放到两个文件中,在sheel中读出,并计算出一个报表名称,
最后产生的报表通过sendmail发送到相关人员的邮箱,然后每天晚只需要收邮件就可以看到当天的报表啦。


14 01, 2005
fast full index scan[转载]
作者 xzh2000 17:41 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

Evaluating Oracle index access methods

Oracle9i offers a variety of indexing methods including b-tree, bitmapped, and function-based indexes. Regardless of the index structure, an Oracle index can be thought of as a pair bond of a symbolic key, paired with a ROWID.

The goal of Oracle index access is to gather the ROWIDs required to quickly retrieve the desired rows from the table. Within Oracle, we see the following types of index access.

 查看全文

14 01, 2005
index rebuild的实现过程
作者 xzh2000 16:16 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

 explain plan for alter index idx_anno_id rebuild;

Explained.

Elapsed: 00:00:00.00
15:42:13 SQL> @plan

PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------

-----------------------------------------------------------------------
| Id  | Operation              |  Name        | Rows  | Bytes | Cost  |
-----------------------------------------------------------------------
|   0 | ALTER INDEX STATEMENT  |              |   879 |  4395 |    13 |
|   1 |  INDEX BUILD NON UNIQUE| IDX_ANNO_ID  |       |       |       |
|   2 |   SORT CREATE INDEX    |              |   879 |  4395 |       |
|   3 |    INDEX FAST FULL SCAN| IDX_ANNO_ID  |   879 |  4395 |       |
-----------------------------------------------------------------------


11 01, 2005
dataguard在优化中的运用
作者 xzh2000 20:34 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

dataguard在优化中的运用
dataguard不仅在数据安全性、高可用性等方面有很突出的作用,
同时也可以减轻主生产库的压力,即可以承担部分报表的处理任务.

如果有足够的机器,建议主生产库一拖二,一个物理备用库,一个逻辑备用库,
如果只有一台机器的话,那就只能配置成物理备用库,众所周知,物理库用库
通常在managed recover状态是不能提供查询的,如果想提供查询,就必须
在open read only状态.

在open read only状态,当然是不可以再进行即时归档恢复,
但并不防碍主生产库将归档源源不地传送到备用库,通常大的报
表对当天的统计并不是十分关注,所以可以把归档在备用机上的
恢复放到晚上进行。

通过crontab在每天早上凌晨3:00开始运行备用库进行恢复的shell,然后在凌晨6:00钟
左右crontab进程再将managed recover取消,将数据库打开到open read only状态,
这样就物理备用库在安全性、高可用没有降低的情况,可以提供一部分的报表业务,可以很
大程度减轻主生产库的压力。

备用库上开始归档恢复的脚本,注意一定要先kill掉备用库上的连接(假如有的话).

备用库上开始归档恢复的脚本:

[oracle@data2 work]$ more startrecovery.sh

#!/bin/sh

source ~oracle/.bash_profile

 

$ORACLE_HOME/bin/sqlplus /nolog<<!

connect / as sysdba;

alter database recover managed standby database disconnect from session;

exit

!

备用库上取消归档恢复,打开数据库到open read only状态的脚本:

[oracle@data2 work]$ more stoprecovery.sh

#!/bin/sh

source ~oracle/.bash_profile

 

$ORACLE_HOME/bin/sqlplus /nolog<<!

connect / as sysdba;

alter database recover managed standby database cancel;

alter database open read only;

exit

!

调度crontab进程:

[oracle@data2 work]$ crontab -e

00 02 * * * /home/oracle/backup/work/startrecovery.sh

00 05 * * * /home/oracle/backup/work/stoprecovery.sh


11 01, 2005
9i与10g中SGA的粒度演变
作者 xzh2000 10:06 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

9i与10g中SGA的粒度演变
在oracle9i的文档中,关于粒度的描述译:
granule size的大小应该取决于实际为oracle分配的SGA大小
也就是show sga时Total System Global Area 的值

当这个值小于128M的时候为4M
当这个值大于128M的时候。就会根据系统的不同产生不同的结果。
如:在32bit的win是8M。在32bit的linux是16M.

9i
sql>show sga
Total System Global Area  991500264 bytes
Fixed Size                   452584 bytes
Variable Size             201326592 bytes
Database Buffers          788529152 bytes
Redo Buffers                1191936 bytes
sql>col component format a27
sql>select component,current_size,min_size,max_size,oper_count,granule_size from V$SGA_DYNAMIC_COMPONENTS;
COMPONENT          CURRENT_SIZE   MIN_SIZE   MAX_SIZE OPER_COUNT GRANULE_SIZE
------------------ ------------ ---------- ---------- ---------- ------------
shared pool           134217728  134217728  134217728          0     16777216
large pool             16777216   16777216   16777216          0     16777216
buffer cache          788529152  788529152  788529152          0     16777216

10g
sql>show sga
Total System Global Area  780140544 bytes
Fixed Size                   780864 bytes
Variable Size             140776896 bytes
Database Buffers          637534208 bytes
Redo Buffers                1048576 bytes
sql>col component format a27
sql>select component,current_size,min_size,max_size,oper_count,granule_size from V$SGA_DYNAMIC_COMPONENTS;
COMPONENT                   CURRENT_SIZE   MIN_SIZE   MAX_SIZE OPER_COUNT GRANULE_SIZE
--------------------------- ------------ ---------- ---------- ---------- ------------
shared pool                    134217728  134217728          0          0      4194304
large pool                       4194304    4194304          0          0      4194304
java pool                              0          0          0          0      4194304
streams pool                           0          0          0          0      4194304
DEFAULT buffer cache           536870912  536870912          0          0      4194304
KEEP buffer cache              100663296  100663296          0          0      4194304
RECYCLE buffer cache                   0          0          0          0      4194304
DEFAULT 2K buffer cache                0          0          0          0      4194304
DEFAULT 4K buffer cache                0          0          0          0      4194304
DEFAULT 8K buffer cache                0          0          0          0      4194304
DEFAULT 16K buffer cache               0          0          0          0      4194304
DEFAULT 32K buffer cache               0          0          0          0      4194304
OSM Buffer Cache                       0          0          0          0      4194304


说明:
在10g,提供了比9i更小的粒度,在内存管理上就更为精细,使内存的使用更为允分.


07 01, 2005
index skip scan的一个发现
作者 xzh2000 16:34 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

SQL>explain plan for select game_card_id from game_card_GM50180

where INUSED_USER_ID=:"SYS_B_0" and bill_number = :"SYS_B_1" order by game_card_id;

Explained.

Elapsed: 00:00:00.01
15:46:20 SQL> @plan

PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------
| Id  | Operation                    |  Name                   | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                         |     1 |    20 |     5   (0)|
|   1 |  SORT ORDER BY               |                         |     1 |    20 |     5   (0)|
|*  2 |   TABLE ACCESS BY INDEX ROWID| GAME_CARD_GM50180       |     1 |    20 |     2   (0)|
|*  3 |    INDEX SKIP SCAN           | IDX_GCTID_IUID_GM50180  |  2187 |       |    10   (0)|
---------------------------------------------------------------------------------------------

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

   2 - filter("GAME_CARD_GM50180"."BILL_NUMBER"=:Z)
   3 - access("GAME_CARD_GM50180"."INUSED_USER_ID"=:Z)
       filter("GAME_CARD_GM50180"."INUSED_USER_ID"=:Z)

本来发现bill_number这个字段没有索引,正想用hints强制idx_gctid_iuid_gm50180进行SKIP SCAN时,在解释执行计划,oracle却告诉偶已经使用了INDEX SKIP SCAN,难道不用hints也可以让oracle选择到理想的索引吗?


05 01, 2005
表及索引monitoring的使用
作者 xzh2000 17:48 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

关于对表及索引monitoring的使用.
除了logmnr及audit之外,如何才能监控对表的若干操作呢?
大家可以试试表的monitoring.表的monitoring与索引的
monitoring稍有区别.可以看出table及index的monitoring功能都很弱,如果相做到精细监控,还是用audit比较好。
表的monitoring主要记录针对的一些操作,如truncate/delete/update/insert等
索引的monitoring主要记录索引是否被使用过.
如何监控/取消监控表呢?
alter table &table_name monitoring;
alter table &table_name nomonitoring;
如何监控/取消监控索引呢?
alter index &index_name monitoring usage;
alter index &index_name nomonitoring usage;

@connect_sys
Enter value for passwd: oracle
Connected.
16:27:08 SQL> desc DBA_TAB_MODIFICATIONS
 Name                                                              Null?    Type
 ----------------------------------------------------------------- -------- ---------------------------------------------
 TABLE_OWNER                                                                VARCHAR2(30)
 TABLE_NAME                                                                 VARCHAR2(30)
 PARTITION_NAME                                                             VARCHAR2(30)
 SUBPARTITION_NAME                                                          VARCHAR2(30)
 INSERTS                                                                    NUMBER
 UPDATES                                                                    NUMBER
 DELETES                                                                    NUMBER
 TIMESTAMP                                                                  DATE
 TRUNCATED                                                                  VARCHAR2(3)

16:27:13 SQL> select count(*) from DBA_TAB_MODIFICATIONS ;

  COUNT(*)
----------
         0

1 row selected.

create table test monitoring as select count(*) as rns from all_users ;

Table created.

Elapsed: 00:00:00.05
16:28:24 SQL> truncate table test;

Table truncated.

Elapsed: 00:00:00.12
16:28:41 SQL> @connect_sys
Enter value for passwd: oracle
Connected.
16:28:48 SQL> select count(*) from dba_tab_modifications ;

  COUNT(*)
----------
         1

1 row selected.

Elapsed: 00:00:00.06

 select table_name,inserts,updates,deletes,timestamp,truncated from dba_tab_modifications;

TABLE_NAME            INSERTS    UPDATES    DELETES TIMESTAMP           TRU
------------------ ---------- ---------- ---------- ------------------- ---
TEST                        0          0          0 2005-01-05 16:29:46 YES

create table test2 as select object_id,object_name from all_objects;

Table created.

Elapsed: 00:00:00.61
16:57:06 SQL> create index idx_test2_objectid on test2(object_id);

Index created.

alter index idx_test2_objectid monitoring usage;

Index altered.

Elapsed: 00:00:00.02
17:02:30 SQL> select * from v$object_usage;

INDEX_NAME                       TABLE_NAME                     MON USE START_MONITORING    END_MONITORING
-------------------------------- ------------------------------ --- --- ------------------- -------------------
IDX_TEST2_OBJECTID               TEST2                          YES NO  01/05/2005 17:03:36

1 row selected.

Elapsed: 00:00:00.05
17:02:40 SQL> select count(*) from test2 where object_id > 3000;

  COUNT(*)
----------
     10981

1 row selected.

Elapsed: 00:00:00.02
17:03:01 SQL> select * from v$object_usage;

INDEX_NAME                       TABLE_NAME                     MON USE START_MONITORING    END_MONITORING
-------------------------------- ------------------------------ --- --- ------------------- -------------------
IDX_TEST2_OBJECTID               TEST2                          YES YES 01/05/2005 17:03:36


27 12, 2004
outln在9204与10.1.0.2差异
作者 xzh2000 15:26 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

OUTLN在9.2.0.4与10.1.0.2上的差异

在9.2.0.4中的测试
SQL> @connect_test
Connected.
14:48:40 SQL> create table test1(id int,name varchar2(20));
Table created.
14:48:53 SQL> create table test2(id int,age number(3));
Table created.
14:49:02 SQL> create or replace outline ol_test on select t1.id,t1.name,t2.age from test1 t1,test2 t2 where t1.id=t2.id;
Outline created.

14:49:35 SQL> set autot trace exp
14:49:47 SQL> select t1.id,t1.name,t2.age from test1 t1,test2 t2 where t1.id=t2.id;
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=5 Card=82 Bytes=
          4182)
   1    0   HASH JOIN (Cost=5 Card=82 Bytes=4182)
   2    1     TABLE ACCESS (FULL) OF 'TEST1' (Cost=2 Card=82 Bytes=205
   3    1     TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=82 Bytes=213

14:50:20 SQL> connect outln/......
Connected.
14:50:38 SQL> select ol_name,hint#,hint_text from ol$hints;
OL_NAME                             HINT# HINT_TEXT
------------------------------ ---------- --------------------------------
OL_TEST                                 1 NO_EXPAND
OL_TEST                                 2 PQ_DISTRIBUTE(T2 NONE NONE)
OL_SALES                                3 LEADING(A)
OL_TEST                                 3 USE_HASH(T2)
OL_TEST                                 4 ORDERED
OL_TEST                                 5 NO_FACT(T2)
OL_TEST                                 6 NO_FACT(T1)
OL_TEST                                 7 FULL(T2)
OL_TEST                                 8 FULL(T1)
OL_TEST                                 9 NOREWRITE
OL_TEST                                10 NOREWRITE
OL_SALES_2                              3 USE_HASH(A)
12 rows selected.
Elapsed: 00:00:00.00
14:50:50 SQL> delete from ol$hints where ol_name='OL_TEST' and hint#<>3;
9 rows deleted.
14:51:49 SQL> select ol_name,hint#,hint_text from ol$hints;

OL_NAME                             HINT# HINT_TEXT
------------------------------ ---------- --------------------------------
OL_TEST                                 3 USE_HASH(T2)
OL_SALES                                3 LEADING(A)
OL_SALES_2                              3 USE_HASH(A)
3 rows selected.
14:51:54 SQL> commit;
Commit complete.
14:51:56 SQL> update ol$hints set hint_text='USE_NL(T1,T2)' where ol_name='OL_TEST';
1 row updated.
14:52:55 SQL> commit;
Commit complete.
14:52:57 SQL> select ol_name,hint#,hint_text from ol$hints;

OL_NAME                             HINT# HINT_TEXT
------------------------------ ---------- --------------------------------
OL_TEST                                 3 USE_NL(T1,T2)
OL_SALES                                3 LEADING(A)
OL_SALES_2                              3 USE_HASH(A)
3 rows selected.
14:53:00 SQL> @connect_test
Connected.
14:53:12 SQL> alter session set use_stored_outlines=default;
Session altered.
14:53:23 SQL> select name,used from user_outlines;
NAME                                                   USED
------------------------------------------------------ ---------
OL_TEST                                                UNUSED
1 row selected.
14:53:52 SQL> set autot trace exp
14:54:04 SQL> select t1.id,t1.name,t2.age from test1 t1,test2 t2 where t1.id=t2.id;
Elapsed: 00:00:00.00
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=FIRST_ROWS (Cost=166 Card=82 Byte
          s=4182)
   1    0   NESTED LOOPS (Cost=166 Card=82 Bytes=4182)
   2    1     TABLE ACCESS (FULL) OF 'TEST1' (Cost=2 Card=82 Bytes=205
   3    1     TABLE ACCESS (FULL) OF 'TEST2' (Cost=2 Card=1 Bytes=26)
14:57:37 SQL> select name,used from user_outlines;
NAME                                                   USED
------------------------------------------------------ ---------
OL_TEST                                                USED

在10.1.0.2上的测试
14:48:40 SQL> create table test1(id int,name varchar2(20));
Table created.
14:48:53 SQL> create table test2(id int,age number(3));
Table created.
SQL> create or replace outline ol_test on select * from test1,test2 where test1.id=test2.id;
Outline created.
SQL> select used from user_outlines;
USED
------
UNUSED
select * from test1,test2 where test1.id=test2.id;
no rows selected
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=5 Card=82 Bytes=41
   1    0   HASH JOIN (Cost=5 Card=82 Bytes=4100)
   2    1     TABLE ACCESS (FULL) OF 'TEST2' (TABLE) (Cost=2 Card=82 B
   3    1     TABLE ACCESS (FULL) OF 'TEST1' (TABLE) (Cost=2 Card=82 B

select hint_text from ol$hints;

HINT_TEXT
-------------------------------------------------------------------------------------------------------------------------
NO_EXPAND(@"SEL$1" )
NO_SWAP_JOIN_INPUTS(@"SEL$1" "TEST2"@"SEL$1")
PQ_DISTRIBUTE(@"SEL$1" "TEST2"@"SEL$1" NONE NONE)
USE_HASH(@"SEL$1" "TEST2"@"SEL$1")
LEADING(@"SEL$1"  "TEST1"@"SEL$1" "TEST2"@"SEL$1")
NO_STAR_TRANSFORMATION(@"SEL$1" )
NO_FACT(@"SEL$1" "TEST2"@"SEL$1")
NO_FACT(@"SEL$1" "TEST1"@"SEL$1")
FULL(@"SEL$1" "TEST2"@"SEL$1")
FULL(@"SEL$1" "TEST1"@"SEL$1")
NO_REWRITE(@"SEL$1" )
NO_REWRITE(@"SEL$1" )

update ol$hints set hint_text=replace(hint_text,'USE_HASH','USE_NL');
12 rows updated.
SQL> select hint_text from ol$hints;

HINT_TEXT
-------------------------------------------------------------------------------------------------------------------------
NO_EXPAND(@"SEL$1" )
NO_SWAP_JOIN_INPUTS(@"SEL$1" "TEST2"@"SEL$1")
PQ_DISTRIBUTE(@"SEL$1" "TEST2"@"SEL$1" NONE NONE)
USE_NL(@"SEL$1" "TEST2"@"SEL$1")
LEADING(@"SEL$1"  "TEST1"@"SEL$1" "TEST2"@"SEL$1")
NO_STAR_TRANSFORMATION(@"SEL$1" )
NO_FACT(@"SEL$1" "TEST2"@"SEL$1")
NO_FACT(@"SEL$1" "TEST1"@"SEL$1")
FULL(@"SEL$1" "TEST2"@"SEL$1")
FULL(@"SEL$1" "TEST1"@"SEL$1")
NO_REWRITE(@"SEL$1" )
NO_REWRITE(@"SEL$1" )
SQL> delete from ol$hints where hint#<>4;
11 rows deleted.

SQL> commit;

SQL> select hint_text,hint# from ol$hints;

HINT_TEXT                                    HINT#
--------------------------------------- ----------
USE_NL(@"SEL$1" "TEST2"@"SEL$1")                 4

select * from test1,test2 where test1.id=test2.id;

no rows selected
Execution Plan
----------------------------------------------------------
   0      SELECT STATEMENT Optimizer=ALL_ROWS (Cost=5 Card=82 Bytes=41
   1    0   HASH JOIN (Cost=5 Card=82 Bytes=4100)
   2    1     TABLE ACCESS (FULL) OF 'TEST2' (TABLE) (Cost=2 Card=82 B
   3    1     TABLE ACCESS (FULL) OF 'TEST1' (TABLE) (Cost=2 Card=82 B

SQL> select used from user_outlines;

USED
------
USED

说明,在9.2.0.4中,outln很方便就达到偶想预期的效果,但在10.1.0.2中,

虽然outln也被使用,但它却没有达到偶想要的效果,改变SQL的执行计划


27 12, 2004
Oracle Enqueue and Lock
作者 xzh2000 13:54 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

http://publib.boulder.ibm.com/tividd/td/oracle2/GC32-0454-00/en_US/HTML/oracle20rgf2k75.htm

http://www.csee.umbc.edu/help/oracle8/server.815/a67790/apb.htm

https://cwisdb.cc.kuleuven.ac.be/ora10doc/server.101/b10755/enqueues.htm


23 12, 2004
关于分区表的性能问题
作者 xzh2000 15:00 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

关于分区表的性能问题

create table test1(test_id number(9),id number(9),log_time date)
partition by range(log_time)
(partition t1_01 values less than (to_date('2004-02-01','yyyy-mm-dd')),
partition t1_02 values less than (to_date('2004-03-01','yyyy-mm-dd')),
partition t1_03 values less than (to_date('2004-04-01','yyyy-mm-dd')),
partition t1_04 values less than (to_date('2004-05-01','yyyy-mm-dd')),
partition t1_05 values less than (to_date('2004-06-01','yyyy-mm-dd')),
partition t1_06 values less than (to_date('2004-07-01','yyyy-mm-dd')),
partition t1_07 values less than (to_date('2004-08-01','yyyy-mm-dd')),
partition t1_08 values less than (to_date('2004-09-01','yyyy-mm-dd')),
partition t1_09 values less than (to_date('2004-10-01','yyyy-mm-dd')),
partition t1_10 values less than (to_date('2004-11-01','yyyy-mm-dd')),
partition t1_11 values less than (to_date('2004-12-01','yyyy-mm-dd')),
partition t1_12 values less than (to_date('2005-01-01','yyyy-mm-dd')));

create table test2(test_id number(9),id number(9),log_time date);

create sequence seq_t1;
create sequence seq_t2;

create index idx_test1_logtime on test1(log_time) local;
create index idx_test1_testid on test1(test_id) local;
create index idx_test1_id on test1(id) local;

create index idx_test2_logtime on test2(log_time);
create index idx_test2_testid on test2(test_id);
create index idx_test2_id on test2(id);

关于分区表与非分区表的测试
begin
for i in 1 .. 1000 loop
for j in 1 .. 12 loop
for k in 1 .. 28 loop
insert into test1 values(seq_t1.nextval,i,to_date('2004-'||to_char(j)||'-'||to_char(k),'yyyy-mm-dd'));
end loop;
end loop;
end loop;
end;
/
begin
for i in 1 .. 1000 loop
for j in 1 .. 12 loop
for k in 1 .. 28 loop
insert into test2 values(seq_t2.nextval,i,to_date('2004-'||to_char(j)||'-'||to_char(k),'yyyy-mm-dd'));
end loop;
end loop;
end loop;
end;
/

SQL> select count(*) from test1;

COUNT(*)
----------
336000

Elapsed: 00:00:00.02

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1104 consistent gets
0 physical reads
0 redo size
394 bytes sent via SQL*Net to client
508 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

SQL> select count(*) from test2;

COUNT(*)
----------
336000

Elapsed: 00:00:00.02

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
1067 consistent gets
0 physical reads
0 redo size
394 bytes sent via SQL*Net to client
508 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed


统计显示,分区表在全表扫描时将比非分区表需要更多的逻辑读

SQL> select count(*) from test1 where test_id = 1000;

COUNT(*)
----------
1

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
24 consistent gets
0 physical reads
0 redo size
393 bytes sent via SQL*Net to client
508 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

SQL> select count(*) from test2 where test_id = 337000;

COUNT(*)
----------
1

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
2 consistent gets
0 physical reads
0 redo size
393 bytes sent via SQL*Net to client
508 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

在没有与分区字段组合查询时,分区表需要更多的逻辑读

SQL> select count(*)
2 from test1
3 where id = 1000
4 and log_time between to_date('2004-11-01','yyyy-mm-dd') and to_date('2004-11-30 23:59:59','yyyy-mm-dd hh24:mi:ss');

COUNT(*)
----------
28

Elapsed: 00:00:00.01

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
393 bytes sent via SQL*Net to client
508 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)

SQL> select count(*)
2 from test2
3 where id = 1000
4 and log_time between to_date('2004-11-01','yyyy-mm-dd') and to_date('2004-11-30 23:59:59','yyyy-mm-dd hh24:mi:ss');

COUNT(*)
----------
28

Elapsed: 00:00:00.00

Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
5 consistent gets
0 physical reads
0 redo size
393 bytes sent via SQL*Net to client
508 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed

与分区字段组合查询时,分区表比非分区表有更好的性能优势


22 12, 2004
数据库高速缓存配置演变
作者 xzh2000 11:51 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在9i中,数据库高速缓存配置有两种方式:

1 用db_cache_size/db_keep_cache_size/db_recycle_cache_size
2 用db_buffer_blocks/buffer_pool_keep/buffer_pool_recycle

 查看全文

22 12, 2004
ads3中sga突破1.7G的限制
作者 xzh2000 11:36 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

Ads3sga如何突破1.7G/4G的限制?

内存在4G以内的方法(比ads2.1操作简单一些)

       #cd /home/oracle/9.2.0.4/rdbms/lib

       #genksms –s 0x15000000 > ksms.s   必须root,需要有oracle环境变量

$make –f ins_rdbms.mk ksms.o       必须oracle用户

$make –f ins_rdbms.mk ioracle

 

通过这种方法,ads3oracle9.2.0.4sga可以达到2.6G左右,在4G的机器上也算是比较合理的配置,oracle10.1.0.1sga照此方法也可以达到2.6G左右吧;genksms中的0x15000000可以提高到0x18000000,不过对sga的提高没有多大用处。

 

具体详细操作见如下两个贴子:

http://www.itpub.net/showthread.php?s=&threadid=124424

http://www.itpub.net/showthread.php?s=&threadid=195413

 

内存在8G以内的方法

       9.2.0.4在安装时shmmax设置成2147483648即可,安装后用方法一可以将sga提高到2.6G左右,但无法突破4G的限制,只有使用very large memory参数啦,创建fpile,然后删除spfileshowdown数据库。

initsid.ora中添加

*.use_indirect_data_buffers=true

*.db_block_buffers=500000

 

然后重启动数据库,sga将达到4.5g左右,加上pga1goracle将要使用的内存大约在6g以内,基本上算比较合理的配置啦;但oracle10.1.0.1使用该方法无效,如果谁找到了如何配置的请告诉我。

8g内存的系统中,当db_block_buffers>520000时,就会报ORA-27102: out of memory

Linux Error: 28: No space left on devic错误,如果你有解决办法,也请你告诉我;目前找不到将ads3oracle10.1.0sga突破4g的限制。


21 12, 2004
在job中动态创建mview?
作者 xzh2000 15:08 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
http://www.itpub.net/303549.html
20 12, 2004
返回记录集的存储过程
作者 xzh2000 14:09 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

返回记录集的存储过程

 

测试过程:

1、建立测试表

CREATE TABLE student

 (

  id                         NUMBER,

  name                       VARCHAR2(30)

)

/

 

2、建立带ref cursor定义的包和包体及函数:

CREATE OR REPLACE package pkg_test as

/* 定义ref cursor类型

   不加return类型,为弱类型,允许动态sql查询,

   否则为强类型,无法使用动态sql查询;

*/

  type myrctype is ref cursor;

 

--函数申明

  function get return myrctype;

end pkg_test;

/

 

CREATE OR REPLACE package body pkg_test as

--函数体

   function get return myrctype is

     rc myrctype;  --定义ref cursor变量

     sqlstr varchar2(500);

   begin

        --静态测试,直接用select语句直接返回结果

        open rc for select id,name from student;

        --动态sql赋值,用:w_id来申明该变量从外部获得

        --sqlstr := 'select id,name,sex,address,postcode,birthday from student --where id=:w_id';

        --动态测试,用sqlstr字符串返回结果,用using关键词传递参数

        --open rc for sqlstr using intid;

        return rc;

   end get;

 

end pkg_test;

/

3、用pl/sql块进行测试:

declare

   w_rc       pkg_test.myrctype; --定义ref cursor型变量

   --定义临时变量,用于显示结果

   w_id       student.id%type;

   w_name     student.name%type;

 begin

   --调用函数,获得记录集

   w_rc := pkg_test.get;

   --fetch结果并显示

   fetch w_rc into w_id,w_name;

   while w_rc%Found loop

      dbms_output.put_line(w_name);

      fetch w_rc into w_id,w_name;

   end loop;

 end;

/

4、测试结果:

通过。

 

 


20 12, 2004
触发器的属性列表
作者 xzh2000 13:13 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96590/adg14evt.htm


20 12, 2004
pl/sql中table与array的区别
作者 xzh2000 12:03 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

pl/sql中table与array的区别
declare
 type v_test is table of varchar2(30) index by binary_integer;
 t_test v_test;
 v_curr binary_integer;
begin
 t_test(1) := 'abc';
 t_test(3) := 'bcd';
 t_test(5) := 'cde';
 t_test(7) := 'def';
 dbms_output.put_line(t_test.count);
 dbms_output.put_line(t_test.first);
 dbms_output.put_line(t_test.last);
end;

表的机制实现不同于数组,pl/sql的table实现类似于数据库中的表,
它有两列:key与value. key的类型是binary_integer,而value
的类型是is table of data_type中的data_type指定的数据类型.
key  value
1   abc
3   bcd

表的一些特性
a 表是不受约束的,最大值是binary_integer的取值范围
b pl/sql表的元素没有必要按照特定的次序排序,元素可以按照任意键进行插入
c pl/sql表使用键(key)没有必要是顺序的,所有binary_integer数据或表达式都可以作用表的索引

pl/sql表的属性
count  返回表的总元素个数
delete 删除某个元素
exists 判断某个元素是否存在
first  返回表中第一个元素的索引
last  返回表中第后一个元素的索引
next  返回当前元素下一个元素的索引
prior  返回当前元素上一个元素的索引

可变数组(varing array或varray)用来创建具有一个或多个列且不限制行数的变量
type varraytype is varray|varing array (size) of datatype|table.column%type|table%rowtype

在声明数组时,必须声明变量数组中元素中的个数,它保持为常量
变量数组必须密集,程序必须使用连接的下标向变量中插入成员,不能删除元素


14 12, 2004
触发器中不能用rollback吗?
作者 xzh2000 11:10 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

create table test(id number(9),name varchar2(20),age number(6));

 create or replace trigger tri_test_insert
 before insert on test
 for each row
 begin
 if :new.age > 999 then
 rollback;
 end if;
 end;
 /

10:41:39 SQL> insert into test values(1,'abc',1000);
insert into test values(1,'abc',1000)
            *
ERROR at line 1:
ORA-04092: cannot ROLLBACK in a trigger
ORA-06512: at "TEST.TRI_TEST_INSERT", line 3
ORA-04088: error during execution of trigger 'TEST.TRI_TEST_INSERT'

 create or replace trigger tri_test_insert
 before insert on test
 for each row
 begin
 if :new.age > 999 then
 raise_application_error(-20100,'please insert a positive value');
 end if;
 end;
 /

10:42:33 SQL> insert into test values(1,'abc',1000);
insert into test values(1,'abc',1000)
            *
ERROR at line 1:
ORA-20100: please insert a positive value
ORA-06512: at "TEST.TRI_TEST_INSERT", line 3
ORA-04088: error during execution of trigger 'TEST.TRI_TEST_INSERT'


Elapsed: 00:00:00.02
10:42:39 SQL> host oerr ora 20100

10:43:03 SQL> select * from test;

从这里可以发现,oracle的触发器与mssqlserver的触发器差别是很大的,

mssqlserver允许在触发器内部使用rollback的.还有说是mssqlserver的

instead of触发器可以在表上,也可以在视图上,而oracle的instead of

触发器只能作用于视图上。

--触发器中的自治事务及动态DDL
-- create a main table and its shadow table
create table parts (pnum number(4), pname varchar2(15));
create table parts_log (pnum number(4), pname varchar2(15));
-- create an autonomous trigger that inserts into the
-- shadow table before each insert into the main table
create trigger parts_trig
before insert on parts for each row
declare
   pragma autonomous_transaction;
begin
   insert into parts_log values(:new.pnum, :new.pname);
   commit;
end;
-- insert a row into the main table, and then commit the insert
insert into parts values (1040, 'head gasket');
commit;
-- insert another row, but then roll back the insert
insert into parts values (2075, 'oil pan');
rollback;
-- show that only committed inserts add rows to the main table
select * from parts order by pnum;
   pnum pname
------- ---------------
   1040 head gasket
-- show that both committed and rolled-back inserts add rows
-- to the shadow table
select * from parts_log order by pnum;
   pnum pname
------- ---------------
   1040 head gasket
   2075 oil pan
--在触发器中执行DDL.
create trigger bonus_trig
after update on bonus
declare
   pragma autonomous_transaction;  -- enables trigger to perform ddl
begin
   execute immediate 'drop table temp_bonus';
end;


14 12, 2004
fulljoin在9201/9204的差异
作者 xzh2000 10:17 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
http://www.itpub.net/300771.html
13 12, 2004
含bind var的sql优化过程
作者 xzh2000 16:59 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

一个含bind var的sql优化过程

AAAF2F68  685266707        .00            .18     61327.00          1 2004-12-13/14:48:35
select a.user_name,b.*
 from reseller_base a,reseller_user b
where a.reseller_id=b.reseller_id and a.user_name=:"SYS_B_0" order by reseller_user_id

表a,b数据量都在10,0000左右,而且a.user_name是唯一索引,这个地方a,b是一对多的关系,
如果a.user_name=:"SYS_B_0"有数据返回的话,记录集也会很小,但它们的逻辑读竟然达到
61327,虽然该SQL存在问题。
explain plan for select a.user_name,b.*
 from reseller_base a,reseller_user b
 where a.reseller_id=b.reseller_id and a.user_name=:"SYS_B_0" order by reseller_user_id;

16:16:30 SQL> select * from table(dbms_xplan.display);

PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------
| Id  | Operation                    |  Name             | Rows  | Bytes | Cost (%CPU)|
---------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                   |     1 |    96 |  4681   (0)|
|   1 |  NESTED LOOPS                |                   |     1 |    96 |  4681   (0)|
|   2 |   TABLE ACCESS BY INDEX ROWID| RESELLER_BASE     |     1 |    13 |     2  (50)|
|*  3 |    INDEX UNIQUE SCAN         | IDX_RB_USER_NAME  | 81696 |       |     1   (0)|
|*  4 |   TABLE ACCESS BY INDEX ROWID| RESELLER_USER     |     1 |    70 |  4680   (0)|
|   5 |    INDEX FULL SCAN           | IDX_RU_RUID       | 90979 |       |     2   (0)|
---------------------------------------------------------------------------------------

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

   3 - access("A"."USER_NAME"=:Z)
   4 - filter("A"."RESELLER_ID"="B"."RESELLER_ID")

发现在b表上存在index full scan,也就是说优化器选择了用reseller_user_id字段上的索引,
而没有选择reseller_id上的索引.

@list_index
Enter value for 1: reseller_user
old   3: where a.index_name=b.index_name and a.table_name=upper('&1')
new   3: where a.index_name=b.index_name and a.table_name=upper('reseller_user')

OWNER      INDEX_NAME               COLUMN_NAME                      STATUS     INDEX_TYPE             CP
---------- ------------------------ -------------------------------- ---------- --------------------- ---
CYBERCAFE  IDX_RU_LAST_LOGIN        LAST_LOGIN_IPADDR                VALID      NORMAL                  1
CYBERCAFE  IDX_RU_LAST_LOGIN        LAST_LOGIN_TIME                  VALID      NORMAL                  2
CYBERCAFE  IDX_RU_MCID              MCID                             VALID      NORMAL                  1
CYBERCAFE  IDX_RU_RESELLER_ID       RESELLER_ID                      VALID      NORMAL                  1
CYBERCAFE  IDX_RU_RUID              RESELLER_USER_ID                 VALID      NORMAL                  1
CYBERCAFE  IDX_RU_USERNAME          USERNAME                         VALID      NORMAL                  1

explain plan for select /*+ index(b idx_ru_reseller_id) */ a.user_name,b.*
 from reseller_base a,reseller_user b
where a.reseller_id=b.reseller_id and a.user_name=:"SYS_B_0" order by reseller_user_id;

@plan

PLAN_TABLE_OUTPUT
-------------------------------------------------------------------------------------------------------------------------

------------------------------------------------------------------------------------------
| Id  | Operation                     |  Name               | Rows  | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT              |                     |     1 |    83 |     6  (17)|
|   1 |  SORT ORDER BY                |                     |     1 |    83 |     6  (17)|
|   2 |   NESTED LOOPS                |                     |     1 |    83 |     3  (34)|
|   3 |    TABLE ACCESS BY INDEX ROWID| RESELLER_BASE       |     1 |    13 |     2  (50)|
|*  4 |     INDEX UNIQUE SCAN         | IDX_RB_USER_NAME    | 81696 |       |     1   (0)|
|   5 |    TABLE ACCESS BY INDEX ROWID| RESELLER_USER       |     1 |    70 |     2  (50)|
|*  6 |     INDEX RANGE SCAN          | IDX_RU_RESELLER_ID  |     1 |       |            |
------------------------------------------------------------------------------------------

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

   4 - access("A"."USER_NAME"=:Z)
   6 - access("A"."RESELLER_ID"="B"."RESELLER_ID")

添加提示后 index full scan消失了,替代的是index range scan,逻辑读降到30左右。


11 12, 2004
求出shared_pool共aged out的对象
作者 xzh2000 17:58 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
--求出shared_pool共aged out的对象
SELECT * FROM sys.x$ksmlru WHERE ksmlrnum>0;

11 12, 2004
自动编译invalid状态对象
作者 xzh2000 17:55 | Permalink 静态链接网址 | Comments 最新回复 (2) | Trackback 引用 (0) | 技术交流

--自动重编译对象
create or replace procedure timer_auto_recompile_objs
as
cursor objects_list is
 select object_name,object_type from user_objects where status='INVALID';
begin
 for v_object in objects_list loop
  if v_object.object_type='PROCEDURE' then
   execute immediate 'alter procedure '||v_object.object_name||' compile';
  elsif v_object.object_type='VIEW' then
   execute immediate 'alter view '||v_object.object_name||' compile';
  elsif v_object.object_type='MATERIALIZED VIEW' then
    execute immediate 'alter materialized view '||v_object.object_name||' compile';
  end if;
 end loop;
end;

exec dbms_job.submit(:job_id,'timer_auto_recompile_objs;',sysdate,'sysdate+1/24');


11 12, 2004
linux下如何将磁盘信息定时发到邮箱?
作者 xzh2000 17:53 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

--将disk使用信息保存到数据库中
create table disk_status(snap_id date,USED_STATUS varchar2(4000));
alter table disk_status add constraint pk_ds_snapid primary key(snap_id);

[oracle@data1 backup]$ more auto_collect_disk.sh
#!/bin/bash
rm /home/oracle/sql/backup/disk_status.lst
df>/home/oracle/sql/backup/disk_status.lst

DISK_STATUS=`cat /home/oracle/sql/backup/disk_status.lst`
echo $DISK_STATUS
sqlplus -s xxxx/yyyy<<!;
insert into disk_status values(trunc(sysdate),'$DISK_STATUS');
commit;
exit
!

[oracle@data1 oracle]$ crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.21703 installed on Mon Nov 22 09:46:47 2004)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
00 05 * * * /home/oracle/sql/backup/auto_collect_disk.sh >> /home/oracle/sql/backup/tmp.lst 2>&1

[oracle@www1 sql]$ more backup/auto_send_disk.sh
#!/bin/sh
. ~oracle/.bash_profile

/home/oracle/product/9.2.0/bin/sqlplus -s xxxx/yyyy@zzzz<<!
set timing off
spool /home/oracle/sql/backup/disk_status.lst
set linesize 81
col used_status format a69
select to_char(snap_id,'yyyy-mm-dd') snap_id,used_status from disk_status where snap_id = trunc(sysdate);

set linesize 101
set pagesize 999
col "表空间名" format a12
col mbytes format 9999.99
col "已使用空间(M)" format 99999.99
col 使用比 format a8
col "空闲空间(M)" format 9999.99
col "最大块(M)" format 9999.99
SELECT F.TABLESPACE_NAME "表空间名",
       D.TOT_GROOTTE_MB "表空间大小(M)",
       D.TOT_GROOTTE_MB - F.TOTAL_BYTES "已使用空间(M)",
       TO_CHAR(ROUND((D.TOT_GROOTTE_MB - F.TOTAL_BYTES)/D.TOT_GROOTTE_MB*100,2),'990.99') 使用比,
       F.TOTAL_BYTES "空闲空间(M)",F.MAX_BYTES "最大块(M)"
FROM (SELECT TABLESPACE_NAME,ROUND(SUM(BYTES)/(1024*1024),2) TOTAL_BYTES,ROUND(MAX(BYTES)/(1024*1024),2) MAX_BYTES
          FROM SYS.DBA_FREE_SPACE GROUP BY TABLESPACE_NAME) F,
       (SELECT DD.TABLESPACE_NAME,ROUND(SUM(DD.BYTES)/(1024 * 1024), 2) TOT_GROOTTE_MB
          FROM SYS.DBA_DATA_FILES DD GROUP BY DD.TABLESPACE_NAME) D
WHERE D.TABLESPACE_NAME = F.TABLESPACE_NAME ORDER BY 4 DESC;

spool off
exit
!

mail -s "磁盘信息发布" ####@###.## < /home/oracle/sql/backup/disk_status.lst
rm /home/oracle/sql/backup/disk_status.lst

[oracle@www1 sql]$crontab -l
# DO NOT EDIT THIS FILE - edit the master and reinstall.
# (/tmp/crontab.32619 installed on Mon Nov 22 09:51:02 2004)
# (Cron version -- $Id: crontab.c,v 2.13 1994/01/17 03:20:37 vixie Exp $)
30 05 * * * /home/oracle/sql/backup/auto_send_disk.sh >> /home/oracle/sql/backup/disk.lst 2>&1


11 12, 2004
在linux上如何定时生成statspack的报表?
作者 xzh2000 17:44 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

--如何自动生成statspack的报表将发邮件到指定人的邮箱
[oracle@www1 sql]$ more backup/auto_send_perf.sh
#!/bin/sh
. ~oracle/.bash_profile

/home/oracle/product/9.2.0/bin/sqlplus -s perfstat/xxxx@yyyy<<!
set head off
set timing off
spool /home/oracle/sql/backup/snap_begin.lst
select min(snap_id) snap_id
from stats$snapshot
where snap_time between trunc(sysdate) and trunc(sysdate)+1;
spool off
spool /home/oracle/sql/backup/snap_end.lst
select max(snap_id) snap_id
from stats$snapshot
where snap_time between trunc(sysdate) and trunc(sysdate)+1;
spool off
exit
!

BEGIN_SNAP=`cat /home/oracle/sql/backup/snap_begin.lst | tail -n 2`
END_SNAP=`cat /home/oracle/sql/backup/snap_end.lst | tail -n 2`
#END_SNAP=`expr $BEGIN_SNAP + 13`
REPORT_NAME=/home/oracle/sql/report/sp`date +%m%d`_ac

/home/oracle/product/9.2.0/bin/sqlplus -s perfstat/xxxx@yyyy<<!
define begin_snap=$BEGIN_SNAP
define end_snap=$END_SNAP
define report_name=$REPORT_NAME
@?/rdbms/admin/spreport
exit
!

mail -s "perfstat report" ####@###.## < /home/oracle/sql/report/sp`date +%m%d`_ac.lst

然后用crontab -e调度生成报表的时间

$crontab -e

30 21 * * * /home/oracle/sql/backup/auto_send_perf.sh >> /home/oracle/sql/backup/perf.lst 2>&1


11 12, 2004
pl/sql学习大纲
作者 xzh2000 17:34 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流
第一章 pl/sql简介
1.1 为什么使用pl/sql
1.1.1 客户-服务器模式
1.1.2 标准
1.2 pl/sql的功能特性
1.2.1 块结构
1.2.2 变量与类型
1.2.3 循环结构
1.3 本书使用的约定
1.3.1 pl/sql与oracle
1.3.2 oracle文档
1.3.3 在线代码
1.4 示例样表
1.5 小结
第二章 pl/sql基础
2.1 pl/sql块
2.2 词法单位
2.2.1 标识符
2.2.2 分界符
2.2.3 文字
2.2.4 注释
2.3 变量声明
2.3.1 声明语法
2.3.2 变量初始化
2.4 pl/sql类型
2.4.1 标量类型
2.4.2 复合类型
2.4.3 引用类型
2.4.4 LOB类型
2.4.5 使用%TYPE
2.4.6 用户定义子类型
2.4.7 数据类型转换
2.4.8 变量作用域及可见性
2.5 表达式和运算符
2.5.1 赋值
2.5.2 表达式
2.6 pl/sql控制结构
2.6.1 if-then-else-end if
2.6.2 循环
2.6.3 GOTO与标号<<>>
2.6.4 pragma
2.7 pl/sql风格指南
2.7.1 注释风格
2.7.2 变量名风格
2.7.3 缩进风格
2.7.4 大写风格
2.7.5 常见风格
2.8 小结
第三章 记录与表
3.1 pl/sql记录
3.1.1 记录赋值
3.1.2 使用%ROWTYPE
3.2 pl/sql表
3.2.1 表与数组
3.2.2 表属性
3.2.3 使用pl/sql表的指南
3.3 小结
第四章 在pl/sql中使用sql
4.1 sql语句
4.2 在pl/sql中使用dml语句
4.2.1 select
4.2.2 insert
4.2.3 update
4.2.4 delete
4.2.5 where
4.2.6 表引用
4.2.7 数据库链接
4.2.8 同义词
4.3 伪例
4.3.1 currval与nextval
4.3.2 level
4.3.3 rowid
4.3.4 rownum
4.4 grant/revoke语句
4.4.1 对象与权限
4.4.2 grant/revoke
4.4.3 角色
4.5 事务控制
4.5.1 commit和rollback
4.5.2 保存点
4.5.3 事务和块
4.6 小结
第五章 内置sql函数
5.1 前言
5.2 这符函数
5.2.1 chr
5.2.2 concat
5.2.3 initcap
5.2.4 lower
5.2.5 lpad
5.2.6 ltrim
5.2.7 nls_initcap
5.2.8 nls_lower
5.2.9 nls_upper
5.2.10 replace
5.2.11 rpad
5.2.12 rtrim
5.2.13 soundex
5.2.14 substr
5.2.15 substrb
5.2.16 translate
5.2.17 upper
5.3 字符函数 返回数字
5.3.1 ascii
5.3.2 instr
5.3.3 instrb
5.3.4 length
5.3.5 lengthb
5.3.6 nlssort
5.4 数字函数
5.4.1 abs
5.4.2 acos
5.4.3 asin
5.4.4 atan
5.4.5 atan2
5.4.6 ceil
5.4.7 cos
5.4.8 cosh
5.4.9 exp
5.4.10 floor
5.4.11 ln
5.4.12 log
5.4.13 mod
5.4.14 power
5.4.15 round
5.4.16 sign
5.4.17 round
5.4.18 sinh
5.4.19 sqrt
5.4.20 tan
5.4.21 tanh
5.4.22 trunc
5.5 日期函数
5.5.1 add_months
5.5.2 last_day
5.5.3 months_between
5.5.4 new_time
5.5.5 next_day
5.5.6 round
5.5.7 sysdate
5.5.8 trunc
5.5.9 日期算术
5.6 转换函数
5.6.1 chartorowid
5.6.2 convert
5.6.3 hextoraw
5.6.4 rawtohex
5.6.5 rowidtochar
5.6.6 to_char(date)
5.6.7 to_char(number)
5.6.8 to_date
5.6.9 to_number
5.7 分组函数
5.7.1 avg
5.7.2 count
5.7.3 max
5.7.4 min
5.7.5 sum
5.7.6 group by
5.7.7 having
5.8 其它函数
5.8.1 decode
5.8.2 case
5.8.3 dump
5.8.4 empty_clob/empty_blob
5.8.5 greatest/least
5.8.6 nvl
5.8.7 uid
5.8.8 user
5.8.9 userenv
5.8.10 sys_context
5.8.11 sys_guid
5.8.12 vsize
5.9 小结
第六章 游标
6.1 什么是游标
6.1.1 处理显式游标
6.1.2 处理隐式游标
6.2 游标提取循环
6.2.1 简单循环
6.2.2 while循环
6.2.3 for循环
6.2.4 游标的属性(%found/%notfound等)
6.2.5 异常处理(NO_DATE_FOUND/TOO_MANY_ROWS)
6.2.6 select for update游标
6.3 游标变量
6.3.1 声明游标变量
6.3.2 为游标分配置空间
6.3.3 打开查询的游标变量
6.3.4 关闭游标变量
6.3.5 游标变量示例(1,2)
6.3.6 使用游标变量的限制
6.4 小结
第七章 子程序(过程与函数)
7.1 创建过程与函数
7.1.1 创建过程
7.1.2 创建函数
7.1.3 异常处理
7.1.4 删除过程及函数
7.2 子程序位置
7.2.1 内置子程序
7.2.2 本地子程序
7.3 子程序依赖性
7.4 权限和内置子程序
7.4.1 execute权限
7.4.2 内置子程序和角色
7.5 小结
第八章 包
8.1 包介绍
8.1.1 包说明
8.1.2 包主体
8.1.3 包和作用域
8.1.4 重载子程序
8.1.5 包初始化
8.1.6 包和相关性
8.2 在sql中使用内置函数
8.2.1 纯度级别
8.2.2 restric_references
8.2.3 缺省参数
8.3 使用pl/sql数据模式输出程序
8.4 小结
第九章 触发器
9.1 创建触发器
9.1.1 触发器组件
9.1.2 触发器和数据字典
9.1.3 触发器点火次序
9.1.4 行触发器(:new与:old)
9.1.5 触发器动作(inserting/updating/deleting)
9.2 变化表
9.2.1 变化表示例
9.2.2 消除变化表错误
9.3 使用pl/sql实现级联更新
9.3.1 实用程序的内容
9.3.2 工作原理
9.4 小结
第十章 错误处理
10.1 异常处理
10.1.1 声明异常处理
10.1.2 触发异常处理
10.1.3 处理异常情况
10.1.4 exception_init pragma
10.1.5 raise_application_error
10.2 异常状态传播
10.2.1 执行部分引发异常
10.2.2 在声明部分引异常
10.2.3 在异常部分处理异常
10.3 异常处理指南
10.3.1 异常状态的作用域
10.3.2 避免未处理的异常情况
10.3.3 屏蔽错误发生的位置
10.4 使用pl/sql常用错误处理模块
10.5 小结
第十一章 对象
11.1 背景介绍
11.1.1 面向对象的程序设计
11.1.2 对象关系型数据库
11.2 对象类型
11.2.1 定义对象类型
11.2.2 声明和初始化对象
11.2.3 方法
11.2.4 更改和删除类型
11.2.5 对象依赖性
11.3 数据库中的对象
11.3.1 对象位置
11.3.2 在dml中使用对象
11.3.3 map和order方法
11.4 小结
第十二章 集合(collections)
12.1 嵌套表
12.1.1 声时嵌套表
12.1.2 数据库中的嵌套表
12.1.3 嵌套表和索引表
12.2 varrays
12.2.1 声明varray
12.2.2 数据库中的array
12.2.3 varray和嵌套表
12.3 集合方法
12.3.1 exists
12.3.2 count
12.3.3 limit
12.3.4 first/last
12.3.5 next/prior
12.3.6 extend
12.3.7 trim
12.3.8 delete
12.4 小结
第十三章 pl/sql执行环境
13.1 不同的pl/sql引擎
13.2 服务器端pl/sql
13.2.1 sql*plus
13.2.2 oracle预编绎器
13.2.3 oci
13.2.4 isqlplus
13.3 客户端pl/sql
13.3.1 客户端pl/sql引擎
13.3.2 oracle forms
13.3.3 procedure builder
13.4 pl/sql wrapper
13.4.1 运行wrapper
13.4.2 输入与输出文件
13.4.3 检查语法和语义
13.4.4 wrapper使用指南
13.5 小结
第十四章 测试和调试
14.1 问题诊断
14.1.1 调试指南
14.1.2 debug package
14.2 插入测试表
14.3 dbms_output
14.4 pl/sql调试器
14.5 prcocedure builder/toad/lecco sql expert
14.6 程序设计方法
14.6.1 模块化
14.6.2 自顶向下
14.6.3 数据抽象
14.7 小结
第十五章 动态pl/sql
15.1 前言
15.1.1 静态与动态sql
15.1.2 dbms_sql概述
15.2 执行非查询dml与ddl
15.2.1 打开游标
15.2.2 分析语句
15.2.3 联编输入参数
15.2.4 执行语句
15.2.5 关闭游标
15.2.6 执行ddl语句
15.2.7 执行查询
15.2.8 定义输出变量
15.2.9 提取行
15.2.10 将结果返回给pl/sql变量
07 12, 2004
如何减少共享池碎片
作者 xzh2000 18:16 | Permalink 静态链接网址 | Comments 最新回复 (5) | Trackback 引用 (0) | 技术交流

http://www.itpub.net/298019.html

如何减少共享池的碎片

       SGA中,由shared_pool_size参数控制共享池的大小,共享池主要是sql arealibrary cache等部分组成,每部分所耗用的内存可以通过v$sgastat字典表查看,如果想了解共享池碎片是如何产生的,可以参考eygle的贴子(http://www.eygle.com/internal/shared_pool-1.htm)。

       理解了共享池的碎片是如何产生的,那么就可以想办法消除它。通常共享池碎片产生的原因很多,而且有些oracle版本的bug也可能引起共享池的碎片,如果是由bug引起的,解决办法请参照eygle的这个贴子(http://www.eygle.com/internal/shared_pool-6.htm),其它方面的原因大概有以下方面:

       1 不良的数据库设计,导致数据库对象众多

       2 bind varSQL,导致共享池过度交换

       3 cursor_sharing参数及histogram引起的

       4 项目组没有统一的sql编写规范引起的

       关于第1个原因,处理起来难度较大,风险也高,因为涉及到修改数据库结构,需要修改的地方就比较多,这样做首先要取得公司的支持,然后对数据库进行良构设计,消除结构上不太合理的地方。例如偶公司的业务系统是从mysql迁移到oracle中的,有一些很重要的产品表以前是这样设计的game_card_gmxxxx,由于最初产品不是很多,所以矛盾并不突出,但随着业务的扩展,产品表从几十个增加到几百个,问题就随着来啦,每个表有6个索引,仅产品表相关的对象就上千个(含每个产品表的sequence),庞大的对象体系必然增加了共享池(sql arealibrary cache等)的消耗,如果数据库结构重新设计的话,一个表/六个索引/一个序列就可以满足啦,可以极大地减少shared_pool的争用。

bind varSQL导致共享池中的SQLaged out,被aged outSQL大致可分为两种:可重用的或不可重用的。如DDLDCLDMLINSERT/DELETE/UPDATE)这些99%是不可以重用的,aged out后几乎不会被再次reload;但SELECT语句是可以重用的,如果大量的SELECT被换进换出就会影响数据库的性能。

图一 Library Cache Activity

       如图一所示,显示SQL AREAReloads20万次左右,每个SQL在共享池中就按分配20k来计算,SGA以外的内存中将需要提供320m左右的空间给这些被aged out出来的SELECT语句;至于不可重用的SQL可以按业务数据的增长计算出它们使用SGA以外内存的数量。如果你的statspack报表中关于Library Cache Activity的统计项中SQL AREA中存在Reloads值较多,那就需要考虑使用bind var,因为这部分只是SELECT语句的部分,关于DML这部分SQLaged out后使用SGA之外部分内存就没有量化的标准,如果你的业务数据量增加较大的话,那被aged out INSERT肯定很多,所以需要对数据量增加较多的表或数据查询很频繁的SQL使用bind var。在常用的SQL中使用bind var,其本质就是通过减少共享池的使用来减少共享池的碎片。

       cursor_sharing参数及histogram引起的执行计划恶化问题,大家需要先了解一下cursor_sharing参数的意义。它共有三个可选值:exactforcesimilarexact是表示cursor共享文本量必须相同,是默认值;forcesimilar是控制cursor共享的参数,由于force在控制cursor共享时对histogram(柱状图)不敏感,oracle才提供similar参数增加cursor共享时对histogram的敏感性;以下是在9.2.0.4上的测试结果:

图一 cursor_sharing等于exact

       如图一所示,创建test4表用于测试,添加10000条记录,然后查看cursor_sharing参数的取值,在exact下共享cursor必须确保SQL文本是全部相同的,虽然查询id = 1id = 2只有细微的差别,却在共享池中保存了两个语法分析树。如图二所示,当cursor_sharing等于force时,虽然文本量不同,该SQL却共享了id = 3SQL的执行计划,当然,其它类似的SQL也将可以共享id = 3的执行计划。

图二 cursor_sharing等于force

图三 cursor_sharing等于similar

图四 cursor_sharing等于similar时(已分析histogram

       如图三所示,cursor_sharing等于similar时,也体现了cursor_sharing=force时的效果,可以共享SQL的执行计划;如图四所示,如果表已分析,并产生了histogram的情况下,SQL为了使用histogram的信息,将不再共享已经解析出来的执行计划,所以在similar下,很有可能会产生执行计划臌胀的情况。如何解决由图四情况下执行计划膨胀的的问题呢?一是cursor_sharing=forse,这将不能使用histogram带来的好处,二是cursor_sharing=similar,不分析表。可以看出:如果想减少共享池的碎片,最好不要对表进行histogram运算;如果已经分析并有histogram信息的表,可以用analyze table &table_name delete statistics去删除它的分析信息。其实在表的主键字段或唯一索引字段,通常是不需要求histogram信息的,当然如果执行计划确定的话,也不需要为表生成histogram信息;但在某些复杂的情况下,执行计划不能确定或很多查询条件是动态的,最好是为表生成histogram信息,让优化器去选择适当的执行计划,就只有在两者之间(最佳性能/共享池碎片)进行取舍啦。

       由于项目组没有统一的SQL编写规范,程序员在SQL编写方面有着很大的随意性,结果导致很多可以共享执行计划的SQL由于程序员的失误而被重新解析,所以成熟的项目组都有完善的开发规范,用于减少人为的失误。

       在这方面,本人的意见是:编写SQL时,组成SQL的所有字符单元都用小写字符,每个SQL的关键字与非关键字之间只保留一个空格,selectfield listwhere子句中出现的查询字段必须按它们在表中出现的字段顺序为准,selectfield list中各字段以逗号(“,”)隔开,不必保留空格。示例如下:

图五 SQL编写范例

       虽然这些约定很简单,只要所有的程序员都按这样的规范去写,必定可以减少共享池的碎片,如图五中所示;对oracle较为熟练的程序员在很大程度上可以减少共享池碎片的产生,有丰富数据库设计经验的数据库设计师也可以避免数据库对象膨胀的问题。

除了以上的情况,尽量在应用软件设计时对SQL使用bind variable,因为cursor_sharing=forcesimilar时,有可能产生一些不可预知的BUG。常用的开发工具都支持SQLbind variable(变量绑定),如PBDELPHIJAVA等,无论是程序员还是DBA,都需要注意SQL使用变量绑定对系统的影响。

如何检验sql 使用bind var改进后的效果呢?一种方法就是看图一所示的的sql reload的情况,如果将大量的SQL改为使用bind var的语法,那soft parse的值必将有所下降;二是看图六的soft parse情况,如果将大量的SQL改为使用bind var的语法,那soft parse的值必将有所提升。(附注:如果您对statspack不熟,您可以参考eygle所作的statspack系列专题教程 http://www.eygle.com/pdf/Statspack-v3.0.pdf

图六 实例关键能指标


07 12, 2004
动态创建mview时权限问题
作者 xzh2000 18:01 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

在sqlplus上直接执行创建mview的SQL是可以执行的,当前用户有dba权限

create materialized view mv_sellstatbyprovince_200411
build immediate refresh complete on demand
as
select a.province_id as pro_id,a.name as p_name,e.name as c_name,f.name as g_name,e.game_card_type_id,f.game_id,
sum(c.transaction_amount) as s_money,sum(c.game_card_num) as s_num,sum(game_card_cost) as cost
from province a,city b,game f,game_card_type e,reseller_base d,v_sale_tmp_log c
where a.province_id = b.province_id and d.city_id = b.city_id and c.reseller_id = d.reseller_id
and c.game_card_type_id = e.game_card_type_id and e.game_id = f.game_id
and c.log_time between to_date('2004-11-01','yyyy-mm-dd') and to_date('2004-12-01','yyyy-mm-dd')
and c.is_success = 'Y' group by a.province_id,a.name,f.game_id,f.name,e.game_card_type_id,e.name;
将这个SQL封装在存储过程中执行时报错:

create or replace procedure timer_sellstatbyprovince_cmv
as
v_begin varchar2(30);
v_end varchar2(30);
v_sql varchar2(2000);
v_mvname varchar2(30);
v_success varchar2(3);
v_format varchar2(36);
begin
 v_format := 'yyyy-mm-dd hh24:mi:ss';
 v_mvname := to_char(add_months(sysdate,-1),'yyyymm');
 v_success := ''''||'Y'||'''';
 v_begin := v_mvname||'01';
 v_mvname := upper('mv_sellstatbyprovince_'||v_mvname);
 v_end := to_char(last_day(to_date(v_begin,v_format))+86399/86400,v_format);
 v_sql := 'create materialized view '||v_mvname||' ';
 v_sql := v_sql||'build immediate refresh complete on demand as ';
 v_sql := v_sql||'select a.province_id as pro_id,a.name as p_name,e.name as c_name,f.name as g_name,e.game_card_type_id,f.game_id,';
 v_sql := v_sql||'sum(c.transaction_amount) as s_money,sum(c.game_card_num) as s_num,sum(game_card_cost) as cost ';
 v_sql := v_sql||'from province a,city b,game f,game_card_type e,reseller_base d,v_sale_tmp_log c ';
 v_sql := v_sql||'where a.province_id = b.province_id and d.city_id = b.city_id and c.reseller_id = d.reseller_id ';
 v_sql := v_sql||'and c.game_card_type_id = e.game_card_type_id and e.game_id = f.game_id ';
 v_sql := v_sql||'and c.log_time between to_date('||''''||v_begin||''''||','''||v_format||''') ';
 v_sql := v_sql||'and to_date('||''''||v_end||''''||','''||v_format||''') and c.is_success = '||v_success||' ';
  v_sql := v_sql||'group by a.province_id,a.name,f.game_id,f.name,e.game_card_type_id,e.name';
 execute immediate v_sql;
end;
/

Elapsed: 00:00:00.04
16:51:16 SQL> exec TIMER_SELLSTATBYPROVINCE_CMV;
BEGIN TIMER_SELLSTATBYPROVINCE_CMV; END;

*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "CYBERCAFE.TIMER_SELLSTATBYPROVINCE_CMV", line 26
ORA-06512: at line 1


Elapsed: 00:00:00.05
16:51:22 SQL> connect sys/xxxxxx@yyyyyy as sysdba
Connected.
16:51:39 SQL> grant create materialized view to cybercafe;

Grant succeeded.

Elapsed: 00:00:00.01
16:51:54 SQL> @connect                        
Connected.
16:52:06 SQL> exec TIMER_SELLSTATBYPROVINCE_CMV;
BEGIN TIMER_SELLSTATBYPROVINCE_CMV; END;

*
ERROR at line 1:
ORA-01031: insufficient privileges
ORA-06512: at "CYBERCAFE.TIMER_SELLSTATBYPROVINCE_CMV", line 26
ORA-06512: at line 1

然后在存储过程的定义上加上authid current_user后创建完毕即可以执行.

create or replace procedure timer_sellstatbyprovince_cmv
authid current_user as
v_begin varchar2(30);
v_end varchar2(30);
v_sql varchar2(2000);
v_mvname varchar2(30);
v_success varchar2(3);
v_format varchar2(36);
begin
 v_format := 'yyyy-mm-dd hh24:mi:ss';
 v_mvname := to_char(add_months(sysdate,-1),'yyyymm');
 v_success := ''''||'Y'||'''';
 v_begin := v_mvname||'01';
 v_mvname := upper('mv_sellstatbyprovince_'||v_mvname);
 v_end := to_char(last_day(to_date(v_begin,v_format))+86399/86400,v_format);
 v_sql := 'create materialized view '||v_mvname||' ';
 v_sql := v_sql||'build immediate refresh complete on demand as ';
 v_sql := v_sql||'select a.province_id as pro_id,a.name as p_name,e.name as c_name,f.name as g_name,e.game_card_type_id,f.game_id,';
 v_sql := v_sql||'sum(c.transaction_amount) as s_money,sum(c.game_card_num) as s_num,sum(game_card_cost) as cost ';
 v_sql := v_sql||'from province a,city b,game f,game_card_type e,reseller_base d,v_sale_tmp_log c ';
 v_sql := v_sql||'where a.province_id = b.province_id and d.city_id = b.city_id and c.reseller_id = d.reseller_id ';
 v_sql := v_sql||'and c.game_card_type_id = e.game_card_type_id and e.game_id = f.game_id ';
 v_sql := v_sql||'and c.log_time between to_date('||''''||v_begin||''''||','''||v_format||''') ';
 v_sql := v_sql||'and to_date('||''''||v_end||''''||','''||v_format||''') and c.is_success = '||v_success||' ';
  v_sql := v_sql||'group by a.province_id,a.name,f.game_id,f.name,e.game_card_type_id,e.name';
 execute immediate v_sql;
end;
/

Elapsed: 00:00:00.04
16:55:29 SQL> exec TIMER_SELLSTATBYPROVINCE_CMV;

PL/SQL procedure successfully completed.

然后偶就可以用job进行调度,每月初为上个月创建一个mview。


03 12, 2004
cursor_sharing在9204/10102/10103差异
作者 xzh2000 13:39 | Permalink 静态链接网址 | Comments 最新回复 (1) | Trackback 引用 (0) | 技术交流

 10.1.0.2/10.1.0.3
 create table test4(id number(8),name varchar2(20),age number(3));

 begin 
 for i in 1..10000 loop
 insert into test4 values(i,to_char(i,'00000'),mod(i,2));
 end loop;
 end;

SQL> show parameter cursor_sharing

NAME                                 TYPE                             VALUE
------------------------------------ -------------------------------- ------------------------------
cursor_sharing                       string                           SIMILAR
SQL> select * from test4 where id = 9;

        ID NAME                        AGE
---------- -------------------- ----------
         9  00009                        1

Elapsed: 00:00:00.02
SQL> select sql_text from v$sql where sql_text like 'select * from test4%';

SQL_TEXT
-------------------------------------------------------------------------------------------------------------------------
select * from test4 where id = :"SYS_B_0"

Elapsed: 00:00:00.03
SQL> select * from test4 where id = 10;

        ID NAME                        AGE
---------- -------------------- ----------
        10  00010                        0

Elapsed: 00:00:00.01
SQL> select sql_text from v$sql where sql_text like 'select * from test4%';

SQL_TEXT
-------------------------------------------------------------------------------------------------------------------------
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"

表肯定没有没有做过分析

9.2.0.4上的分析
13:08:32 SQL>  create table test4(id number(8),name varchar2(20),age number(3));

Table created.

Elapsed: 00:00:00.12
13:09:06 SQL>  begin 
13:09:14   2   for i in 1..10000 loop
 insert into test4 values(i,to_char(i,'00000'),mod(i,2));
13:09:14   3   end loop;
13:09:14   4   end;
13:09:14   5  13:09:14   6 
13:09:15   7  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.73
13:09:17 SQL> show parameter cursor_sharing

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
cursor_sharing                       string      EXACT
13:09:24 SQL> select * from test4 where id = 1;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
         1  00001                                                          1

1 row selected.

13:11:16 SQL> select * from test4 where id = 2;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
         2  00002                                                          0

1 row selected.

13:11:26 SQL> select sql_text from v$sql where sql_text like 'select * from test4%';

SQL_TEXT
-------------------------------------------------------------------------------------------------------------------------
select * from test4 where id = 2
select * from test4 where id = 1

2 rows selected.

Elapsed: 00:00:00.24
13:11:50 SQL> alter session set cursor_sharing=force;

Session altered.

Elapsed: 00:00:00.00
13:12:01 SQL> select * from test4 where id = 3;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
         3  00003                                                          1

1 row selected.

Elapsed: 00:00:00.02
13:12:05 SQL> select * from test4 where id = 4;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
         4  00004                                                          0

1 row selected.

Elapsed: 00:00:00.01
13:12:08 SQL> select sql_text from v$sql where sql_text like 'select * from test4%';

SQL_TEXT
-------------------------------------------------------------------------------------------------------------------------
select * from test4 where id = 2
select * from test4 where id = 1
select * from test4 where id = :"SYS_B_0"

3 rows selected.

Elapsed: 00:00:00.36
13:12:11 SQL> alter session set cursor_sharing=similar;

Session altered.

Elapsed: 00:00:00.00
13:12:20 SQL> select * from test4 where id = 5;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
         5  00005                                                          1

1 row selected.

Elapsed: 00:00:00.01
13:12:24 SQL> select * from test4 where id = 6;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
         6  00006                                                          0

1 row selected.

Elapsed: 00:00:00.01
13:12:27 SQL> select sql_text from v$sql where sql_text like 'select * from test4%';

SQL_TEXT
-------------------------------------------------------------------------------------------------------------------------
select * from test4 where id = 2
select * from test4 where id = 1
select * from test4 where id = :"SYS_B_0"

3 rows selected.

Elapsed: 00:00:00.22
13:12:30 SQL> analyze table test4 compute statistics for all columns size 32;

Table analyzed.

Elapsed: 00:00:00.27
13:13:44 SQL> select * from test4 where id = 7;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
         7  00007                                                          1

1 row selected.

Elapsed: 00:00:00.02
13:13:54 SQL> select * from test4 where id = 8;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
         8  00008                                                          0

1 row selected.

Elapsed: 00:00:00.01
13:13:57 SQL> select sql_text from v$sql where sql_text like 'select * from test4%';

SQL_TEXT
-------------------------------------------------------------------------------------------------------------------------
select * from test4 where id = 2
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"

3 rows selected.

Elapsed: 00:00:00.43
13:14:00 SQL> select * from test4 where id = 9;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
         9  00009                                                          1

1 row selected.

Elapsed: 00:00:00.02
13:14:46 SQL> select * from test4 where id = 10;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
        10  00010                                                          0

1 row selected.

Elapsed: 00:00:00.01
13:14:49 SQL> select sql_text from v$sql where sql_text like 'select * from test4%';

SQL_TEXT
-------------------------------------------------------------------------------------------------------------------------
select * from test4 where id = 2
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"

5 rows selected.

Elapsed: 00:00:00.25
13:14:52 SQL> alter session set cursor_sharing=force;

Session altered.

Elapsed: 00:00:00.00
13:15:04 SQL> select * from test4 where id = 11;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
        11  00011                                                          1

1 row selected.

Elapsed: 00:00:00.02
13:15:08 SQL> select * from test4 where id = 12;

        ID NAME                                                          AGE
---------- ------------------------------------------------------ ----------
        12  00012                                                          0

1 row selected.

Elapsed: 00:00:00.01
13:15:10 SQL> select sql_text from v$sql where sql_text like 'select * from test4%';

SQL_TEXT
-------------------------------------------------------------------------------------------------------------------------
select * from test4 where id = 2
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"
select * from test4 where id = :"SYS_B_0"

7 rows selected.

Elapsed: 00:00:00.28
13:15:12 SQL>


29 11, 2004
mview在10.1.0.2及10.1.0.3上的区别?
作者 xzh2000 16:29 | Permalink 静态链接网址 | Comments 最新回复 (0) | Trackback 引用 (0) | 技术交流

create table test(id int,log_time date,qty number(9,2),type char(2));

begin
for i in 1 .. 100 loop
for j in 1 .. 12 loop
for k in 1 .. 28 loop
if mod(i,2) = 0 then
insert into test values(i,to_date('2004-'||to_char(j)||'-'||to_char(k),'yyyy-mm-dd'),32,'RW');
else
insert into test values(i,to_date('2004-'||to_char(j)||'-'||to_char(k),'yyyy-mm-dd'),32,'RS');
end if;
end loop;
end loop;
end loop;
end;

create materialized view log on test with rowid (id,log_time,qty,type) including new values;
create materialized view mv_test refresh fast on commit enable query rewrite
as
select to_char(log_time,'yyyy-mm') as log_time,count(*) as qty_c,sum(qty) qty_s
from test
group by to_char(log_time,'yyyy-mm');

在10.1.0.2上
select count(*),sum(qty) from test
where log_time >= to_date('2004-09-01','yyyy-mm-dd') and log_time <= to_date('2004-09-30 23:59:59','yyyy-mm-dd hh24:mi:ss');

SQL> set autot on
SQL> select count(*),sum(qty) from test
2 where log_time >= to_date('2004-09-01','yyyy-mm-dd') and log_time <= to_date('2004-09-30 23:59:59','yyyy-mm-dd hh24:mi:ss');

COUNT(*) SUM(QTY)
---------- ----------
2800 89600

Elapsed: 00:00:00.07

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1 Bytes=31)
1 0 SORT (AGGREGATE)
2 1 MAT_VIEW REWRITE ACCESS (FULL) OF 'MV_TEST' (MAT_VIEW RE
WRITE) (Cost=2 Card=1 Bytes=31)

Statistics
----------------------------------------------------------
661 recursive calls
0 db block gets
210 consistent gets
0 physical reads
0 redo size
455 bytes sent via SQL*Net to client
508 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
14 sorts (memory)
0 sorts (disk)
1 rows processed

SQL> select count(*),sum(qty) from test where to_char(log_time,'yyyy-mm') = '2004-09';

COUNT(*) SUM(QTY)
---------- ----------
2800 89600

Elapsed: 00:00:00.04

Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=ALL_ROWS (Cost=2 Card=1 Bytes=31)
1 0 SORT (AGGREGATE)
2 1 MAT_VIEW REWRITE ACCESS (FULL) OF 'MV_TEST' (MAT_VIEW RE
WRITE) (Cost=2 Card=1 Bytes=31)

Statistics
----------------------------------------------------------
10 recursive calls
0 db block gets
67 consistent gets
0 physical reads
0 redo s