小插曲

Posted by Freedba on July 21st, 2009

2009年6月27日 星期六

         今天是6月27号,又是一个应用上线日.每到这样的日子,各个开发中心的人就从五湖四海云集到北京,做应用新版本的上线部署.11楼里也就显得特别热闹,跟菜市场似的,人山人海,颇为壮观.不过在这样看上去乱成一糟的场面下,却是分工极为明确,毕竟停机时间有限,什么时间谁该干什么都早有了精心的安排.小罗回武汉度婚假去了,幸福的小男人啊,让人羡慕不已.他所支持的系统今天有上线的安排,我也就义不容辞的帮他顶一下.不过还好没人安排我要到现场,必要的时候电话支持一下就好了.知道这个消息,心里暗暗庆幸了一下,周末可以在家好好看会电视了.

       一到周末,整个人就懒了下来.吃饭就更加没规律了.时间过得飞快,不知不觉中已经到了8点半,肚子饿得不行了.我喜欢肚子饿的感觉,这样的状态下才会觉得吃饭是一种享受,而不是像为了活着似的例行公事.我住的地方在南边的三环新城,晚上挺热闹的,露天的太阳伞下,烧烤、啤酒、凉菜、卤煮,还有各色各样的小吃,引得忙碌了一天的人们停下疲惫的脚步,和朋友、家人一起享受下难得的清净。路口拐弯的地方,有一家广东人开的夜市,是我最常去的一家,偶尔跟老板说上几句粤语后,也能感受到一种难得的亲切。最主要的是那里有我比较爱吃的烤茄子,烤玉米和生耗。蔬菜烧烤在北方是比较难见到的,满大街基本都是只烤羊肉串。想到这,食欲就来了,出了门直奔那去。从家到那里步行要十分钟左右。路上我看了下时间,快九点了,他们应该已经开始操作了。之前发现有个存储过程的物理读比较大,里面的一个SQL用了全表扫描,对IO造成了一定的压力。今天他们在数据库方面的操作也就是着针对性的新建一个索引,顺利的话应该没我啥事。不过我一般不这么想,以往的经验证明,老天爷总是会想办法给你找点事做的。还真是的,就在这时,电话响了,小谢打来的。

         小谢是我比较佩服的一个人,技术很全面,现在是这个系统的项目经理。原来,他们把索引建起来后,执行了一个SQL语句以验证是否走索引,结果走了全表扫描。执行的语句很简单,select * from table where cola=XXX .其中cola是一个skew的列,XXX在COLA中值很少。这是典型的可以用索引来去除全表扫的。数据库是AIX 上9208的RAC。他们在发现走了全表扫描后,对索引进行了统计信息的收集,问题依旧,问我可能是什么原因造成的。我想了一下,难道是语句还用原来的执行计划?于是我叫他在语句中多加几个空格,把一两个字符大小写改一下,以重新解析。不过这个方法他早做过了,10046里显示的misses in library cache parse为1。说明确实是做了硬解析的。针对表的列倾斜的情况,我建议他分析一下直方图好让CBO知道这个值的选择率。郁闷的是这个他也做了,dba_tab_columns里显示的histogram为频率直方图。这我就纳闷了。。。看来我想到的他都想了。这时,电话里换了另外一个人的声音,是老郑,他是行里这个系统的主管经理。他问我能不能过去一趟?’行吧,我这就赶过去.’做乙方的能说不吗?

新应用上线前的CORE DUMP

Posted by Freedba on July 16th, 2009

13层的办公室里,静悄悄的一片……

50多个来自不同公司的外包人员每天就在这里辛勤的忙碌着,吵吵嚷嚷的,为自己的梦想在默默的打拼着。从一开始的怀揣梦想到和朋友的创业以失败告终,我陷入了无尽的深渊中,各方面的压力也随之而来。经过漫长的考虑,为了能早点偿还背负的债务,我决定背起行囊,离开我心爱的家乡,但这次我并没有选择我的伤心地-深圳。而是希望到另外一个陌生的地方,踏踏实实的重新开始。08年的4月,我只身来到北京,加入到了北漂一族,就在这个屋子里开始了一个从未接触过的职业,DBA。

对这份工作,我格外的珍惜和热爱。所以当中午大伙都趴台休息的时候,我就趁着难得的安静,好好看会书。希望能多学点东西,希望以后有机会可以出去接点私活,早点还清债务。

终于,刺耳的铃声还是打破了这一天里难得的宁静。

11楼电话打来,说有个机器出现了ORACLE 的CORE DUMP。

我一听傻了,这是个刚搭建起来不久的新环境,AIX 5.3上的oracle 10.2.0.3,单实例,HA。现在应用开发商正在上面进行上线前的测试呢。这个时候出现core dump,会对应用不久后的上线多少造成信心上的影响,同时也可能会有人对我所搭建的环境提出质疑。抖擞下精神,出发吧……

处理细节:

二、问题分析过程
2.1、使用errpt -aj
使用errpt -aj确认CORE DUMP的进程和CORE DUMP文件的位置
见红色加粗部分,可确认确实是SQLPLUS发生了CORE DUMP,CORE文件放为
/somepath/core

oracle@HOST_AIX:/somepath> errpt -aj 40E9A4E1
—————————————————————————
LABEL:          CORE_DUMP
IDENTIFIER:     40E9A4E1

Date/Time:       Wed May 13 14:51:21 BEIST 2009
Sequence Number: 649
Machine Id:      00C1F6EB4C00
Node Id:         HOST_AIX
Class:           S
Type:            PERM
Resource Name:   SYSPROC        

Description
SOFTWARE PROGRAM ABNORMALLY TERMINATED

Probable Causes
SOFTWARE PROGRAM

User Causes
USER GENERATED SIGNAL

        Recommended Actions
        CORRECT THEN RETRY

Failure Causes
SOFTWARE PROGRAM

        Recommended Actions
        RERUN THE APPLICATION PROGRAM
        IF PROBLEM PERSISTS THEN DO THE FOLLOWING
        CONTACT APPROPRIATE SERVICE REPRESENTATIVE

Detail Data
SIGNAL NUMBER
           3
USER’S PROCESS ID:
                107374
FILE SYSTEM SERIAL NUMBER
          11
INODE NUMBER
       66218
PROCESSOR ID
          -1
CORE FILE NAME
/somepath/core
PROGRAM NAME
sqlplus
STACK EXECUTION DISABLED
           0
COME FROM ADDRESS REGISTER
??
ADDITIONAL INFORMATION
read 1C4
??
__filbuf 400
fgets 188
slfirs E0
lfibgl 14C
lfibfil 120
lfibrdl 6C
lfird 294
safiinp 64
afiinp 104
afinligtl 1A4
afinli 304
aficfd 1E8
aficdr B4
afidrv 106C
main 50
__start 9C

Symptom Data
REPORTABLE
1
INTERNAL ERROR
0
SYMPTOM CODE
PCSS/SPI2 FLDS/sqlplus SIG/3 FLDS/read VALU/1c4
—————————————————————————
LABEL:          CORE_DUMP
IDENTIFIER:     40E9A4E1

Date/Time:       Mon May 11 09:44:33 BEIST 2009
Sequence Number: 648
Machine Id:      00C1F6EB4C00
Node Id:         HOST_AIX
Class:           S
Type:            PERM
Resource Name:   SYSPROC        

Description
SOFTWARE PROGRAM ABNORMALLY TERMINATED

Probable Causes
SOFTWARE PROGRAM

User Causes
USER GENERATED SIGNAL

        Recommended Actions
        CORRECT THEN RETRY

Failure Causes
SOFTWARE PROGRAM

        Recommended Actions
        RERUN THE APPLICATION PROGRAM
        IF PROBLEM PERSISTS THEN DO THE FOLLOWING
        CONTACT APPROPRIATE SERVICE REPRESENTATIVE

Detail Data
SIGNAL NUMBER
           3
USER’S PROCESS ID:
                102680
FILE SYSTEM SERIAL NUMBER
          15
INODE NUMBER
       37120
PROCESSOR ID
          -1
CORE FILE NAME
/home/db/oracle/tmp/core
PROGRAM NAME
sqlplus
STACK EXECUTION DISABLED
           0
COME FROM ADDRESS REGISTER
??
ADDITIONAL INFORMATION
read 1C4
??
__filbuf 400
fgets 188
slfirs E0
lfibgl 14C
lfibfil 120
lfibrdl 6C
lfird 294
safiinp 64
afiinp 104
afinligtl 1A4
afinli 304
aficfd 1E8
aficdr B4
afidrv 106C
main 50
__start 9C

Symptom Data
REPORTABLE
1
INTERNAL ERROR
0
SYMPTOM CODE
PCSS/SPI2 FLDS/sqlplus SIG/3 FLDS/read VALU/1c4
oracle@HOST_AIX:/somepath>

2.2、检查ORACLE alert日志
Cd $ORACLE_HOME/admin/$ORACLE_SID/bdump
Vi alert_$ORACLE_SID.log
未发现任何ORA-错误和其他有用的信息。
2.3、检查ORACLE CDUMP目录
Cd $ORACLE_HOME/admin/$ORACLE_SID/cdump
无任何CORE文件生成
2.4、初次分析
从1到3的检查可知,本次CORE DUMP虽然发生在ORACLE的SQLPLUS进程上,但是ORACLE的alert日志和CDUMP目录无任何异常,也就是本次CORE DUMP为OS LEVEL的CORE DUMP,和RDBMS无关,对数据库无影响。既然没发现什么有用的信息,不如确认下到底谁做了什么操作
2.5、CTRL+C?
经询问,开发回答为使用了CTRL+C终止了SQLPLUS进程。
CTRL+C终止进程会导致OS的CORE DUMP?
显然不符合常理,如果是这样,那平时用了那么多CTRL+C,那蚩不是天天CORE DUMP了?问题发生在ORACLE上,是不是ORACLE的BUG?
2.6、尝试METALINK
用AIX上的dbx命令检查SQLPLUS 异常时出错的系统调用
oracle@HOST_AIX:/somepath> dbx /home/db/oracle/product/10.2.0/bin/sqlplus core
Type ‘help’ for help.
[using memory image in core]
reading symbolic information …warning: no source compiled with -g
Quit in read at 0×900000000064b98 ($t1)
0×900000000064b98 (read+0×1c4) e8410028          ld   r2,0×28(r1)
(dbx) where
read(??, ??, ??) at 0×900000000064b98
__filbuf(??) at 0×900000000062474
fgets(??, ??, ??) at 0×900000000061a2c
slfirs(??, ??, ??, ??, ??, ??) at 0×10004e83c
lfibgl(??, ??, ??, ??, ??, ??) at 0×10004e308
lfibfil(??, ??, ??) at 0×10004dddc
lfibrdl(??, ??, ??, ??, ??) at 0×100050648
lfird(??, ??, ??, ??) at 0×100051ab0
safiinp(??, ??) at 0×100051680
afiinp(??, ??, ??, ??, ??, ??, ??, ??) at 0×1000b6200
afinligtl(??, ??, ??) at 0×100d96480
afinli(??, ??, ??, ??, ??) at 0×100d96860
aficfd(??) at 0×100dbb0a4
aficdr(??) at 0×100e15a50
afidrv(??, ??, ??, ??) at 0×100054228
main(??, ??) at 0×1000005cc
(dbx) quit
oracle@HOST_AIX:/somepath>

通过步骤6出错的系统调用filbuf fgets等检索METALINK,通过keywords ‘SQLPLUS~CORE’检索也未发现任何类似按例。问题陷入僵局
三、问题研究
3.1、信号研究
到底是什么导致了OS CORE DUMP,不应该是CTRL+C,CTRL+C只是给OS传递了一个中断信号而已。检索信号的相关文档,发现

常见信号列表
Name     Number DefaultAction Description
SIGHUP     1     T     Hangup
SIGINT     2     T     Interrupt from keyboard (^C)
SIGQUIT     3     T+D     Quit from keyboard (^\)
SIGILL     4     T+D     Illegal Instruction
SIGFPE     8     T+D     Floating Point Exception
SIGKILL     9     T     Kill signal, cannot be caught
SIGSEGV     11     T+D     Invalid memory reference
SIGPIPE     13     T     Write to a pipe with no readers
SIGTERM     15     T     Graceful termination signal
SIGCHLD     17     I     Child process terminated
T :结束进程 D: CoreDump  I:Ignored

