计划管理器(Planning Manager)技术概要

Posted on May 27, 2010 Filed Under E-Business Suite

计划管理器简介

计划管理器属于Immediate类型的可执行并发程序,作为MRP 管理器的子例程运行。MRP 管理器是一种特殊的并发管理器,和计划管理器是完全不同的存在。它主要作用在以下几个方面:

  1. 针对发运冲减MDS
  2. 针对完工产品冲减MPS
  3. 预测冲减
  4. MRP接口数据的处理
  5. 相关数据清理

实际上,计划管理器和相关的MPS/MRP冲减工作流程是通过下列存储过程完成的:

计划管理器的启动

进入供应链管理员(Supply Chain Planner)职责,在设置菜单里有计划管理器的设置。

间隔时间是指计划管理器每次隔多久处理一次数据,它是指每次的开始时间的间隔长度,如果执行时间超过间隔时间,则执行结束后等待该时间后再次执行。若间隔时间太短,则可以近乎当作不间断执行,这时的冲减也是最及时的,但是系统资源消耗较大。同时,间隔时间过短,日志会更加大,如果启用了DEBUG模式,则每日的日志将可能多出数百兆(视业务数据多少有所不同)。

如果计划管理器处于Active状态,则设置窗口中的Messages界面会显示每次执行的时间。该界面仅仅告知每次的执行时间,并没有多大保留意义,可以安全删除。如果想停止计划管理器,则直接根据请求号取消相应的并发请求即可。需要留意的是,由于计划管理器是依附于MRP管理器执行的,因此在异常诊断时,应当先确认MRP管理器是正常运行的。

每次重新启动计划管理器时,都会自动提交“Planning Manager Worker (once-a-day tasks)”。每天,计划管理器都会分配一个新的请求号,开始新的请求号时,“Planning Manager Worker (once-a-day tasks)”工作流程也会被自动提交。这也是个并发程序(派生类型), 该程序主要执行各类清理工作。其中,对于MRP相关接口表的清理,主要取决于配置文件 MRP:Interface Table History Days 设置的保留天数。涉及的MRP接口表包括:

MDS Relief
创建新的订单时,会有记录插入到MTL_DEMAND,当发运确认后,相关记录会插入MTL_TRANSACTIONS_INTERFACE,接口数据被验证通过才会在MTL_MATERIAL_TRANSACTIONS产生新的纪录,在此同时,如果库存事务管理器判断出所处理的记录是销售订单,就会插入记录到MRP_RELIEF_INTERFACE以供冲减MDS。

在MRP_RELIEF_INTERFACE中的MDS待冲减条目的各字段含义如下:

对于MDS冲减,计划管理器仅仅处理符合以上条件的记录。

MPS Relief
之前介绍过 MPS Relief Worker,这里补充一下MPS冲减的数据来源。

当采购申请、采购订单、接收事务等采购相关数据产生时,会有记录插入到MTL_SUPPLY,这些数据都作为供应用于MPS冲减。当然离散任务的发放、完工时,会有记录插入到WIP_DISCRETE_JOBS,此时也会触发冲减。对于冲减记录的产生,在系统内部实际上是通过Trigger来实现的,大致有以下Trigger:

在MRP_RELIEF_INTERFACE中的MPS待冲减条目的各字段含义如下:

相关的配置文件

MRP:Interface Table History Days 接口数据保留日期,仅删除已完成的记录
MRP:Planning Manager Batch Size 指定每个Worker的处理记录数量
MRP:Planning Manager Max Workers 最大同时启动多少个Worker
MRP:Perform Planning Manager Functions in Loads 让主计划程序执行计划管理器的相关功能
MRP:Consume MDS 启用MDS冲减
MRP:Consume MPS 启用MPS冲减
MRP:Debug Mode 启用诊断模式,会在日志中输出运行过程中的相关信息
MRP:Trace Mode DB级的诊断,Trace文件产生在USER_DUMP_DEST目录下

» Leave a Comment

Planning Manager诊断过程和10046事件

Posted on May 26, 2010 Filed Under Database, E-Business Suite

在一次Planning Manager性能问题的诊断中,用到了Oracle ERP环境中非常典型的诊断操作和过程,特全程记录于此。

