想象你家里有两台洗碗机:第一台负责清洗餐具(UPD1),第二台负责烘干和消毒(UPD2)。当你按下普通启动按钮(COMMIT WORK)时,餐具放进洗碗机后你就可以转身离开做其他事情,这就是典型的异步处理。而当你按下"洗完后提醒我"按钮(COMMIT WORK AND WAIT),就必须站在洗碗机前等到整个流程结束听到"嘀"声才能离开,这就是同步等待。
在ABAP世界里,COMMIT WORK就像那个普通启动按钮。我做过一个采购订单批量创建的报表,连续提交500个订单时,如果每个都同步等待,程序要运行20分钟。改用异步提交后,3分钟就完成了界面交互,后台更新慢慢消化,用户体验直线上升。但这里有个坑:有次我忘记检查SM13事务码里的更新日志,后来发现部分订单因字段长度限制更新失败,导致财务对账时出现差异。
在SAP系统中,更新任务就像装配流水线:
abap复制" 典型UPD1任务示例:物料主数据创建
DATA: ls_mara TYPE mara.
ls_mara-matnr = 'MAT_001'.
ls_mara-mtart = 'FERT'.
INSERT mara FROM ls_mara.
COMMIT WORK. " 触发UPD1更新
每个SAP系统都有类似高速公路收费站的设计:
在ECC6 EHP8系统中实测发现:当并发用户达到300人时,如果大量使用同步提交,SM50里会出现大量等待锁的工作进程。这时就需要像交通管制一样,只在关键业务(如财务过账)使用同步提交。
根据我的踩坑经验,这些情况非用COMMIT WORK AND WAIT不可:
abap复制" 银行转账示例
CALL FUNCTION 'BAPI_ACC_DOCUMENT_POST'
EXPORTING
documentheader = ls_header
TABLES
accountgl = lt_gl
currencyamount = lt_amt
return = lt_return.
READ TABLE lt_return WITH KEY type = 'E'.
IF sy-subrc = 0.
ROLLBACK WORK.
ELSE.
COMMIT WORK AND WAIT. " 必须等待银行返回结果
IF sy-subrc = 0.
CALL FUNCTION 'Z_PRINT_PAYMENT_SLIP'.
ENDIF.
ENDIF.
这些情况用普通COMMIT WORK更合适:
有个取巧的做法:在WebDynpro应用里,可以先用异步提交让界面快速响应,再通过轮询SM13或自定义状态表来检查更新结果。就像外卖APP先显示"商家已接单",后台继续跟踪配送状态。
当SM13出现红色警报时,我常用的排查三板斧:
曾经遇到个诡异案例:UPD2总是凌晨2点失败。后来发现是BW抽取程序与月结作业冲突,通过调整作业计划解决。这类问题如果只用异步提交,可能要等月末对账才会暴露。
ROLLBACK WORK不是万能橡皮擦:
有次我做接口测试时,连续执行了10次带有回滚的测试脚本,自以为很安全。结果发现对方系统还是收到了10条测试数据,原来他们的接口设计是收到请求就立即写入日志库。这提醒我们:跨系统交互要特别设计补偿机制。
通过ST12事务码跟踪发现:
abap复制" 优化的批量提交示例
DATA: lt_data TYPE TABLE OF zorder,
lv_lines TYPE i.
SELECT * INTO TABLE lt_data FROM zorder
WHERE erdat = sy-datum.
lv_lines = lines( lt_data ).
DO lv_lines TIMES.
READ TABLE lt_data INDEX sy-index INTO DATA(ls_data).
" 处理逻辑...
IF sy-index MOD 350 = 0 OR sy-index = lv_lines.
COMMIT WORK. " 每350条提交一次
ENDIF.
ENDDO.
好的更新函数应该像瑞士军刀:
我重构过一个运行要2小时的物料主数据更新函数,通过以下改造降到25分钟: