ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SAP批量程序治理:EX/FX/MB/WB/TB分类与运维实战

SAP批量程序治理:EX/FX/MB/WB/TB分类与运维实战 做SAP这一行不管是ABAP开发还是模块顾问、运维早晚都会被批量程序绊一跤。白天在系统里点几下就跑完的东西放到晚上无人值守的后台第二天早上可能给你留下一屏红色的作业日志——更糟的是日志干净、作业显示已完成但数据是错的。我在几个项目上专门负责过SAP批量程序的梳理和重建静态批量EX、FX和期间批量MB、WB、TB这套命名分类就是在这种反复返工里慢慢成型的一套方法。它的价值不在于字母多好看而在于让你在几十上百个后台作业里一眼就能判断出一件事这个作业到底该不该现在跑跑错了会污染哪个期间的数据。这篇内容会把这套分类背后的逻辑、程序写法、作业调度、监控和踩坑经验完整拆开讲清楚适合刚接手SAP批量运维的同学也适合想把自家作业清单重新规整一遍的老手。1. 批量程序的分类逻辑为什么要在命名上先下功夫SAP系统里的后台作业一旦超过三十个如果没有一套分类规则运维就退化成了看作业名猜它是干嘛的。我在第一个项目上就吃过这个亏一个查询类报表被做成了每日后台作业跑了整整两年没人管直到某天它和一个月结批量作业抢同一个工作进程组把月结窗口往后拖了四十分钟。事后复盘问题根本不在技术而在于没人说得清这个作业属于哪一类、什么时候允许它跑。所以后面再做批量程序治理我第一步永远是分类和命名而不是去优化程序性能。1.1 一次月结卡壳的复盘那次事故很典型。系统里有大约一百二十个后台作业命名五花八门有按开发人员名字缩写命名的有直接叫Z_TEST_01的还有一批是复制别人的作业改的名字都没动。月结那两天我们按作业清单逐个确认状态全靠人肉扫SM37的列表。扫到一半发现有个作业在反复重跑日志显示的是锁对象被占用但没人知道它在等谁。等我顺着SM12的锁记录一路查下去才发现等的是一个前一天就该跑完、但因为数据量大没跑完的日批量作业——而那个作业的名字看起来跟财务月结毫无关系。这次之后我意识到一件事批量作业的分类不能只按业务模块分更要按运行时机分。因为抢占资源、阻塞依赖、污染数据的风险绝大多数都发生在不该跑的时机跑了这个环节上而不是模块归属错了。按运行时机分最粗的两类就是静态批量和期间批量前者跟业务期间无关、按固定节奏触发后者必须跟期间状态严格绑定。1.2 静态批量与期间批量的三条分界线我把这两类的区别总结成三条线实际梳理作业清单时逐条对照就行。对比维度静态批量期间批量触发节奏按固定时间/固定周期和期间开合无关必须等期间准备就绪通常由人工或前置校验触发数据范围当期新增数据通常是滚动窗口整个期间的累计数据可能会全表扫描出错的后果影响效率最多报表延迟影响账务准确性可能污染已结账期间的余额典型失败原因数据量暴涨、锁冲突、程序逻辑缺陷期间未打开、上一步没跑完、数据未齐备允许重跑基本可以随时重跑谨慎重跑部分作业绝对不允许重跑第二条线尤其容易被人忽略。静态批量作业出问题最坏的后果是报表晚出来两个小时业务能理解期间批量作业出问题可能是重复过账、余额翻倍或者把已关账期间的数据又动了一遍这就不是晚两个小时能解决的了。所以这两类在权限、监控频率、执行窗口上的管理策略也应该完全不同。1.3 这套编号体系在实际项目里的落地形态标题里的EX、FX、MB、WB、TB本质上是把这套分类压缩成两位后缀挂在程序名或作业名后面。每个项目的字母定义不一定完全一样但逻辑是共通的第一位字母指向期间属性第二位字母指向执行频率或业务域。我待过的项目里这套后缀是这样落地的EXEvery day eXecution每日执行的静态批量比如日清账、日余额汇总、接口日批次。FXFiXed固定时点执行的静态批量涵盖周频、按工作日、按班次触发的作业。MBMonth Batch月末批量期间批量里体量最大、顺序最讲究的一批。WBWeek Batch周批量在滚动预测或周度结账场景里用得比较多。TBTerm Batch期末收口批量负责余额结转、总账层级的汇总与校验。需要说明的是这套字母不是SAP标准而是项目级的约定属于经验补充的部分不同公司看到同一组字母含义可能完全不同。所以你在自己项目里推行的时候别急着照搬字母先把期间属性 频率这两个维度定下来再挑字母字母本身不重要重要的是任何人看到作业名三秒钟内能判断出它能不能在这个时点跑。2. 静态批量EX和FX把每天都在跑的东西管住静态批量是批量体系里数量最多、也是看起来最无害的一类。正因为无害管理中投入的精力往往最少结果就是它成了最容易积累技术债的地方。我梳理过一个系统光是EX类作业就有六十多个其中十一个其实是重复的四个是两年前临时验证用、后来忘了删的还有三个每天都在跑但没人知道它输出去哪里了。这一节主要讲静态批量怎么分级、怎么调度以及怎么避免它变成没人管的灰色地带。2.1 EX类程序日频执行型批量的典型清单EX类作业的特点是必须和业务日对齐也就是每天的业务数据进来之后需要在下一个业务日开始前处理完。典型的几类接口批处理把外部系统进来的数据做校验、转换、导入。这类作业的失败率最高因为外部数据质量不可控。每日清账与对账把当天的往来明细做匹配、清账、生成差异清单。状态推进类把单据从A状态推到B状态比如发货单批量过账、计划订单批量转生产订单。日报表与快照生成当天数据快照为后续报表提供基线。我通常会把EX类作业的运行窗口卡在夜间具体时点取决于接口到达时间。判断标准很简单这个作业的输入数据最晚什么时候到齐。如果接口数据凌晨两点才全部落地你就别把清账作业排到一点半。我见过太多排得过早导致处理了半份数据的问题日志还显示成功因为程序逻辑里没有做完整性校验。2.2 FX类程序固定时点与特殊频率的批量安排FX类作业没那么日更但同样不跟期间绑定。常见场景是周频、双周频、按工作日比如只在工作日跑、按班次早班结束跑一次晚班结束跑一次。这类作业最容易出事的地方是日期计算逻辑。举个我自己踩过的坑一个FX类作业设置成每周一凌晨执行逻辑里用SY-DATUM往前推7天取数据。看着没问题但遇到法定假日调休、月末和月初跨月的时候取数区间就可能横跨两个会计期间导致一部分数据落在错误的期间里。后来的改法是不用SY-DATUM做隐式推算而是让程序显式接收起止日期参数由作业的变式固定传入或者由前置的日期计算作业生成后传给下游。具体的日期计算逻辑我一般会写成这样把期间和日期的关系显式表达出来 取上一个完整自然周周一至周日的起止日期 DATA: lv_week TYPE scal-week, lv_begda TYPE d, lv_endda TYPE d. 以当前日期反推上一个完整周 CALL FUNCTION DATE_GET_WEEK EXPORTING date sy-datum - 7 IMPORTING week lv_week. CALL FUNCTION WEEK_GET_FIRST_DAY EXPORTING week lv_week IMPORTING date lv_begda. lv_endda lv_begda 6.这段代码本身没问题但生产上我不会把日期计算放在作业程序内部而是拆成一个独立的FX小作业先算出区间并写入一张参数表下游作业从表里读。这样做的理由是日期计算逻辑出问题时你能单独重跑它并检查结果而不用把整个业务处理作业重跑一遍。2.3 静态批量的调度设计变式、依赖、队列与并发静态批量的调度有几条经验都是花时间换来的。第一变式必须固定并且禁止在后台作业里使用动态选择条件。所谓动态就是程序里用了SELECT-OPTIONS但没绑定变式或者绑定了变式但每次执行都重新计算日期。作业一旦跑起来选择屏幕上的值就是定死的任何根据今天日期自动算的逻辑都必须显式写在程序里并打日志。第二控制并发度。后台作业的执行依赖工作进程work process不同类型的进程对话、后台、更新、队列资源是分开的但后台进程数量有限。我见过一次事故一个月初的FX批量作业启动了二十个并行作业把后台进程全部占满导致所有EX作业和更新进程排队整个系统在两个小时里几乎不可用。后来我把并行度控制在后台进程总数的三成以内并且加了一层排队控制。第三作业链用事件触发别用时间差猜。SM36的起始条件里可以设置其他作业之后这个功能非常有用。但要注意它判断的是前置作业结束不判断前置作业是否成功。也就是说前置作业失败了后置作业照样会跑起来拿着一堆残缺数据干活。我的做法是在后置作业程序的开头加一段校验逻辑先检查前置作业在作业日志里有没有异常再决定是否继续。 后置作业启动时先检查前置数据是否齐备 SELECT COUNT(*) FROM zbatch_ctrl WHERE run_date sy-datum AND step_code EX001 AND status S. S 成功 IF sy-subrc 0. MESSAGE 前置批次EX001未成功本作业终止 TYPE E. ENDIF.这段校验看起来很笨但它救过我至少三次。批量程序里最贵的不是性能是错了还不知道。注意静态批量作业的重跑要谨慎尤其是带过账、清账动作的作业。重跑前务必确认前一次执行是否已经产生了业务凭证否则很容易出现重复过账。判断方式是查作业的假脱机列表和程序日志里记录的处理条数而不是只看作业状态。3. 期间批量MB、WB、TB跟着期间状态走的批量期间批量和静态批量的最大区别是它的执行时机不由时钟决定而由期间状态决定。会计期间有没有打开、物料期间有没有推进、上一步骤有没有完成这些条件不满足作业跑了也是白跑甚至更糟。所以这一类作业的设计重点不是调度而是前置校验、执行顺序和幂等性。下面按MB、WB、TB三类展开讲。3.1 MB月末批量的执行顺序与前置校验MB类作业是期间批量里的大头通常包括费用分摊、汇率重估、成本核算、库存价值计算、往来重分类、总账结转等。这些东西有一个共同特点——顺序不能乱。分摊要在成本核算之前成本核算要在库存计价之后期末结转要在所有计提完成之后。我在项目里会把MB类作业编号化比如MB010、MB020、MB030编号间隔留十个方便中间插入新步骤。每个作业都配一张控制表记录它依赖哪些前置步骤。程序的第一个动作永远是查控制表前置没完成就直接退出并写日志而不是硬着头皮往下跑。 MB类作业的通用前置校验框架 DATA: lt_pre TYPE TABLE OF zbatch_dep, ls_pre TYPE zbatch_dep. SELECT * INTO TABLE lt_pre FROM zbatch_dep WHERE step_code MB030. 当前步骤 LOOP AT lt_pre INTO ls_pre. SELECT SINGLE status INTO DATA(lv_st) FROM zbatch_ctrl WHERE run_period p_period AND step_code ls_pre-pre_step. IF lv_st S. MESSAGE |前置步骤 { ls_pre-pre_step } 未成功MB030终止| TYPE E. ENDIF. ENDLOOP.这套框架投入不大但收益非常高。它把作业顺序从某个人的记忆里变成了系统里可查、可校验的配置。注意月结类作业执行前必须确认会计期间和物料期间都已正确打开且上一个期间已经关闭。期间状态没准备好就执行轻则作业报错重则数据写进错误的期间后续调整成本极高。前置校验里一定要把期间检查加进去别依赖人工确认。3.2 WB周批量与滚动结账的折中方案WB类作业在一些做滚动预测、周度管理报表的项目里会出现。它的定位比较微妙比EX重、比MB轻处理的是以周为单位聚合的数据比如周度成本归集、周度产能分析、周度资金预测。设计WB类作业时最容易犯的错误是把它当成缩小版的月结来写。我见过有人直接复制月结程序改了个日期区间结果周批量的数据口径和月结完全不一致同一张报表在周中和月末给出的数字对不上业务方直接失去信任。我的做法是让WB和MB共用同一套底层取数逻辑只是通过参数控制区间和聚合粒度保证口径一致 同一取数逻辑通过粒度参数区分周/月 CASE p_granularity. WHEN W. 周粒度 lv_begda p_week_begda. lv_endda p_week_endda. WHEN M. 月粒度 lv_begda p_month_begda. lv_endda p_month_endda. ENDCASE.共用逻辑还有个额外好处一旦发现口径有问题改一处就够不用担心改漏。另外WB类作业的执行时点也要卡准。周批量通常在周末业务量最低的时候跑但如果公司有周末排班就不能想当然地认为周末没有业务数据。判断依据应该是业务系统里周末的实际单据量而不是组织架构上的工作日历。3.3 TB期末总账类批量的收口作用TB类作业是我认为最需要严格管控的一类因为它处理的是收口的工作余额结转、总账层级汇总、期末数据归档、期间关闭前的最终校验。这类作业通常一个月只跑一次出问题也最难发现因为跑完之后很可能就关账了错误数据会被封在期间里。我在这类作业上坚持三个原则。第一个原则先校验后执行校验不过不执行。TB类作业在正式写入数据之前必须做一轮全量校验比如借贷是否平衡、明细汇总是否等于总账、外币折算是否一致。校验结果写进日志和控制表人工确认后再执行正式步骤。有的项目会把这两步拆成两个作业人工在中间确认虽然麻烦但可靠。第二个原则执行前打快照。哪怕只是把关键表的汇总数写进一张自定义表成本也很低但一旦出错它就是唯一的对照依据。我遇到过总账汇总数对不上的情况就是因为有快照才在半小时内定位到是某个分摊步骤重复执行了两次。第三个原则短期禁止重跑长期必须能重跑。听起来矛盾其实不然。期末作业跑完之后立即重跑风险极高因为很多步骤是追加写而不是覆盖写。但过了一段时间、确认结果有误需要修正时又必须能安全重跑。解法是给每个TB作业设计一个清理-重算配对程序正式作业负责写入清理程序负责按批次号删除上一次的结果两者成对使用。作业名 程序名 说明 ZBAT_TB010 ZFI_TB_CLR_010 清理上一批次结果 ZBAT_TB011 ZFI_TB_RUN_010 正式执行写入批次号 ZBAT_TB012 ZFI_TB_CHK_010 结果校验这套清理-执行-校验三段式用起来比单一大作业麻烦但每次出问题的时候都会庆幸自己当初多写了两个程序。4. 实操从程序编写到作业创建的全流程前面讲的是分类和设计这一节讲落地动作。完整流程分成程序侧和作业侧两块程序侧决定作业跑得对不对作业侧决定作业跑不跑得起来。两边都做扎实批量作业才算真正可运维。4.1 程序侧选择屏幕、变式与批处理日志设计后台作业的执行本质上是带着一组固定参数调用程序。所以程序的选择屏幕设计直接决定了作业的可控性。我的做法是选择屏幕上的参数分两组一组是业务参数一组是执行控制参数。业务参数公司代码、期间、范围由变式固定执行控制参数测试模式、并行度、日志级别、批次号单独放在一个块里方便运维临时调整。SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001. PARAMETERS: p_bukrs TYPE bukrs OBLIGATORY, p_gjahr TYPE gjahr OBLIGATORY, p_period TYPE monat OBLIGATORY. SELECT-OPTIONS: s_belnr FOR bkpf-belnr. SELECTION-SCREEN END OF BLOCK b1. SELECTION-SCREEN BEGIN OF BLOCK b2 WITH FRAME TITLE TEXT-002. PARAMETERS: p_test AS CHECKBOX DEFAULT X, 测试模式 p_paral TYPE i DEFAULT 3, 并行度 p_loglv TYPE c DEFAULT 2, 日志级别 p_batch TYPE c LENGTH 20. 批次号 SELECTION-SCREEN END OF BLOCK b2.然后批处理日志是标配不是加分项。程序在后台跑没有人盯着屏幕所有关键信息只能靠日志。我一般会记录四类信息处理条数、成功条数、失败条数、失败明细最多记N条。日志既写进应用日志SLG1也写进自定义控制表前者方便查后者方便下游作业判断。 写应用日志 CALL FUNCTION BAL_LOG_CREATE EXPORTING i_s_log ls_log_header IMPORTING e_s_log ls_log_header. CALL FUNCTION BAL_LOG_MSG_ADD EXPORTING i_s_msg ls_msg. CALL FUNCTION BAL_DB_SAVE EXPORTING i_t_log_handle lt_handle.注意后台作业里千万不要用MESSAGE ... TYPE I或TYPE S作为流程控制更不要用断点调试的思路去写。后台环境下非错误类消息可能被静默吞掉你看到的就是作业成功但什么都没发生。所有分支判断都用显式变量和日志记录。4.2 作业侧SM36/SM37 创建、变式绑定与周期设置作业创建走SM36这个大家都熟但有几个细节占了日常故障的大头。第一作业类和目标服务器。作业类决定了优先级A类最高、C类最低。我的经验是EX和FX类静态批量用C类MB、TB类期间批量用B类只有极少数必须抢占时间的作业才用A类。理由是A类作业会抢占资源用多了反而拖慢整体。目标服务器如果不指定作业会由系统自动分配如果明确某台应用服务器负载较低可以指定过去。第二起始条件。立即执行、指定日期时间、操作模式切换后、其他作业之后、事件触发五种方式。日频作业我用指定日期时间 周期月频作业我用事件触发因为月结启动时间不固定用固定时间很容易跑早了。第三周期设置。日、周、月都有但要特别注意月周期是按每月同一天算的如果起始日设成31号遇到没有31号的月份执行行为和你预期可能不一致。我的处理方式是把所有月频作业的起始日设在1到28号之间避开这个坑。第四变式的绑定。这一步最容易出问题。变式是在SE38里建好、保存、然后在SM36里选择。要点有三个变式必须在同一个客户端下创建变式的属性里仅显示和保护要按需勾选防止被误改变式支持通过传输请求搬运但必须在SE38的变式菜单里选择传输直接传输程序是带不走变式的。配置项静态批量EX/FX推荐值期间批量MB/WB/TB推荐值作业类CB起始条件指定日期时间 周期事件触发或人工启动起始日任意1至28日之间变式保护勾选保护勾选保护且限制修改权限目标服务器自动分配指定低负载服务器重跑策略自由重跑需走清理程序4.3 依赖编排前置作业、事件触发与作业链作业之间的依赖靠两种方式实现作业起始条件里的其他作业之后以及SAP的事件机制。前者简单直观适合一对一的线性依赖后者灵活适合一对多、多对一以及跨系统的场景。我比较偏向后者的原因是一个很实际的问题其他作业之后不判断成功状态。前面提过一次这里再说细一点。假设A作业跑完无论成功失败B作业都会启动。如果A失败了B会拿着半份数据继续跑然后B也可能成功数据就被污染了。所以用这种方式串联作业时后置作业必须自带校验。事件机制相对好一些因为事件是程序显式抛出的你可以在A作业成功结束时抛事件失败时抛另一个事件B作业只监听成功事件。抛事件的代码很简单 作业成功结束时抛出事件 CALL FUNCTION BP_EVENT_RAISE EXPORTING eventid ZEV_MB020_DONE EXCEPTIONS bad_eventid 1 eventid_does_not_exist 2 eventid_locked 3 OTHERS 4.然后在SM36里把B作业的起始条件设置成事件后填入ZEV_MB020_DONE。这套做法的前提是事件必须在SM62里预先定义并且传输到所有相关系统忘了这一步事件抛不出去下游作业就永远等着。4.4 监控SM37、作业日志与运行时长基线监控不是每天早上打开SM37扫一遍就完事。我建议做三件事。第一建立运行时长基线。每个作业正常运行多久记录下来形成基线。一旦某个作业的运行时间是基线的两倍以上就该查原因了——通常是数据量暴涨或者索引失效。这个基线不需要工具一张自定义表加一个统计作业就能做。第二区分作业完成和业务成功。SM37里的已完成只代表程序跑完了不代表结果正确。必须点进作业日志看有没有红色警告。我给团队定过一个规矩任何在日志里出现错误消息的作业无论状态如何都按失败处理。第三把作业日志聚合起来。SM37逐个作业点开看作业多了效率极低。更好的方式是依赖程序的标准化日志——所有批量程序统一把结果写进一张控制表然后做一个监控报表一屏看完所有作业的执行状态、处理条数、耗时。这个报表本身就是个EX类作业每天早上跑一遍。5. 常见问题与排查实录批量作业的故障排查难点不在技术而在信息分散。作业状态在SM37、日志在SLG1或假脱机、锁在SM12、数据在业务表里四处找一遍半小时就过去了。这一节我把高频问题整理成速查表并说明排查思路。5.1 作业假成功日志警告被忽略这是最坑的一类问题。作业状态是已完成日志里有一行黄色或红色消息但没人看。第二天业务反馈数据不对回头再查才发现问题出在前一天晚上。典型场景包括主体逻辑处理成功但收尾的更新提交失败程序里用了CALL FUNCTION ... EXCEPTIONS异常被捕获但只写了一条日志批量处理中部分记录失败程序继续往下跑并正常结束。排查方法很直接看日志而不是看状态。程序侧则要保证所有异常路径都会写日志且日志级别足够高。我通常会在程序结尾加一段汇总输出把处理总数、成功数、失败数都打出来只要失败数不为零日志里就有一条明确的红色消息。5.2 变式被改或丢失导致跑错数据这个问题在多人协作的项目里特别常见。某天某个作业突然处理了全公司的数据一查变式里公司代码被清空了。原因可能是有人为了测试手动改了变式忘了改回去或者变式被程序改动覆盖了。防护手段有三个给生产环境的变式勾选保护属性限制变式的修改权限只给少数几个人给关键作业加一层校验如果传入的参数为空或范围异常直接报错退出。 参数合理性校验 IF p_bukrs IS INITIAL OR p_gjahr IS INITIAL OR p_period IS INITIAL. MESSAGE 关键参数为空作业终止 TYPE E. ENDIF. 期间范围校验 IF p_period 01 OR p_period 16. MESSAGE 期间取值不合法作业终止 TYPE E. ENDIF.注意很多项目会忽略期间取值的上界校验。SAP的特别期间13到16期在部分模块是启用的如果程序里没有预先处理月末批量传入特别期间时行为可能完全出乎意料。要么明确支持要么明确拒绝。5.3 期间未开、锁对象冲突导致的失败期间未开导致的失败表现通常是作业报错期间未打开或者干脆静默跳过。排查时先看OB52的会计期间状态和MMPV的物料期间状态再看程序里有没有做期间校验。如果是标准的过账类程序SAP会自己报错如果是自定义程序就要自己加校验。锁对象冲突的表现是作业卡住不动或者报对象已被锁定。排查思路是查SM12看是哪个用户、哪个事务锁住了对象然后查对应作业的状态。预防方法是在批量的时间段内避免让操作人员在同一批数据上做在线操作这一点需要在流程上约定光靠技术手段很难彻底解决。有一类锁的问题容易被误判作业本身没有冲突但它调用的某个函数在内部加了排他锁而这个锁在当前会话里没有释放。排查时要注意作业日志里的详细消息以及SM12里的锁所有者是不是作业本身。5.4 常见问题速查表现象可能原因排查动作处置方式作业状态成功但数据不对日志有警告被忽略查作业日志和假脱机列表修正程序逻辑强制异常写日志作业卡住不结束锁冲突或死循环SM12查锁、SM50查进程释放锁、终止作业并排错作业报错期间未打开会计/物料期间未推进OB52、MMPV检查期间状态推进期间后重跑注意数据影响后置作业拿到残缺数据前置作业失败但后置照跑检查前置作业日志后置作业增加前置成功校验作业运行时间突然翻倍数据量暴涨或索引失效对比历史运行时长优化SQL、补充索引、拆分批次变式参数为空导致全量处理变式被误改或传输丢失SE38检查变式内容勾选保护属性、限制权限、加参数校验并行作业占满后台进程并行度设置过高SM50查看进程占用降低并行度控制在总数三成以内事件触发作业不启动事件未定义或未传输SM62检查事件定义补齐事件定义并传输6. 我在批量程序治理上的一些个人做法前面讲的都是体系和方法最后聊几个具体的做法都是被现实教育出来的。第一给每个批量程序写作业说明书。不是给开发看的是给运维看的。内容就五条这个作业什么时候跑、跑之前要确认什么、跑多久算正常、失败之后怎么办、能不能重跑。这份文档放在作业清单旁边比任何技术文档都管用。我在一个项目上推行之后夜间值班的响应时间从平均四十分钟降到十分钟以内。第二把作业清单纳入版本管理。作业本身不能直接传输但作业清单可以。我把所有作业的定义作业名、程序名、变式名、起始条件、周期维护成一张Excel或一个文本文件跟着代码库一起管理。每次新增、修改、删除作业都要更新这个清单。这样做的收益在换人、交接、系统迁移的时候体现得最明显。第三作业的创建尽量程序化。手工在SM36里建作业一次两次没问题几十上百个就容易漏、容易填错。我习惯用一段程序化的方式批量创建作业核心是三个函数 打开作业 CALL FUNCTION JOB_OPEN EXPORTING jobname lv_jobname IMPORTING jobcount lv_jobcount EXCEPTIONS cant_create_job 1 invalid_job_data 2 jobname_missing 3 OTHERS 4. 提交作业步骤 CALL FUNCTION JOB_SUBMIT EXPORTING jobcount lv_jobcount report lv_report variant lv_variant EXCEPTIONS bad_priparams 1 bad_priparams 2 bad_priparams 3 OTHERS 4. 关闭作业设置起始条件 CALL FUNCTION JOB_CLOSE EXPORTING jobcount lv_jobcount strtimmed X EXCEPTIONS cant_start_immediate 1 invalid_startdate 2 jobname_missing 3 job_close_failed 4 OTHERS 5.这段代码在实际项目里非常实用尤其是在新系统上线、需要批量重建作业的时候。用它创建的作业和SM36里手工建的一模一样可以在SM37里正常查看和管理。第四关于作业数量我的建议是能合并就合并但不要为了少而强行合并。我见过有人把十几个不相关的逻辑塞进一个作业理由是少建几个作业清爽。结果是每次运行都要跑完整套逻辑出问题也不好定位。合理的粒度是同一业务目的、同一数据范围、可以一起重跑的逻辑放在一个作业里跨越不同业务域、重跑策略不同的就不要合并。第五定期清理。每季度过一遍作业清单把已经没人看的作业停掉、把重复的合并、把临时的删除。这件事听起来很简单但坚持做的项目不多而坚持做的项目批量体系一般都很健康。最后分享一个小技巧。判断一个批量作业是否真的在发挥作用最简单的方法是看它的输出有没有人消费。如果作业生成的报表没人下载、写入的表没人查询、抛出的文件没人取走那这个作业大概率已经可以退休了。批量程序的技术债不像代码那么显眼它就是靠这种方式一点一点积累起来的也靠这种方式一点一点清理掉。
返回列表