2007年9月20日,我从四川的一个小城市来到了成都,来到了这个熟悉又陌生的地方。说这个地方熟悉,是因为我在这里读了四年书,工作的时候偶尔也会出差到这里,每次出远门也要路过这里。说这个地方陌生,则是对于我来说,不太爱动。这里读了四年书,生活了几年,去的地方少得可怜。

想想一年之前,毅然告别了生活、工作了八年多的地方,那时心里面是非常复杂的。徬徨、紧张、憧憬……不过还好,没多久就适应了新的生活和新的工作环境,也很喜欢新的工作,我想这是令我非常高兴的一件事。

成都是一个悠闲的城市,在这样一个地方,一年内体重也增加了好几斤。不过我本来就偏瘦,增加体重说明身体更好了^_^

我喜欢平淡而又充实的生活,所以没什么大喜大悲的事情。我喜欢这样的生活。

谈不上抒情,也没有抒情的文笔,简单记录之。

在Oracle的备份恢复过程中,需要注意数据文件的unrecoverable,不适当的操作很容易造成恢复后有大量的坏块。在视图v$datafile中,UNRECOVERABLE_CHANGE#和UNRECOVERABLE_TIME分别表示数据文件最后一个unrecoverable操作的change#和时间。unrecoverable通常就是指不记录日志的操作(nologging),这样当用一个旧的数据文件还原后,用日志进行恢复时,由于日志文件没有记录unrecoverable的操作时的日志,导致那些操作的数据块为逻辑坏块(实际上在日志文件中为这样的操作产生了一些重做日志项,在恢复时,根据这些重做日志项,直接将相应的数据块标记为坏块)。常见的以下几种情况:
1. 非归档模式下的create table as 操作和直接路径插入(如加了append hint的insert语句和直接路径装载)
2. 归档模式下的create table xxx nologging(即创建表时为表指定了nologging)和nologging表的直接路径插入。
在数据库(或表空间)为force logging时,任何操作都会记录日志。不会有unrecoverable操作。

下面先做个实验(数据库版本为9.2.0.1)来看看这两列:

数据库当前处于非归档模式;

SQL> select name,checkpoint_time,unrecoverable_time from v$datafile where file#=10;

NAME CHECKPOINT_TIME UNRECOVERABLE_TIME
---------------------------------------- ------------------- -------------------
D:\ORACLE\ORADATA\XJ\TEST01.DBF 2008-09-23 09:28:22

SQL> create table t tablespace test nologging as select * from dba_objects where rownum< =10; 表已创建。 SQL> select name,checkpoint_time,unrecoverable_time from v$datafile where file#=10;

NAME CHECKPOINT_TIME UNRECOVERABLE_TIME
---------------------------------------- ------------------- -------------------
D:\ORACLE\ORADATA\XJ\TEST01.DBF 2008-09-23 09:28:22

可以看到,unrecoverable_time为空。想一想就可以理解,unrecoverable操作都是将数据直接写入了数据文件,没有经过SGA的缓存,非归档模式下的物理备份都是一致的冷备份,不需要日志来进行恢复,因此对于非归档模式下并不存在unrecoverable操作。unrecoverable只是针对归档模式的。下面将数据库置为归档模式后,重复上述过程,进行验证:

SQL> create table t tablespace test nologging as select * from dba_objects where rownum< =10; 表已创建。 SQL> select name,checkpoint_time,unrecoverable_time,unrecoverable_change# from v$datafile where file#=10;

NAME CHECKPOINT_TIME UNRECOVERABLE_TIME UNRECOVERABLE_CHANGE#
---------------------------------------- ------------------- ------------------- ---------------------
D:\ORACLE\ORADATA\XJ\TEST01.DBF 2008-09-23 09:45:03 2008-09-23 09:45:41 1298047

可以看到,v$datafile视图中unrecoverable_time和unrecoverable_change#已经有了值。

下面来看看unrecoverable_time是最后一次unrecoverable操作的开始时间还是结束时间?
创建一个具有延时功能的函数:

create or replace function f_cdate return date
as
begin
dbms_lock.sleep(10);
return sysdate;
end;

SQL> create table t (d date) nologging tablespace test;

表已创建。

SQL> begin
2 dbms_output.put_line('start test:'||sysdate);
3 insert /*+ append */ into t select f_cdate from dba_objects where rownum< =10; 4 dbms_output.put_line('after insert:'||sysdate); 5 dbms_lock.sleep(60); 6 commit; 7 dbms_output.put_line('end test:'||sysdate); 8 end; 9 / start test:2008-09-23 10:31:50 after insert:2008-09-23 10:33:33 end test:2008-09-23 10:34:34 PL/SQL 过程已成功完成。 SQL> select name,checkpoint_time,unrecoverable_time,unrecoverable_change# from v$datafile where file#=10;

NAME CHECKPOINT_TIME UNRECOVERABLE_TIME UNRECOVERABLE_CHANGE#
---------------------------------------- ------------------- ------------------- ---------------------
D:\ORACLE\ORADATA\XJ\TEST01.DBF 2008-09-23 09:45:03 2008-09-23 10:33:33 1299032
SQL> begin
2 dbms_output.put_line('start test:'||sysdate);
3 insert /*+ append */ into t select f_cdate from dba_objects where rownum< =10; 4 dbms_output.put_line('after insert:'||sysdate); 5 dbms_lock.sleep(60); 6 rollback; 7 dbms_output.put_line('end test:'||sysdate); 8 end; 9 / start test:2008-09-23 10:37:59 after insert:2008-09-23 10:39:42 end test:2008-09-23 10:40:43 PL/SQL 过程已成功完成。 SQL> select name,checkpoint_time,unrecoverable_time,unrecoverable_change# from v$datafile where file#=10;