当发现某个程序存在性能问题时,首先当然是快速检查一下SESSION的相关信息,看看主要在执行或等待些什么:

SELECT stat.sid,
       n.name,
       n.class,
       stat.value
  FROM v$sesstat  stat,
       v$statname n
 WHERE stat.statistic# = n.statistic#
   AND stat.sid = 121
 ORDER BY upper(n.name);

这里观察到bytes received via SQL*Net from client, bytes sent via SQL*Net to clientSQL*Net roundtrips to/from client 都在飙升。这对应了两个events:SQL*Net message to clientSQL*Net message from client,这两个事件数值大并不意味着网络状况不好,前者仅仅表示Oracle数据库将数据放入TCP send buffer的时间,而后者表示从客户端接收到反馈指令的时间,两者反映了SQL*Net和数据库之间的时间消耗,而不是网络传输的时间消耗。基于对系统架构的了解,排除SQL*Net的性能问题,那么两个事件预示了什么呢?

SELECT * FROM v$sess_io v WHERE v.sid = 61;

观察会话中的数据库读取情况,CONSISTENT_GETS 值在持续增长。结合上面SQL*Net的情况,大致可以判断出该程序在反复执行某个查询语句,每次获取的数据量很小但频率很高。我们知道,客户端在读取数据时,可能影响的因素有Array Fetch Size、SQL*Net中的SDU和数据库服务器每次读取的数据量,简单计算SQL*Net每次传输大致的数据量后将问题定位到SQL的性能问题上。

开始跟踪Planning Manager的全过程。Planning Manager 是一种特殊的并发程序(Immediate),它直接依附于并发管理器MRP Manager执行。但是作为并发请求,它的常规诊断方式是一样的。如果有计划管理器在运行,则先停掉它,然后启用Trace:

关于详细操作和Trace文件的查找可参考另一篇文章《跟踪(Trace)并发请求

进入MRP计划管理员设置界面,启动Planning Manager。对于其他独立的并发请求,可以直接手工提交。等待Planning Manager处理完预先准备的接口数据后,立即取消该请求,并取消Trace。

接下来就是对Trace文件的解读。对于并发请求的Trace,其实就是对应的一次10046事件(event),该事件可简单分为以下四个级别:

手工方式的话可通过下面的命令启用:

alter session set events='10046 trace name context forever, level 8' ;

它和下面的命令类似:

ALTER SESSION SET SQL_TRACE = TRUE

只是前一个命令,可以根据需要指定不同的level,比如此处的level 8,表示跟踪到SQL和等待事件,而不获取绑定变量的数据。也可以通过包DBMS_System来启用,例如:

