1. AP_INVOICES_UTILITY_PKG –发票过账状态
2. AP_INVOICES_PKG –发票验证状态
3. AP_PREPAY_UTILS_PKG
4. AP_PREPAY_PKG
5. AP_PAYMENT_UTIL_PKG
6. AR_RECEIPT_API_PUB –应收接口
1. AP_INVOICES_UTILITY_PKG –发票过账状态
2. AP_INVOICES_PKG –发票验证状态
3. AP_PREPAY_UTILS_PKG
4. AP_PREPAY_PKG
5. AP_PAYMENT_UTIL_PKG
6. AR_RECEIPT_API_PUB –应收接口
情景:Oracle EBS系统批量付款
现象:Oracle EBS系统批量付款卡死
环境:Oracle EBS R12.1.1
取名“一条数据引发的血案”是因为这次事件把自己的第二次通宵奉献出来了。
直接进入主题:2016年4月21日周四,客户在财务系统内批量付款,这次付款从表面上看与往常的批量付款并无差异,92笔付款,量不算大,结果在最后一次鼠标点击确认的时候导致系统直接崩溃(只针对此功能页面,其他功能还是能正常操作)。如下图所示:
一般涉及到付款的操作,一直都是需要十分谨慎的,要是因为付款抽盘数据错误,导致网银付款错误致使公司多付账款,将会造成不可挽回的错误。客户(刚进入公司的新同事)在第一时间找到我,焦急的心情从客户的表述中可以窥见一二。自己也是第一次遇到这样的错误,第一反应就是数据库表被锁了,因为之前也遇到过类似的错误,直接从后台解锁后即可解决问题。但是这次似乎并没有那么简单,后台并未锁表。于是,找到客户的纯数据库DBA检测,从后台的常规日志中可以看到“timeout”的描述,于是通过各种sql命令和linux命令穿梭于PLSQL和操作系统中(幸而能有同事提供生产环境的数据库)。然而,并没有解决,知道下班也并未有任何实质性的进展。于是,为了客户能在周五将今天的付款付出去,在已经格式化付款的状态,一条一条在付款撤销界面点击停止付款,大概统计了一下,这个步骤会超过500次鼠标点击(oracle做得太不智能了,吐槽一下),而且在这个过程中,还出现如下图所示的囧地,无法停止付款(后台解决,IBY_PAYMENTS_ALL表字段update).
由于感觉到事情的严重性,当天晚上到10点多仍然没有解决,于是乎觉得在办公室继续奋战,做到大概12点多,实在熬不起了,很久没有一直工作持续那么长时间,而且是脑袋一直不停的高速运作,在这过去的几个小时内,问过很多同行,大多都是没有好的建议,都建议再向EBS DBA咨询求助。晚上接近一点,睡觉(幸好办公室有张折叠床)。早上6点过几分,起床。继续查找问题,此时已经将昨天留下的92条中的78条数据付款(每次5条左右的数据批付款,也是倒霉,每次都没有碰到那天错误数据)。现在这个时候,最怕的就是客户的追问,不过第二天一早,客户的邮件就来了。客户希望在下午两点之前能解决问题。压力山大。为了能尽快解决问题,向公司申请EBS DBA资源,于是,公司提供一位DBA远程协助。经过20多分钟的排除,得出两个结论:第一,TCP SOCKET超时严重,排列超时第一位;第二,行级锁超时严重,排名超时第二位。DBA也只能做到这里了,但是此时时间已经是下午2点多,于是只能去跟客户解释,目前正在全力排查问题。客户也还好,也只能如此(其实我相信客户内心是崩溃的,两天时间已经积压了好几百万款项待付)。
接下来是周六,本来是该好好休息的时间,结果因为这个事情,觉都睡不好,早上7点多就起来接着查问题。一上午还是没有比较实质性的进展,中午叫了外卖,下午还是继续排查。这之前跟领导甚至商议过如果找不出问题要怎么样先暂时解决问题(具体什么方法就不在此透露)。默默耕耘,必有回响。在晚上11点多的时候,也就是逐条付款的时候,界面上出现了一个比较直接的错误提示,违反唯一约束条件。如下图所示:
于是,能80%确定是应用数据问题,结果果然发现,其中一个供应商的地点层竟然在失效后还多生成了一条付款数据,然后这在界面上看起并没有其他异样,结果从后台查看数据才发现此异象。表现如下图所示:
此时,感觉修复此数据即可解决问题,于是对比正确的数据后,修复数据完成(具体修复方式,如果人遇到,可直接留言交流或者邮件),再次去付款,正常!!!此时想想一条错误数据,竟然能使系统到如此崩溃的地步,也是醉了。
总结:这个问题告诉自己,很多事情并不只是表面上看起的那样,需要更深层次去发掘问题的根源所在。在解决这个问题的过程中,自己也学到了很多东西,对session的理解,查找效率低下的SQL方法,甚至一些很高级的操作系统层report方法。同时,要感谢在这个解决问题的过程中,客户的理解及各位同事的帮助。此文谨以记录此事。
今天财务人员在系统内做批量付款的时候,点击最终完成应用付款的时候,系统一直处于运行状态,但却一直无法完成付款,过几分钟后,直接跳转至如下图所示的界面:
这是第三次出现这样类似的问题,从遇到的情况主要可能有如下两点原因:
1. 表空间不足,特别是临时表空间不足(第一次出现是因为此问题造成)
解决方法:增加表空间,通过脚本查询出需要增加的表空间,增加即可(一般须有DBA执行增加表空间操作),命令如下所示:
select upper(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 1;
2. 锁表,与付款相关的表被锁住(其中两次是此问题造成)
解决方法:通过如下命令查出被锁住的表,最后一个字段即是解锁命令,在COMMAND命令行执行即可,特别是locked_mode为‘6’的在很大程度上是不应该存在的,具体原因请自行网络上搜索。
select dob.object_name table_name,
lo.locked_mode,
lo.session_id,
vss.serial#,
vps.spid,
vss.action action,
vss.osuser osuser,
vss.process ap_pid,
vps.spid db_pid,
'alter system kill session ' || '''' || lo.session_id || ',' ||
vss.serial# || ''';' kill_command
from v$locked_object lo, dba_objects dob, v$session vss, v$process vps
where lo.object_id = dob.object_id
and lo.session_id = vss.sid
and vss.paddr = vps.addr
order by 2, 3, dob.object_name;
最终执行命令如下所示示例:
alter system kill session '38,19020';
alter system kill session '278,3533';
alter system kill session '293,3774';
alter system kill session '1016,64895';
alter system kill session '1054,9699';
alter system kill session '1780,20723';
前段时间做一笔批量付款时候,一直处于已收集付款状态,从锁表、取消的角度去看,都正常。
于是按照图片的顺序操作,解决。
–锁表
select dob.object_name table_name,
lo.locked_mode,
lo.session_id,
vss.serial#,
vps.spid,
vss.action action,
vss.osuser osuser,
vss.process ap_pid,
vps.spid db_pid,
'alter system kill session ' || '''' || lo.session_id || ',' ||
vss.serial# || ''';' kill_command
from v$locked_object lo, dba_objects dob, v$session vss, v$process vps
where lo.object_id = dob.object_id
and lo.session_id = vss.sid
and vss.paddr = vps.addr
order by 2, 3, dob.object_name;