NAME CHECKPOINT_TIME UNRECOVERABLE_TIME UNRECOVERABLE_CHANGE#
---------------------------------------- ------------------- ------------------- ---------------------
D:\ORACLE\ORADATA\XJ\TEST01.DBF 2008-09-23 09:45:03 2008-09-23 10:39:42 1299157

可以看到unrecoverable_time为unrecoverable操作完成的那个时间,不管事务是否提交。

对于数据库备份后的恢复,需要注意查询v$datafile视图中关于unrecoverable操作时间,如果unrecoverable操作时间在数据文件备份之后(更精确的比较是通过change#,比较文件的checkpoint_change#和unrecoverable_change#),则恢复会产生坏块。

建议重要的数据库,将数据库置为force logging(当然数据库应当是归档模式),避免无意的产生了unrecoverable操作。或者在做了unrecoverable操作之后立即进行数据文件的备份。

PS:关于不产生日志的操作,请参见metalink NOTE:269274.1 CHECK FOR LOGGING/NOLOGGING ON DB OBJECT(S)

,

以前的模板,不太适合于写技术类文章,左边内容部分太窄,现在换一个。页面基调为绿色,但上去比较轻爽,似乎不太适合于技术类,不过自己的地盘,自己作主,自己喜欢就行。^_^

先说说这个数据库的环境:
Oracle 9.2.0.4 RAC,只不过这个RAC只运行了一个节点,另一节点没有开启。
AIX 5.3 TL04
主机为p550,4CPU,16G内存
应用为部署在Weblogic下的WEB应用。

故障现象:
首先是客户端的操作没有响应,从weblogic上看连接数非常高,其日志里面不停报超出连接池的最大连接数。在主机上用sqlplus "/ as sysdba",在显示sqlplus的banner后,停止响应。

从故障现象来看,是数据库hang住了。

由于sqlplus不能操作,那么这个时候没办法通过oracle来dump system state。先看看操作系统里面,用topas命令观察,发现一个oracle进程占用了26%左右的CPU资源,IO等待几乎为0,可用的物理内存还比较多。根据那个占用CPU的进程号用ps命令查看,是一个普通的Server Process。

看来起这个进程陷入死循环了,26%的CPU资源正好是1个CPU(因为系统共4个CPU)。如果一个oracle进程拿到比较重要的资源,比如shared pool latch、library cache latch等,然后陷入了死循环(SPIN)后,其他进程没法解析SQL等,也就只有挂起了。

用kill命令杀掉那个进程,系统恢复正常,看来前面对故障的推断是正确的,不过没过几分钟,又出现了此故障现象。

只有找到oracle当时正在干什么,才能进行处理。用dbx来dump system state:

# dbx -a 446910
Waiting to attach to process 446910 ...
Successfully attached to oracle.
Type 'help' for help.
reading symbolic information ...
stopped in iosl.select at 0x9000000000c94d8 ($t2)
0x9000000000c94d8 (select+0xfffffffffff06318) e8410028 ld r2,0x28(r1)
(dbx) print ksudss(10)

Segmentation fault in slrac at 0x100083aa0 ($t2)
0x100083aa0 (slrac+0xe4) 88030000 lbz r0,0x0(r3)
(dbx) detach

Read the rest of this entry

经常遇到客户和其他一些Oracle开发与维护人员,问我为啥使用了RAC,没有感受到业务系统有明显的性能提升,有时反而觉得性能有所下降。这种认为RAC一定能够提高性能的想法,有着广泛的“群众基础”。可以说,使用RAC来提高性能是一种存在于广大ORACLE数据库使用者之间的误解。

这里我不想过多于技术上去解答这个问题,而是从下面这个类比来说明这个问题:

这里我们要谈论的是大部分的业务系统类型,事务处理型,也就是OLTP。虽然很多OLTP类型的系统还兼有生成一些报表和统计数据的功能,但那只是一部分小的功能,主要还是事务处理。

大家都去过银行,假设一个银行营业厅有6个业务窗口,来这个营业厅办理业务的客户一般为3至5个人,最多6个人。由于每个人办理业务的时间,是跟他(她)的业务类型有关的,比如取款2分钟,存款2分钟,开户要5分钟等等,不会以窗口数的增多而减少时间。以这个例子来说,6个窗口已经足够了,因为6个窗口数大于同时办理业务的客户数,而一个客户只会在一个窗口办理业务,就算再多的业务处理窗口,也不会对每个客户办理业务有速度上的提升。

现在假设银行的业务有了很大的发呢,银行营业厅里面的客户比较多了,同时来办理业务的常常超过10人,这个时候就是银行营业厅的窗口不够了(资源不足),客户存在了排队,严重影响了客户办理业务的效率。而营业厅由于受面积的限制,不能增加窗口了(对于机器来说,不能扩容了),这个时候银行在附近又开了一个新的营业厅(增加了一个新的结点),那样部分客户分流到了新的营业厅,这样消除了客户的排队,客户又能够高效率地在银行办理业务了。

使用RAC类似于上面提到的银行,如果业务系统能够在单台机器上跑,这个时候由于资源足够,增加新的结点不会带来性能上的提升,而如果随着业务的发展,机器资源受限,不能为更多的用户服务,这个时候增加新的结点,能够使业务系统能够为更多的用户服务。

然而在现实生活中,很多业务系统并没有为RAC进行一些优化,同时RAC的结点之间由于数据同步的代价比较高,因而使用RAC后往往感受到业务系统并没有更快,有时感觉反而更慢。

RAC的作用更体现于高可用性、水平可扩展性,其次才是某些条件下的性能提升(比如针对于某些DSS系统)。