EXEC DBMS_System.Set_Sql_Trace_In_Session(sid, serial#, true );
EXEC DBMS_System.Set_Ev(sid, serial#, event, level, name);

在某些场合下,针对并发请求的跟踪可能会产生不止一个Trace文件,此时第一个Trace文件中会指明第二个Trace文件标识,如:

PARSE #41:c=0,e=565,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=19728618248238
EXEC #41:c=0,e=781,p=0,cr=0,cu=0,mis=0,r=0,dep=1,og=4,tim=19728618249248
=====================
PARSING IN CURSOR #41 len=54 dep=1 uid=44 oct=42 lid=44 tim=19728618250006 hv=4121095646 ad='f7b931f8'
ALTER SESSION SET TRACEFILE_IDENTIFIER='XZB_CR8909488'
END OF STMT
PARSE #41:c=0,e=249,p=0,cr=0,cu=0,mis=1,r=0,dep=1,og=4,tim=19728618250001

*** TRACE DUMP CONTINUES IN FILE
……/udump/test_ora_14443_XZB_CR8909488.trc ***

先来大致看一下Trace文件中都有些什么。

Dump file ……/udump/test_ora_14443.trc
Oracle9i Enterprise Edition Release 9.2.0.6.0 - 64bit Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.6.0 - Production
ORACLE_HOME = /u08/test/proddb/9.2.0
System name:	SunOS
Node name:	erptest
Release:	5.10
Version:	Generic_118833-03
Machine:	sun4u
Instance name: TEST
Redo thread mounted by this instance: 1
Oracle process number: 59
Unix process pid: 14443, image: oracle@erptest (TNS V1-V3)

这是文件头,显示了相关环境信息。接着往下翻,关键在具体某条SQL的执行情况上,如下:

=====================
PARSING IN CURSOR #75 len=332 dep=0 uid=44 oct=3 lid=44 tim=19728619902280 hv=3581312695 ad='f2b4eb00'
select count(*)  into :b0  from wip_requirement_operations wro ,mtl_system_items items where ((((((wro.inventory_item_id=items.inventory_item_id and wro.organization_id=items.organization_id) and items.bom_item_type=4) and wro.wip_entity_id=:b1) and wro.wip_supply_type=6) and wro.organization_id=:b2) and wro.inventory_item_id=:b3)
END OF STMT
PARSE #75:c=10000,e=2221,p=0,cr=0,cu=0,mis=1,r=0,dep=0,og=0,tim=19728619902273
EXEC #75:c=0,e=2841,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=19728619905363
WAIT #75: nam='db file sequential read' ela= 6392 p1=66 p2=135783 p3=1
……
FETCH #74:c=0,e=1248,p=0,cr=36,cu=0,mis=0,r=0,dep=0,og=4,tim=19728777309437
WAIT #74: nam='SQL*Net message to client' ela= 6 p1=1952673792 p2=1 p3=0
WAIT #74: nam='SQL*Net message from client' ela= 338 p1=1952673792 p2=1 p3=0
EXEC #74:c=0,e=256,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=19728777310344
WAIT #74: nam='SQL*Net message to client' ela= 1 p1=1952673792 p2=1 p3=0
WAIT #74: nam='SQL*Net message from client' ela= 205 p1=1952673792 p2=1 p3=0
EXEC #75:c=0,e=110,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=19728777310795
WAIT #75: nam='SQL*Net message to client' ela= 2 p1=1952673792 p2=1 p3=0
FETCH #75:c=30000,e=26138,p=0,cr=2028,cu=0,mis=0,r=1,dep=0,og=4,tim=19728777336976
WAIT #75: nam='SQL*Net message from client' ela= 278 p1=1952673792 p2=1 p3=0
FETCH #74:c=0,e=749,p=0,cr=36,cu=0,mis=0,r=0,dep=0,og=4,tim=19728777338168
WAIT #74: nam='SQL*Net message to client' ela= 2 p1=1952673792 p2=1 p3=0
WAIT #74: nam='SQL*Net message from client' ela= 304 p1=1952673792 p2=1 p3=0
EXEC #74:c=0,e=112,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=19728777338769
WAIT #74: nam='SQL*Net message to client' ela= 1 p1=1952673792 p2=1 p3=0
WAIT #74: nam='SQL*Net message from client' ela= 227 p1=1952673792 p2=1 p3=0
EXEC #75:c=0,e=272,p=0,cr=0,cu=0,mis=0,r=0,dep=0,og=4,tim=19728777339533
WAIT #75: nam='SQL*Net message to client' ela= 7 p1=1952673792 p2=1 p3=0
FETCH #75:c=30000,e=27212,p=0,cr=2028,cu=0,mis=0,r=1,dep=0,og=4,tim=19728777366810
WAIT #75: nam='SQL*Net message from client' ela= 415 p1=1952673792 p2=1 p3=0
……

这里显示了cursor语句的执行情况,发现编号为#74和#75的语句执行次数非常多,并且间隔执行,每次execute速度很快,fetch消耗时间相对较多,每次读取后立即发送给客户端。(格式的解读参考附注)

由于无法查看源代码,也没有任何技术文档,所以这里,大胆猜测这两个语句在一个LOOP中执行的可能性非常大。Tkprof格式化后,迅速定位最耗时的那个步骤:

select count(*)  into :b0
from
 wip_requirement_operations wro ,mtl_system_items items where
  ((((((wro.inventory_item_id=items.inventory_item_id and wro.organization_id=
  items.organization_id) and items.bom_item_type=4) and wro.wip_entity_id=:b1)
   and wro.wip_supply_type=6) and wro.organization_id=:b2) and
  wro.inventory_item_id=:b3)

call     count       cpu    elapsed       disk      query    current        rows
------- ------  -------- ---------- ---------- ---------- ----------  ----------
Parse        1      0.01       0.00          0          0          0           0
Execute   8890      0.89       0.92          0          0          0           0
Fetch     8890    223.66     231.45       1951   18028921          0        8890
------- ------  -------- ---------- ---------- ---------- ----------  ----------
total    17781    224.56     232.37       1951   18028921          0        8890

Misses in library cache during parse: 1
Optimizer goal: CHOOSE
Parsing user id: 44  

Rows     Row Source Operation
-------  ---------------------------------------------------
   8890  SORT AGGREGATE
      0   NESTED LOOPS
   8890    TABLE ACCESS BY INDEX ROWID MTL_SYSTEM_ITEMS_B
   8890     INDEX UNIQUE SCAN MTL_SYSTEM_ITEMS_B_U1 (object id 18977994)
      0    TABLE ACCESS BY INDEX ROWID WIP_REQUIREMENT_OPERATIONS
61341000     INDEX RANGE SCAN WIP_REQUIREMENT_OPERATIONS_N1 (object id 18977444)

Elapsed times include waiting on following events:
  Event waited on                             Times   Max. Wait  Total Waited
  ----------------------------------------   Waited  ----------  ------------
  db file sequential read                      1951        0.08         11.65
  SQL*Net message to client                    8891        0.00          0.03
  SQL*Net message from client                  8891        0.01          2.82
  latch free                                     19        0.01          0.12

到这里终于确定了主要问题所在,下一步就是对该语句进行优化。由于无法修改代码,因此只能从执行计划角度考虑。检查该语句的执行计划,仔细检查发现虽然利用了索引WIP_REQUIREMENT_OPERATIONS_N1,看上去很漂亮,但是仔细检查索引字段发现这是个组合索引,若走这个索引或导致大量的逻辑块读。到此,整个诊断过程也顺利结束了。

附Trace格式解读:

PARSING IN CURSOR
len	Length of SQL statement.
dep	Recursive depth of the cursor.
uid	Schema user id of parsing user.
oct	Oracle command type.
lid	Privilege user id.
ela	Elapsed time. 8i: in 1/1000th of a second, 9i: 1/1'000'000th of a second
tim	Timestamp.
hv	Hash id.
ad	SQLTEXT address (see?v$sqlarea?and?v$sqltext).

PARSE, EXEC or FETCH
#n	n = number of cursor
c	cpu time
e	elapsed time
p	physical reads
cr	consistant reads
cu	current mode reads
mis	miss in cache
r	rows processed
dep	recursive depth
og	optimizer goal
tim	time

详见 http://www.adp-gmbh.ch/ora/misc/trace_file_format.html

有用的链接:

Update
2010-05-27 其实是可以看到源代码的,下一篇文章会详细阐述。

» Leave a Comment

我们需要监控什么?

Posted on May 24, 2010 Filed Under Database

今天一个很偶然的时间里,我想看看我们的系统有没有异常,其中某个检查点是通过下面这个SQL进行的:

SQL> SELECT local_tran_id,
  2         state,
  3         fail_time
  4    FROM dba_2pc_pending
  5  /

LOCAL_TRAN_ID          STATE            FAIL_TIME
---------------------- ---------------- ---------
31.16.528671           collecting       25-FEB-10

通常情况下,我关注更多地是业务数据异常,很少动手检查此类底层的问题,也不会发现任何异常,但是这次,它来了。当然,在我发现下面这个错误之前,它丝毫不是个问题:

SQL> commit force '31.16.528671';
commit force '31.16.528671'
*
ERROR at line 1:
ORA-02058: no prepared transaction found with ID 31.16.528671

SQL> exec dbms_transaction.purge_lost_db_entry('');
BEGIN dbms_transaction.purge_lost_db_entry(''); END;

*
ERROR at line 1:
ORA-30019: Illegal rollback Segment operation in Automatic Undo mode
ORA-06512: at "SYS.DBMS_TRANSACTION", line 65
ORA-06512: at "SYS.DBMS_TRANSACTION", line 85
ORA-06512: at line 1

一种可能的情况是连接的远程数据库或DBLINK此时不可用,由于最近系统修改比较多,且数据不重要,已经没有追查线索的必要了。解决办法参考Metalink [ID 290405.1]:

1.) alter session set "_smu_debug_mode" = 4;
2.) commit; -- so that the call to DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY is the first
                  -- step of the transaction
