假设
目标 EBS 版本是 Oracle Application R12.1.3
目标 DB 版本是 Oracle Database Enterprise 11.2.0.3
测试机配置 I7-2600K 16G SATA HDD
术语
术语 说明
applprod | UNIX Application 用户 |
oradev | UNIX Oracle Database 用户 |
APPSpwd | 数据库 apps 用户口令 |
APPSuser | apps |
表单元数据的获取
在 FORM 中 帮助=》历史记录 就会弹出一个关于此记录的 FORM 里面写了该 FORM 对应的数据库层视图,我们去看该驶入的定义就能分析出关联了哪些数据,如果显示无可用数据那么尝试改一点关系不大的数据在查看历史记录,抓取到底层试图后,再改回去就可以了,不过后台会记录了本次变更。
并发程序
ORACLE EBS 产品在最初就引入了并发管理器的概念,在用户在 FORM 界面进行了数据的基础录入之后,提交并发请求 在后台异步进行数据的加工以及报表的展现。
本章节基础环境 | R12.1.3 DB 11.2.0.3 PSU8 |
本章节作者 | 虚名 |
并发程序
我们可以在下图中直接看到 程序名称简称以及应用产品,这三个为表现层的东西,其实在并发程序执行阶段都只保存了 application_id 和 concurrent_program_id 分别对应着哪个模块和哪个程序。
优先级 默认为空 底层数值为 50。
启用追踪 是否启用追踪,如果开启会在数据库服务器产生 TRACE 文件保存请求执行过程记录,但是比较费空间。
select fcpt.user_concurrent_program_name, fcp.concurrent_program_name, fat.application_name,
fcpt.description, fe.executable_name, fe.execution_method_code
from applsys.fnd_concurrent_programs fcp , applsys.fnd_concurrent_programs_tl fcpt , applsys.fnd_application_tl fat, applsys.fnd_executables fe
where fcp.application_id=fcpt.application_id and fcp.application_id=fat.application_id
and fcp.concurrent_program_id=fcpt.concurrent_program_id and fcpt.language='ZHS'
and fat.language='ZHS'
and fcp.concurrent_program_name='FNDGAICST' and fcp.application_id=fe.application_id and fcp.executable_id=fe.executable_id
并发程序 可执行
SELECT e.DESCRIPTION, e.EXECUTABLE_NAME, a.APPLICATION_ID, a.APPLICATION_NAME, e.USER_EXECUTABLE_NAME, e.EXECUTION_METHOD_CODE, fa.basepath, E.EXECUTION_FILE_NAME
from FND_EXECUTABLES_VL E, FND_APPLICATION_VL A, FND_APPLICATION fa where E.APPLICATION_ID = A.APPLICATION_ID
and e.APPLICATION_ID = fa.application_id and e.EXECUTABLE_NAME = 'FNDGAICST'
这个 form 里面主要是找并发程序底层执行的那个程序, 此处 basepath 结果是 FND_TOP 对应到应用服务器 就是 $FND_TOP 变量
在执行方法里面显示了底层执行的程序名以及程序类型。常用程序类型有以下几种。
标志 | 类型 | 保存位置 | 备注 |
A | 派生 | $PA_TOP/bin | 不同模块的分别保存在自己的 basepath 下,编译后的文件无法看到内容 |
H | 主机 | $PA_TOP/bin | 直接执行 unix 脚本 |
I | PL/SQL 存储过程 | 数据库内 | 大部分是明文可查看,也有少量核心级别的被加密 |
K | JAVA 并发程序 | 单独讲解 | 单独讲解 |
L | SQLLOADER 程序 | $PA_TOP/bin | 底层是个 apxboav.ctl 文件 格式同 SQLLOADER 的控制文件 |
P | Oracle Reports | $PA_TOP/reports/US | APXXPXPL.rdf 都是这种格式的文件 注意 不同语种的分别保存在不同的目录,例如英文 US 简体中文 ZHS |
Q | SQLPLUS | $PA_TOP/sql | 直接调用 sql 文件 APNLINS.sql |
R | 不常用 | ||
S | 立即 | 不常用 | |
X | 不常用 |
JAVA 并发程序源文件的查找
我们看到了执行文件名和一串执行文件路径 oracle.apps.ap.oie.cc.cp
实际底层对应的目录名是 /R12/PROD/apps/apps_st/comn/java/classes/oracle/apps/ap/oie/cc/cp很长是吧,我们把这一长串分成两部分看待
/R12/PROD/apps/apps_st/comn/java/classes/oracle/apps/ap/oie/cc/cp
下划线部分似曾相识,我们继续拆
oracle/apps/ap/oie/cc/cp
把 “/” 替换成 “.”
oracle.apps.ap.oie.cc.cp
目录这样就对上了,目录里面一堆的.class 文件。
我们找到了 DinersTrx.class 这就对应到了系统里面的执行文件名了。
并发程序 参数
并发请求最多可以传入 20 个参数,请求提交后保存在applsys.fnd_concurrent_requests 表中,但是其中保存的都是 VARCHAR2 类型的字符,但是我们传入的参数有数字有字符有时间等等,都是通过弹性域进行映射,我们本章节只看传入的参数类型。
序号 传入参数的序号,一般从小到大的排列方式,做多传入 20 个变量。
验证 对传入的参数进行验证一般是取值范围的验证,避免非认可变量的传入。此请求的验证为 Yes_No 我们可以在弹性域值集定义里面看到只允许传入 Yes 或者 No
SELECT B.RUNTIME_PROPERTY_FUNCTION, B.APPLICATION_ID, B.DESCRIPTIVE_FLEXFIELD_NAME, B.DESCRIPTIVE_FLEX_CONTEXT_CODE,
B.APPLICATION_COLUMN_NAME, B.END_USER_COLUMN_NAME, B.COLUMN_SEQ_NUM, B.ENABLED_FLAG, B.REQUIRED_FLAG, B.SECURITY_ENABLED_FLAG, B.DISPLAY_FLAG, B.DISPLAY_SIZE, B.MAXIMUM_DESCRIPTION_LEN, B.CONCATENATION_DESCRIPTION_LEN, B.FLEX_VALUE_SET_ID, B.RANGE_CODE, B.DEFAULT_TYPE, B.DEFAULT_VALUE, B.SRW_PARAM, T.FORM_LEFT_PROMPT, T.FORM_ABOVE_PROMPT, T.DESCRIPTION from FND_DESCR_FLEX_COL_USAGE_TL T, FND_DESCR_FLEX_COLUMN_USAGES B WHERE B.APPLICATION_ID = T.APPLICATION_ID and B.DESCRIPTIVE_FLEXFIELD_NAME = T.DESCRIPTIVE_FLEXFIELD_NAME and B.DESCRIPTIVE_FLEX_CONTEXT_CODE = T.DESCRIPTIVE_FLEX_CONTEXT_CODE and B.APPLICATION_COLUMN_NAME = T.APPLICATION_COLUMN_NAME and T.LANGUAGE = userenv('LANG') and t.descriptive_flexfield_name like '%FNDSCMPI%' | ||
我们在这段结果里面找到了 flex_value_set_id=20117 继续追查这个值集的定义 | ||
select * from applsys.fnd_flex_value_sets flvs where flvs.flex_value_set_id=20117 |
并发程序 不兼容
很多程序在运行的时候会对数据库对象进行大量的锁定此时如果有类似操作的请求同事在执行的话,一定会造成比较严重的死锁情况,ORACLE 为了主动避免此类情况的发生,引入了不兼容的定义,此类请求在执行过程中如遇到有不兼容程序在运行,则暂时不运行自身请求,并将自己重新分配到冲突解决管理器队列中进行排队。
我的测试示例里面将 “编译安全性”与 “CP Java 回归测试” 定义了不兼容范围是集类型是域。
范围有两个选项 “集” 和 “程序” 个人理解 集是此条目只在一个请求集中包括这两个请求时才作为不兼容程序,程序则是判断所有在执行的并发请求程序时候有本请求需要进行不兼容判断。
类型,域 只在本冲突域生效 全局 整个系统生效
select fa.application_short_name, fcpt.user_concurrent_program_name, fb.application_short_name, fcpb.user_concurrent_program_name, fcps.running_type, fcps.to_run_type, fcps.incompatibility_type
from FND_CONCURRENT_PROGRAM_SERIAL fcps,
fnd_application fa,
fnd_application fb, applsys.fnd_concurrent_programs_tl fcpt, applsys.fnd_concurrent_programs_tl fcpb
where fcps.running_application_id = fa.application_id
and fcps.running_concurrent_program_id = fcpt.concurrent_program_id and fcps.to_run_application_id = fb.application_id
and fcps.to_run_concurrent_program_id = fcpb.concurrent_program_id and fcpt.language = 'ZHS'
and fcpb.language = 'ZHS'
and fcpt.user_concurrent_program_name = '编译安全性'
写一个并发程序 补充统计数据收集
示例需求 系统有大量的客户化表的统计数据无法被系统的标准请求统计收集到,我们做一个请求作为标准请求的补充。
逻辑分析
排除掉数据库系统用户下的表,并且排除掉 EBS 不建议进行统计数据收集的表,然后我们选上次统计数据收集为 30 天前的表,我们在请求里面会传入三个参数:
周期: 上次统计数据收集时间与当前时间的差
并行度: 开多少个数据库进程进行并行统计数据收集 按照 CPU 数量以及 IO 情况进行分配采样率: 分析对象数据的百分比 100 为 100% 最佳 但是最费时间
select owner, table_name
from dba_tables dt where owner != 'SYS'
and owner != 'SYSTEM' and owner != 'MDSYS' and owner != 'MGDSYS' and owner != 'CTXSYS' and owner != 'ORDSYS' and owner != 'OUTLN' and owner != 'OLAPSYS' and owner != 'ORDDATA' and owner != 'ORDSYS'
and dt.LAST_ANALYZED < sysdate - 30 and table_name not in
(select distinct table_name from applsys.FND_EXCLUDE_TABLE_STATS) select owner, index_name
from dba_indexes di where owner != 'SYS'
and owner != 'SYSTEM' and owner != 'MDSYS' and owner != 'MGDSYS' and owner != 'CTXSYS' and owner != 'ORDSYS' and owner != 'OUTLN' and owner != 'OLAPSYS' and owner != 'ORDDATA' and owner != 'ORDSYS'
and di.LAST_ANALYZED < sysdate - 30 and di.table_name not in
(select distinct table_name from applsys.FND_EXCLUDE_TABLE_STATS)
创建并发执行包
注意! 所有 EBS 包的创建 都要用 APPS 用户登录数据库,默认都是建立在 APPS schema 下。
CREATE OR REPLACE PACKAGE XM_STAT is
procedure main(ERRBUF OUT VARCHAR2,
RETCODE OUT VARCHAR2,
p_age number,
p_degree number,
p_estimate_percent number);
procedure gather_stat(p_age number,
p_degree number, p_estimate_percent number);
end XM_STAT;
/
create or replace package body XM_STAT is
procedure main(ERRBUF OUT VARCHAR2,
RETCODE OUT VARCHAR2,
p_age number,
p_degree number, p_estimate_percent number) is
begin
gather_stat(p_age, p_degree, p_estimate_percent); end main;
procedure gather_stat(p_age in number,
p_degree in number, p_estimate_percent in number) is
p_v1 varchar2(200); p_v2 varchar2(200); p_v3 varchar2(200); p_v4 varchar2(200); Cursor t_list Is
select upper(owner), upper(table_name) from dba_tables dt
where owner != 'SYS' and owner != 'SYSTEM' and owner != 'MDSYS' and owner != 'MGDSYS' and owner != 'CTXSYS' and owner != 'ORDSYS' and owner != 'OUTLN'
and owner != 'OLAPSYS' and owner != 'ORDDATA' and owner != 'ORDSYS'
and dt.LAST_ANALYZED < sysdate - p_age and table_name not in
(select distinct table_name
from applsys.FND_EXCLUDE_TABLE_STATS) order by 1;
Cursor i_list Is
select upper(owner), upper(index_name) from dba_indexes di
where owner != 'SYS' and owner != 'SYSTEM' and owner != 'MDSYS' and owner != 'MGDSYS' and owner != 'CTXSYS' and owner != 'ORDSYS' and owner != 'OUTLN'
and owner != 'OLAPSYS' and owner != 'ORDDATA' and owner != 'ORDSYS'
and di.LAST_ANALYZED < sysdate - p_age and di.table_name not in
(select distinct table_name
from applsys.FND_EXCLUDE_TABLE_STATS) order by 1;
begin
open t_list; loop
fetch t_list
into p_v1, p_v2;
exit when t_list%notfound; dbms_stats.gather_table_stats(ownname
=> p_v1,
tabname => p_v2, estimate_percent => p_estimate_percent,
degree => p_degree);
end loop; close t_list;
-- process index open i_list;
loop
fetch i_list
into p_v1, p_v2;
exit when i_list%notfound; dbms_stats.gather_index_stats(ownname
=> p_v1,
indname => p_v2, estimate_percent => p_estimate_percent,
degree => p_degree);
end loop; close i_list;
-- end process index end gather_stat;
end XM_STAT;
APP 设置
底层执行包
用已经有的包 xm_stat.MAIN
创建并发请求执行系统管理员 职责
并发=〉程序=〉可执行
创建并发请求系统管理员 职责
并发=〉程序=〉定义
配置请求参数
周期 值集使用系统已经预制好的 6 位长度数值 默认类型为常数 默认值为 7 并且此值为必选项
采样率
并行度 要平衡 CPU 数量与存储的 IO 能力,我们这里默认给 4 个,我的机器是四核的。
分配请求到请求组增加到请求组
安全性=〉责任=〉请求
注: 加给 System Administrator Reports 组
提交请求试试看
我们测试一下,提交的时间为 99999 天前的,基本不会有什么表那么久都没有做过统计数据收集,我们只是测试一下程序执行就可以了
跑完了 一切正常。