可以看出,使用kill -3,kill -4,kill -8,kill -11 时不单可以结束进程,还同时会CORE DUMP。仔细分析当手工使用kill -3 pid或者CTRL+\退出进程,或者程序运行过程由于出现非法的指令、出现浮点错误(如分母为0)或者访问了非法的内存地址时都会CORE DUMP。
因此手工结束进程导致的CORE DUMP有2个办法,’kill -3 pid或者CTRL+\退出进程’
其他为程序运行过程发生expection导致而自行终止进程的CORE DUMP
3.2、与errpt -aj核对
检查errpt -aj的信息,发现
SIGNAL NUMBER
           3
确实是通过信号3来终止进程的。
四、问题验证
4.1、搭建环境
在个人虚拟机上编写一个小的C程序,程序睡眠60秒
/* 编写的简单的C,睡60秒 */

oracle@shadow:/tmp/hyb_c>cat 2.c
int main()
{
sleep(60);
}

/* 编译 */
oracle@shadow:/tmp/hyb_c>gcc -o 2 2.c

4.2、执行测试(1)
执行的时候用ctrl+\来结束进程
oracle@shadow:/tmp/hyb_c>./2
退出 (core dumped)

oracle@shadow:/tmp/hyb_c>ll -rt
-rw-r–r–  1 oracle dba      26  4月 19 23:20 2.c
-rwxr-xr-x  1 oracle dba    4701  4月 20 01:07 2
-rw——-  1 oracle dba 1306624  4月 20 01:10 core.3751

可以看到产生CORE DUMP了

4.3、执行测试(2)
使用kill -3的办法
窗口一运行
oracle@shadow:/tmp/hyb_c>./2

窗口二检查
oracle@shadow:/home/oracle>ps -ef|grep ./2
oracle    4099  3672  0 02:26 pts/0    00:00:00 ./2
oracle    4101  3724  0 02:26 pts/1    00:00:00 grep ./2
oracle@shadow:/home/oracle>kill -3 4099
oracle@shadow:/home/oracle>

回到窗口一,发现
oracle@shadow:/tmp/hyb_c>./2
退出 (core dumped)

Kill -3 也一样可以在终止进程的同时产生CORE DUMP
4.4、与开发再次确认
再次与开发联系,经确认,确实是使用了CTRL+\来终止的SQLPLUS,而不是一开始说的CTRL+C。建议
如果CTRL+C无法退出进程,用kill -9也可以,就是不能用kill -3 \kill -4\kill 8\ kill -11或者等同于信号3的ctrl+\操作 即可。
五、总结
常规方法如metalink不起作用时,不如花点时间切入研究,可能会发现新大陆。实在不行,转给厂家继续跟进。
这个问题,如果一开始出现CORE DUMP告警时,开发直接说出事情的真相(可能是出于怕担当责任等各种原因吧,能理解),就不需要费神费时费力去查了,最后的结果让人苦笑不得。

来的不是时候的电话

Posted by Freedba on July 13th, 2009

咽完午饭,已经是11点半了。食堂的午餐虽然难吃,但是有公司买单,所以虽然大家一致觉得很难吃,可是也没见到谁放弃了这个福利。
看来大家都不富裕啊,北京房价这么高,能省点就省点吧……
有意思的是,最近大家多了个爱好,每天吃完午饭,就到附近的一个台球馆打球,步行15分钟就到了。
以前打小案子来的,北方很流行的黑8,谁输谁下,人多的时候,一下能去五六个,所以打黑8的话大伙能多打几把。
可是时间长了,大家就有点腻了,决定换斯诺克打打,也感受一下什么叫远台进攻。
进了球馆,选好杆,电话又不争气的响了,我的心一下提到嗓子眼上。”乖乖,希望是我老婆的来电。”。可是往往是你不希望来什么,却偏偏来什么。

果然,出现告警了,有个系统的归档文件系统76%,告警阀值是70%-80%,据说还在继续增长。
这在以前是不正常的。以前的使用率,历史峰值也从来没超过40%。

我现在在外面,10分钟后回去’,挂了电话,跟同伴们摆了一个无奈的表情。走出了球馆……

一路上我开始琢磨起来了,这是一个HPUX 11.23上的9208的环境,单实例。对于应用方面的信息,我则知之甚少。
赶回来的路上,我给应用开发商的左工去了个电话,跟他说明了这个情况,并且希望一会他能给我应用方面的支持。
我简单咨询了一下关于这个应用的架构。
这个系统的设计很简单,接受外围系统ftp过来的数据,做了预处理后,用SQL*LOADER入库,经过运算再把运算结果导出返回给外围系统,类似一个数据加工厂。
外围各个系统给过来的数据是按天给的,文件按不同的系统放在不同的目录下。每天给一次数据。每个系统给过来的数据的时间不确定。
系统中存在一个守护进程在扫描各个目录,发现有文件过来后,会先做一些预处理,然后启动入库;如果发现没有文件,则睡眠一段时间后醒来继续扫描……如此往复。
可以说这是一个日终程序,跑的任务是固定的。不像其他系统,可能并发突然加大。

 