3.) execute DBMS_TRANSACTION.PURGE_LOST_DB_ENTRY('local_tran_id');

如果业务数据并不重要,那么解决办法非常简单。这里觉得有点遗憾的是,过去了如此许久才发现问题。基本上,我们的监控处于最原始的手工阶段,这也是为什么我最近评估各类自动化监控系统的主要原因之一。我曾发过一个感叹:

我觉得,如果出一本数据库监控专题的书籍肯定会火,专门介绍如何设置度量和策略,介绍每个监控点。其实这类监控范围,也或许代表了DBA工作职责和经验的体现吧。(via Twitter)

企业的信息化是一个渐进的过程,我们因需求而变化。之前,我们曾经希望有一整套的现成的方案告诉我们如何监控,需要监控什么。但是现在,我基本上可以肯定,每个企业的情况都不相同,寻求一套普适的方案并不值得推荐,因需而定,这才是一个正常的成长过程。

所以我收回之前的Tweet……

Update
1. 将零碎的知识整理成系统性的规范,并进行有序管理,这是当前应该做的事。但是常常独木难支,并且缺少一套有效的知识管理系统来支撑这种渐进的优化。

2. 近日陆续梳理ERP系统的方方面面,发现很多待优化的模块,也发现了很多日常工作中完全可能避免的性能问题。将个人的良好经验形成团队的规范行为,是一个不断积累的过程。尤其的,可以将一些常规项目集成到监控系统中去。

