关于ABAP中锁参数SCOPE的使用bug一粒

本文详细描述了一个在SAP系统中处理批量投料时遇到的程序锁问题。由于在处理过程中锁的释放时机不当,导致了重复投料。作者通过调试发现,设置SCOPE参数为1可以确保锁在整个程序执行过程中保持,从而解决了问题。文章还探讨了V1和V2锁的区别,并提供了相关测试程序和锁对象的使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这2天我们处理了一个关于程序锁的bug,本来还不想写blog,因为并没有完全清楚V1,V2和锁的机制,不过兴伟说写一个,那还是记录一个吧。

场景:

LES系统每天会把现场投入5个车间的生产物料,传给SAP系统。SAP系统收到这些投料数据后,会有程序批量的把它们投料到生产工单上,完成物料在SAP系统中的消耗。

最初在1000工厂,我们开展的整车业务,随后,在1010工厂,我们开展了自制件业务。把整车业务的投料程序拷贝了一份,并对订单类型做了限制,就成了自制件业务的投料程序。

因为这个程序会有几个业务部门的人员同时操作,而每一次批量操作时,调用系统BAPI(系统标准功能)消耗物料(投料)的程序执行有几分钟才能处理完成。为了防止这个程序同时多次去读取了同一份LES的投料数据,然后在SAP系统中重复投料。所以我们给这个程序加了锁。

症状:

在自制件业务的物料投料凭证看,有很多重复投料产生,即一份LES的数据,在SAP系统中被执行了2次,产生了2个物料凭证。从最近的几次重复投料物料凭证时间看,间隔时间大概是2分钟。

即用户1对A物料产生投料凭证,2分钟后用户2又对A物料产生了投料凭证。

原因:

投料程序的逻辑如下:

1、读取LES数据,显示给用户

2、按用户的选择,处理投料数据,先把寄售数据转自有

3、再把物料按订单投料,完成物料消耗

我们在第1步程序中,加锁:

 但程序在第2步中,锁被释放掉了,这并不是我们想要的,因为第3步才是长耗时程序,我们加锁是需要这把锁可以在1、2、3步都锁住数据。经过调试,我们发现在第2步调用系统做411K寄售转自有的BAPI后,锁被释放掉了。

解决:

因为使用了标准的锁功能及函数,默认的SCOPE参数中是给的是2,就是出现上面的问题,当我们使用SCOPE = 1时,这把锁可以锁住数据,在1、2、3程序真正执行完成后才解锁。金圣俊的书上对V1、V2更新及锁也有专门的章节讲解,但其实还是没有讲得很清楚。

 

 目前我能够理解的就是SCOPE = 1是V1锁,是程序层面的锁,程序层面的锁,是整个程序结束后才释放;而SCOPE = 2是V2锁,是针对更新事件的锁。,更新层面的锁是程序中有数据库更新发生后就释放。

--------2022.1.17 后记----------------

今天有时间测试了一下锁的_SCOPE参数,可以总结一下,_SCOPE 遭遇到如下物料BAPI,

BAPI_GOODSMVT_CREATE,BAPI_TRANSACTION_COMMIT的情况如下:

一、SE11创建的对象锁:

如果 _SCOPE = 1,锁不会被释放。

如果 _SCOPE = 2,锁在物料BAPI执行后会自动释放。

二、程序锁 ENQUEUE_ES_PROG:

如果 _SCOPE = 1,锁不会被释放。

如果 _SCOPE = 2,锁在物料BAPI执行后会自动释放。

三、关于说明的翻译:

_SCOPE Controls how the lock is passed to the update program:

Value Meaning

1 The lock is not passed to the update program. The lock is removed when the transaction ends.

2 (default) The lock is passed to the update program. The update program is responsible for removing the lock.

3 The lock is passed to the update program. The lock must be removed in both the interactive(交互) program and in the update program.

_SCOPE控制锁范围的传递:

1、当为1时,锁不能传给更新程序。锁会在程序结束后才移除。

2、当为2时,锁被传递给了更新程序,更新程序会负责移除锁。(有可能移除锁,也有可能不移除锁)

四、测试程序如下,不好找,所以放这里吧:

REPORT ZJAMES_LOCK.


CALL FUNCTION 'ENQUEUE_ES_PROG'
 EXPORTING
   MODE_TRDIR           'E'
   NAME                 'ZJAMES_LOCK'
   X_NAME               ' '
   _SCOPE               '2'
   _WAIT                ' '
   _COLLECT             ' '
 EXCEPTIONS
   FOREIGN_LOCK         1
   SYSTEM_FAILURE       2
   OTHERS               .


IF SY-SUBRC <> 0.
 MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
          
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ENDIF.

DATA:lit_return     LIKE STANDARD TABLE OF bapiret2"bapi return
     lwa_return     TYPE bapiret2"bapi return
     lit_movs       LIKE STANDARD TABLE OF bapi2017_gm_item_create"mat doc item
     lwa_movs       TYPE bapi2017_gm_item_create,  "mat doc item
     lwa_header     LIKE bapi2017_gm_head_01,      "mat doc hdr
     lwa_code       LIKE bapi2017_gm_code,         "mmim code
     lwa_header_ret TYPE bapi2017_gm_head_ret.     "mat hdr return

lwa_code '04'.    "MB1B
lwa_header-pr_uname   sy-uname.
lwa_header-pstng_date sy-datum.
lwa_header-doc_date   sy-datum.

REFRESH:lit_movs.

CLEAR:lwa_movs.
lwa_movs-material '000000000050580071'.
lwa_movs-plant '8800'.
lwa_movs-stge_loc '8813'.
lwa_movs-move_type '311'.
lwa_movs-stck_type ''.
lwa_movs-move_stloc '8814'.
lwa_movs-spec_stock 'E'.
lwa_movs-val_sales_ord '0640003056' .
lwa_movs-val_s_ord_item '000200'.
lwa_movs-entry_qnt 1.
CLEAR:lwa_movs-entry_uom.
APPEND lwa_movs TO lit_movs.

CALL FUNCTION 'BAPI_GOODSMVT_CREATE'
  EXPORTING
    goodsmvt_header lwa_header
    goodsmvt_code   
lwa_code
  
TABLES
    goodsmvt_item   lit_movs[]
    
return          lit_return[].


LOOP AT lit_return INTO lwa_return WHERE type 'E'
                                      OR type 'A'
                                      OR type 'X'.
  write:/ lwa_return-type && ': ' && lwa_return-MESSAGE.
ENDLOOP.


IF sy-subrc 0.
  CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
ELSE.
  CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
    EXPORTING
      wait 'X'.
ENDIF.

五、关于对象锁和程序锁的功能

1、程序锁:

比较好理解,程序开始加一把锁,程序结束后,这把锁自动释放。

2、对象锁:

我们想对更细的数据加锁,比如细到某表中的一行数据,我们可以在SE11中按表的关键字建一个锁对象,然后我们使用这个对象锁时,传入一行主键数据;那么这一行数据就有了锁,如果其它程序也有这个锁对象,也传入了相同的主键,就可以知道前面已经有锁了。

如下面EZ_JAMES_OBJECT这个锁对象,它的主键是GUID,我们对A10001236这行数据加锁。

CALL FUNCTION 'ENQUEUE_EZ_JAMES_OBJECT'
 EXPORTING
   MODE_ZESBTEST        'X'
   MANDT                SY-MANDT
   GUID                 'A10001236'
   X_AUTONUMBER         ' '
   X_GUID               ' '
   _SCOPE               '2'

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘欣的博客

你将成为第一个打赏博主的人!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值