难道今天开发商上来做了什么其他大的操作么?按理来说不会啊,这边的流程控制很严格,这种现象几乎是不可能出现的。
我也询问了一下左工,他们今天是否有大的动作。他很肯定的回答没有。这也是预料之中的事情。
那么能解释这点的,似乎只有”今天的数据量比以往大得多”这个理由了。可是,今天只是很普通的一天,不是月初,也不是月末的。

不知不觉已经到了公司,登陆上去检查一下就可以揭开谜底了。
1、检查归档路径
SQL> archive log list
Database log mode              Archive Mode
Automatic archival             Enabled
Archive destination            /home/db/archive_b
Oldest online log sequence     16570
Next log sequence to archive   16571
Current log sequence           16571

2、检查文件系统使用率
/home/db/oracle_b #bdf
Filesystem      kbytes     used   avail    %used  Mounted on

/dev/VGXX/LVYY  31457280  23907532  7549748    76%   /home/db/archive_b

确实,归档文件系统已经到了76%,并且使用率还在上升没有停止的势头。为了避免归档文件系统被占满而导致系统挂起,
我请应用运维人员联系备份组启动legato把归档先备走,并且密切关注该文件系统的使用率,一旦超过50%,需要再启动LEGATO把归档备走。
好为自己核查问题赢得更充裕的时间。
那么到底是哪个会话什么程序导致了这个问题呢。

3、检查哪个会话生成最多的归档最多
SQL> select STATISTIC# ,NAME from v$statname where name like ‘%redo size%’;

STATISTIC# NAME
———- —————————————————————-
115        redo size

create table tmp_0422 as select sid,value from v$sesstat where statistic#=115;

稍微等上几分钟,执行
SQL> select a.sid,b.value-a.value from tmp_0422 a,v$sesstat b where a.sid=b.sid(+) and b.statistic#=115 order by 2;

       SID B.VALUE-A.VALUE
———- —————
         1               0
         3               0
         4               0
         6               0
         7               0
        10               0
        12               0
        20               0
        36               0
        22               0
        11               0

       SID B.VALUE-A.VALUE
———- —————
         9               0
         5          193120
         8          301712
         2        18705888
        16      1701174280

16 rows selected.
3、
两个时间段一减,立刻发现会话16生成了1.7个G的redo log,在所有会话里生成量最大。这段时间生成1.7G的数据量算不算正常呢?没有历史数据做比对,这个问题不好回答。
接着检查该会话的详细信息,发现