3. 有时候,让功能顾问去解决功能问题可能是个错误的选择,他们更倾向于面对业务问题。纯技术顾问也解决不了,需兼而得之。

……

» 1 Comment

关于10.2.0.5 agent无法连接9i (9.2.0.6)的问题

Posted on May 19, 2010 Filed Under Enterprise Management

升级GC到10.2.0.5后,在给9i(9.2.0.6)数据库配置Agent时,主机监控可以顺利配置,但数据库连接总是无法配置成功。查看agent日志显示:

ERROR vpxoci: ORA-03113: end-of-file on communication channel
WARN  vpxoci: Login 0x27fa600 failed, error=ORA-03113: end-of-file on communication channel

事实上,不论是test connection,还是在服务器上用sqlplus做测试,都是没有问题的。那么,估计会是个agent的程序bug。翻遍Metalink[ID 828464.1]才最终发现这样一个补丁信息:升级RDBMS到9.2.0.8,或者应用agent补丁到10.2.0.5.2

就像选数据库,总是倾向于最新主版本号的上一个版本,因为相对稳定,GC也是如此。Bug不可免,立此存照,以备后用。
Read more

» Leave a Comment

关于RepositoryPatchUpgrade失败

Posted on May 13, 2010 Filed Under Enterprise Management

在打Patch的过程中,最不痛快的就是在过程中出现一些莫名其妙的错误了。今天将OMS版本从10.2.0.2.1升级到10.2.0.5,在进行到Repository Upgrade一步时报错了。

按提示检查cfgtoollogs/configToolFailedCommands文件,有以下内容:

rem 版权所有 (c) 1999, 2009, Oracle。保留所有权利。
oracle.sysman.emcp.oms.RepositoryPatchUpgrade -verbose
oracle.sysman.emcp.oms.OmsPatchUpgrade -configureOms
oracle.sysman.emcp.aggregates.ConfigPlugIn
oracle.sysman.emcp.oms.StartOMS -configureOms
oracle.sysman.emcp.oms.EMCLISetup
oracle.sysman.ccr.configCCR.ConfigCCRPlugIn
oracle.sysman.ccr.configCCR.ConfigRepeaterPlugIn

这部分更新应当是执行一系列SQL出现异常。检查sysman/log目录下的emrepmgr.log.10.2.0.5.0日志,里面最后部分内容是:

SQL> 从 Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production
With the Partitioning, OLAP, Data Mining and Real Application Testing options 断开
[13-05-2010 08:50:23] Checking repository version..
[13-05-2010 08:50:23] Running setSchemaStatus: BEGIN EMD_MAINTENANCE.SET_VERSION('_UPGRADE_','0','0','SYSTEM',EMD_MAINTENANCE.G_STATUS_UPGRADING);END;

[13-05-2010 08:50:23] Could not connect to SYSMAN/(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=127.0.0.1)(PORT=1521)))(CONNECT_DATA=(SID=WEB2))): ORA-01017: invalid username/password; logon denied (DBD ERROR: OCISessionBegin)

这里有个有趣的现象。翻看该日志前面的记录,很多语句都正常执行,并且同样是用SYSMAN用户执行的,但是最后一段出现密码错误的提示显然是该脚本本身输入的密码不正确。

在之前的经验中,确实遭遇到很多关于密码的问题,尤其是大小写不一致的问题。比如有的程序会将密码自动改为小写而导致错误,于是我就习惯将密码控制在小写。而现在,显然遭遇到了相反的情形。

检查参数确定是区分大小写:

SQL> SHOW PARAMETER SEC_CASE_SENSITIVE_LOGON

NAME                                 TYPE                   VALUE
------------------------------------ ---------------------- ------
sec_case_sensitive_logon             boolean                TRUE

这里,SYSMAN的密码是小写的aa,用SYSDBA进入数据库修改SYSMAN密码:

alter user sysman identified by AA;

将密码从原先的小写修改为大写,再retry,顺利通过了。

另外一种办法就是取消大小写敏感的控制,不过,有时候没必要为了一两个特殊应用而修改数据库安全策略。

» Leave a Comment

读书:《构建0racle高可用环境》

Posted on May 9, 2010 Filed Under Review

“未来的DBA,必将都是一个架构师。”

当应用规模达到某个量级后,自然而然的就需要考虑如何扩展,如何保证高可用。DBA对数据库的理解深入后,同时往往也开始了更大的担当,从之前负责数百个在线用户的系统,到负责数千甚至数万在线用户的系统,此时对于某个数据库的管理和优化已经满足不了业务需求了,尤其是数据库的日常管理越来越智能,越来越自动化后,DBA的角色应该升到一个更到的层次。

作为一名ERP顾问,我并没有将所有精力投入到纯粹的数据库领域中,更多的是从应用角度去留意我们的数据库系统运行状态。现在的企业信息化,是以数据库为核心的信息化,当信息化工作从一个公司层面上升到集团层面时,这个核心的瓶颈就暴露在了所有人的面前。我们往往在事后才发现,原来一切的一切,依旧围绕着这个核心在运作

当面临庞大数据的分析,当面临大型数据库(TB级)的效率和安全问题,当面临各类遗留系统的信息整合和功能整合时,架构的调整就摆上了案台。

《构建0racle高可用环境》出来的不晚,不过我却拖到最近才下决心一读,这是一种需求的表示,也是需求的必然。书中并没有过多深入到某些技术专题,而是以一种建造师的角度去看待Oracle数据库系统的设计、部署和管理,很多其实算是一种经验,比如高可用环境下的系统维护。乍看之下好像觉得都没什么名堂,所阐述的技巧和知识平淡无奇,我不都会嘛?但是慢慢品来,发现它并不是为了炫耀什么小技巧,而是通过这些方式来传授一种思路。

这是一种经验的积累和传承。

我很少看国内作者的技术类书籍,缘于不信任,而这种不信任则由于国内IT行业大环境的浮躁。在培养人才方面,无可否认阿里巴巴是个好地方,虽然晚了两年才来读这本书,但这依然证明了作者陈吉平的实力,也证明了阿里巴巴的实力。

今后,我或将花更多的时间在这些值得投入的地方。

有用的链接:

  1. 豆瓣上的介绍
  2. 支付宝冯大辉的书评
  3. 卓越的地址

» Leave a Comment

« go back keep looking »