SQL>select  machine,program from v$session where sid=’16′
——————————————–
HOST_AP         sqlldr (TNS V1-V3

恩,是SQL*LOADER,看来正在入库数据。
SQL> select sql_text from v$sqltext where address in(select sql_address from v$session where sid=16) order by piece;

SQL_TEXT
—————————————————————-
INSERT INTO BC_LOG_STOCKTRANSFER   (CREDIT_ID,USERID,TXCODE,SERI
AL,ACC_DATE,BRANCH_CODE,TRAN_DATE,IP_ADD,BBRANCH_CODE,ACC_NO,ACC
_TYPE,BROKER_CODE,BOURSE_CODE,STOCKHOLDER_CODE,FEE,AMOUNT,CUR_TY
PE,STATUS,DAC,TRAN_TYPE) VALUES (:CREDIT_ID,:USERID,:TXCODE,:SER
IAL,:ACC_DATE,:BRANCH_CODE,:TRAN_DATE,:IP_ADD,:BBRANCH_CODE,:ACC
_NO,:ACC_TYPE,:BROKER_CODE,:BOURSE_CODE,:STOCKHOLDER_CODE,:FEE,:
AMOUNT,:CUR_TYPE,:STATUS,:DAC,:TRAN_TYPE)

7 rows selected.
……过了一会再检查……
SQL> select sql_text from v$sqltext where hash_value in(select decode(sql_hash_value,0,prev_hash_value,sql_hash_value) from v$session where sid=’&sid’) order by piece;
Enter value for sid: 16
old   1: select sql_text from v$sqltext where hash_value in(select decode(sql_hash_value,0,prev_hash_value,sql_hash_value) from v$session where sid=’&sid’) order by piece
new   1: select sql_text from v$sqltext where hash_value in(select decode(sql_hash_value,0,prev_hash_value,sql_hash_value) from v$session where sid=’16′) order by piece
SQL_TEXT
—————————————————————-
INSERT INTO BC_LOG_PAYMENT   (CREDIT_ID,USERID,TXCODE,SERIAL,ACC
_DATE,BRANCH_CODE,TRAN_DATE,IP_ADD,PAY_BBRANCH_CODE,PAY_ACC_NO,P
AY_ACC_TYPE,MER_ACC_NO,POS_CODE,MERCHANT_CODE,REMARK1,REMARK2,FE
E,ORDER_NUM,CUR_TYPE,AMOUNT,STATUS,DAC,PAY_ACC_NAME,AGREE_STATUS
,LOCATION,REFUNDEMENT_AMOUNT) VALUES (:CREDIT_ID,:USERID,:TXCODE
,:SERIAL,:ACC_DATE,:BRANCH_CODE,:TRAN_DATE,:IP_ADD,:PAY_BBRANCH_
CODE,:PAY_ACC_NO,:PAY_ACC_TYPE,:MER_ACC_NO,:POS_CODE,:MERCHANT_C
ODE,:REMARK1,:REMARK2,:FEE,:ORDER_NUM,:CUR_TYPE,:AMOUNT,:STATUS,
:D AC,:PAY_ACC_NAME,:AGREE_STATUS,:LOCATION,:REFUNDEMENT_AMOUNT)

……过了一会再检查……
发现的信息无非是会话在往另外一张表导入数据。相应的文件导入相应的表中
4、

回到最开始的分析,验证下今天入库文件的数据量是不是比以前多了。
根据电话里左工一步步的指导,我找到了当天过来的所有文件,和前7天的数据做了比对,和以前是一个数量级的。
排除了这个情况。那么还可能是什么原因呢,检查也没发现有其他会话在干活。跟之前对系统描述的是一样的。
时间一分一秒过去,也没有发现造成这个问题的根本原因。
接下来系统开始空跑了。也就是进程进入了睡眠时间。
归档日志之前被LEGATO备走后,才一会功夫,又涨到了20%。不过进程进入了睡眠,归档文件系统的使用率也暂时停止了增长。
左工告诉我,要休眠30分钟才会醒来扫描别的目录,发现别的系统传来了文件则继续处理。
趁着这中间的工夫,我出去抽了根烟,把思路好好缕缕,也好提提神。

5、

好不容易等半个小时过去了,SQL*LOADER的入库非常快,这次我一定在入库的过程中好好检查检查。
依然是查找生成归档日志最大的会话
SQL>  select a.sid,b.value-a.value from tmp_0422 a,v$sesstat b where a.sid=b.sid(+) and b.statistic#=115 order by 2;

       SID B.VALUE-A.VALUE
———- —————
        18           -4520
         1               0
         3               0
         4               0
         6               0
         7               0
        10               0
        20               0
        22               0
        12               0
        11               0

       SID B.VALUE-A.VALUE
———- —————
         9               0
         5          365936
         8          735792
         2        42392032
        28      1988499944

16 rows selected.

重新起来后,可以看到进程以新的SID 28来导数了。
SQL> @sql_sid
Enter value for sid: 28
old   1:  select sql_text from v$sqltext where hash_value in(select decode(sql_hash_value,0,prev_hash_value,sql_hash_value) from v$session where sid=’&sid’) order by piece
new   1:  select sql_text from v$sqltext where hash_value in(select decode(sql_hash_value,0,prev_hash_value,sql_hash_value) from v$session where sid=’28′) order by piece

SQL_TEXT
—————————————————————-
INSERT INTO BC_LOG_PAYMENT   (CREDIT_ID,USERID,TXCODE,SERIAL,ACC
_DATE,BRANCH_CODE,TRAN_DATE,IP_ADD,PAY_BBRANCH_CODE,PAY_ACC_NO,P
AY_ACC_TYPE,MER_ACC_NO,POS_CODE,MERCHANT_CODE,REMARK1,REMARK2,FE
E,ORDER_NUM,CUR_TYPE,AMOUNT,STATUS,DAC,PAY_ACC_NAME,AGREE_STATUS
,LOCATION,REFUNDEMENT_AMOUNT) VALUES (:CREDIT_ID,:USERID,:TXCODE
,:SERIAL,:ACC_DATE,:BRANCH_CODE,:TRAN_DATE,:IP_ADD,:PAY_BBRANCH_
CODE,:PAY_ACC_NO,:PAY_ACC_TYPE,:MER_ACC_NO,:POS_CODE,:MERCHANT_C
ODE,:REMARK1,:REMARK2,:FEE,:ORDER_NUM,:CUR_TYPE,:AMOUNT,:STATUS,
:D AC,:PAY_ACC_NAME,:AGREE_STATUS,:LOCATION,:REFUNDEMENT_AMOUNT)

9 rows selected.
还是老套路,我这样能查到问题吗?我开始怀疑自己了。
不过,再仔细看这个语句,终于发现了问题的线索了……

 
这个不就是上一次入库中SQL*LOADER中曾经导入的其中一张表吗?为什么会重复导2次呢?
难道是……难道是程序进入了死循环?!
这个想法一出,我整个人马上兴奋起来了。接下来,我要验证我的想法是不是真的疯了。我把第二次抓到的表名和第一次抓到的表名逐一做了比对,真的是完全的重复!

6、

我把我的想法告诉了左工,’不会吧’,左工不敢相信。
接下来就是要验证这个想法了,通过左工电话中的描述,我一步一步的进入到了导入程序的LOG。
发现了下面的这一段应用日志

 71476  Import data into bc_log_fundtransfer Success ……–<2009-04-22 16:49:40>
 71477
 71478  bc_log_fundtransfer 导数成功
 71479  清空基金确认信息表,个人客户新增、变动信息临时表
 71480
 71481  Table truncated.
 71482
 71483
 71484  Table truncated.
 71485
 71486
 71487  Table truncated.
 71488
 71489
 71490  Table truncated.
 71491
 71492  开始装载[20090421]基金确认信息(来自ods)的数据
 71493
 71494  gzip: CAS_ODS_TCONFIRM_20090421.dat.gz: invalid compressed data–format violated
 71495  CAS_ODS_TCONFIRM_20090421.dat file not found!
 71496  装载[20090421]基金确认信息(来自ods)的数据失败
 
 ……
 ……
 ……
 
 ############
  Commit point reached – logical record count 20537
 69821  Commit point reached – logical record count 22305
 69822  Import data into bc_log_fundtransfer Success ……–<2009-04-22 16:13:59>
 69823
 69824  bc_log_fundtransfer 导数成功
 69825  清空基金确认信息表,个人客户新增、变动信息临时表
 69826
 69827  Table truncated.
 69828
 69829
 69830  Table truncated.
 69831
 69832
 69833  Table truncated.
 69834
 69835
 69836  Table truncated.
 69837
 69838  开始装载[20090421]基金确认信息(来自ods)的数据
 69839
 69840  gzip: CAS_ODS_TCONFIRM_20090421.dat.gz: invalid compressed data–format violated
 ##########
 

这段LOG被重复着,而其他归档日志量正常的时候,这段LOG只出现了一次。
从这段LOG中也不难看出,由于在解压缩gzip: CAS_ODS_TCONFIRM_20090421.dat.gz的时候,报了无效的压缩数据而使程序退出。
之后睡眠了30分钟,又重复进行的导入。

严格来说,这个程序的逻辑是有问题的。即使出现了异常,也不应该从头把所有数据再导一次啊。毕竟前面的数据是导成功了的。没必要truncate掉重新导。
这个属于后期的调整建议了。马上修改不现实,毕竟需要代码测试、新版本上线等流程。

找到了根本原因,问题就好解决了,只需要让对方重传正确的数据,就可以跳出这个死循环了。

7、

终于外围的一个系统传来了正确的数据,观察导入程序的日志,终于出现了期待中的正常导入。
 76453 
 76454  开始装载[20090421]基金确认信息(来自ods)的数据
 76455  Import data from CAS_ODS_TCONFIRM_20090421.dat into t_fund_conf_info Begining ……–<2009-04-22 18:36:56>
 76458  SQL*Loader: Release 9.2.0.8.0 – Production on Wed Apr 22 18:36:56 2009
 76459 
 76460  Copyright (c) 1982, 2002, Oracle Corporation.  All rights reserved.
 76461 
 76462  Commit point reached – logical record count 2442
 76463  Commit point reached – logical record count 4884
 76464  Commit point reached – logical record count 7326
 76465  Commit point reached – logical record count 9768

看到这个日志,终于放下心来了。不然这个归档日志不断的增长,要折腾多少人不能下班和睡觉呢。
庆幸。

总结:

1、这个事情本来是要应用运维人员要第一时间去查应用日志的问题。可是报警的是数据库的归档日志,结果承受压力的是我一个人,查应用日志的人却是我,对应用不了解的人。
   说明了有很多需要思考的地方。
2、了解应用的设计,处理好和应用开发商的关系对问题的处理很重要。本次开发商的左工给了我应用方面的很多支持,包括要导入的文件放在哪,导入程序的LOG在哪。
3、细心是不可缺少的。将多个现象联系起来给出大胆的猜想,然后去验证。

外援

Posted by freedba on July 12th, 2009

2009年7月3号 星期五 天气晴朗

早上到公司,打开邮件看了看,今天应该没什么事,索性下楼抽会烟吧。
刚下楼,电话就响了,是阿伟的,一看知道准没好事。
这家伙,上次帮他解决几个问题的钱还没给我呢,还倒贴了车费。谁叫他是朋友呢,认了。
果然,他们正在谈维护合同的一个客户,今天系统变得很慢,希望得到帮助。而现在正处于拿下这个单子的关键时期,希望我能过去支援一下。
我问他系统怎么回事,据客户给他的描述,早上客户在建一个索引,系统就慢得不行了,所有日常工作都受到了影响。
照例,我问了一下系统资源的使用情况,据他说现在好几个盘都是busy 100%,WIO也比较高,将近40%。
听完大概明白慢的原因了,系统估计存在不少的全表扫描,所以盘很忙。
于是让他检查了一下gv$session_wait,发现了大量的db file scattered read和gc buffer busy。
看来应用并没有针对RAC系统做设计,而是单纯的采用了load balance.
另外,这个客户的系统的是AIX 5.3上的ORACLE RAC 10.2.0.2,2个节点,用了ASM。

我想了一下,系统是今天早上才突然出现这个情况的。针对这个情况的描述,基本可以确定为执行计划发生了变化。
10g上创建索引时会自动收集统计信息,相比9i来说是一个大的进步。
9i下如果创建完索引没有及时收集统计信息,例如只是create index而未采用create index ..compute statistics,是可能会造成原有语句的执行计划发生改变的。
问题是据阿伟的描述,现在索引还在创建过程中,而不是已经创建完了。所以按理应该不存在新建索引导致执行计划变慢的情况才对啊。
不想了,到现场了再说,先干好自己手上的的活吧。
中间又来了几次电话催,晕,我总不能请假跑出去吧,看来客户把他逼得很紧。
好不容易等到中午11点下班,打车还是坐300呢?从南三环到北三环,打车怎么也要60了,还是300吧,才4毛钱。
再说打车钱估计也是我自己倒贴,现在赚钱不容易啊,一路想着就过了天桥,今天老天爷还算配合,678倒了一站到了草桥,300在草桥是始发站,因此很顺利的找到了一个座位,爱死300了.

好不容易找到地方,已经全身是汗了。阿伟把我接进去,刚坐下来,客户就说了,能否在一个小时内搞定,否则下午的工作还是受到影响,今天他们领导已经追问过好几次了,问到底什么时候能好。我笑了笑,‘尽力吧。’

现场处理细节
1.2.1 TOPAS检查系统资源情况

Read the rest of this entry »

感谢kamusis

Posted by freedba on July 12th, 2009

感谢kamusis,有了他的free hosting计划,才有了这个BLOG.

可惜,很多WP的功能还不会用。我想用一种故事和技术结合起来的方式来写这个BLOG,这样大家看起来会觉得更有意思一些。

以后会把一些遇到的问题记录下来和大家分享,希望能交到更多的朋友,一起学习、提高。


Copyright © 2007 梦开始的地方,自由的DBA. All rights reserved.