vlambda博客
学习文章列表

SAP小技巧 通过ENQUEUE_READ读取共享锁所著的资源信息


前言

在一些自定义程序中,开发有时需要考虑多个用户同时处理同一个事务,在处理过程中对资源的占用.

TIPS

SPRING

这里说的资源是业务层面的资源含义:可以是库存数量, 库存可用量数量,信用限额或者科目预算金额等.

处理过程中临时占用资源,处理结束后,通过单据占用. 如果处理事务异常中止,则释放出占用的资源.

为了说明清楚这个场景, 我们虚拟一个业务需求(该业务需求曾经在某个项目上由业务提出)


业务需求说明

科目预算控制:

我们需要为一些重要科目确定一个科目预算金额. 实际创建会计凭证时, 该科目的借方总额不能超过这个预算金额.



业务需求实现方案

业务需求的实现根据预算控制精确度或顾问水准,大致可以分为下面三个方案: 这三个方案各有优劣,需要按具体情况选择使用. 

(方案中的读取BSEG的借方总额,如果是HANA数据库系统,可以直接用SELECT SUM 读取, 性能很好. 如果非HANA数据系统, 需要考虑优化读取方案.使用科目余额表辅助是一个优化的方式.)


01

初级方案:


在会计凭证增强中检查该科目在表BSEG 中的借方总额, 如果超过了配置表中预算的金额. 则报错.

这个方案中没有考虑当前凭证金额和多用户同时创建对总额的影响.


02

中级方案


在会计凭证增强中检查当前会计凭证中科目的借方金额+该科目在表BSEG中的总额, 如果超过了配置表中的预算的金额. 则报错

该方案考虑了当前凭证对总额的影响,但是没有考虑多个用户同时创建凭证的情况.

如果科目限额 1000 , BSEG 中已经创建了900.此时两个用户同时创建金额为60的凭证. 在中级方案中,这两个用户的凭证可能都会创建成功.最终: 科目限额被超过了20. 再次创建凭证则会失败.


03

高级方案


在会计凭证增强中检查当前会计凭证中的科目金额+该科目在表BSEG 中的总额+其它用户正在处理的金额, 如果超过了配置表中的预算金额. 则报错.

这个方案中考虑了所有可能的情况. 理论上不会出现科目限额超出的情况.

但是该方案有个难点就是怎么获取其它用户正在处理的金额.

如果科目限额 1000 , BSEG 中已经创建了900.此时两个用户同时创建金额为60的凭证. 在高级方案中,这两个用户的凭证只有一个能创建成功.


获取其他用户正在处理的金额

加S类型的锁,把公司代码,科目,金额作为锁中的关键字,并用ENQUEUE_READ读取锁内容,是获取其它用户正在处理的金额的最佳方案. 


01

添加结构及锁对象


SAP小技巧 通过ENQUEUE_READ读取共享锁所著的资源信息
SAP小技巧 通过ENQUEUE_READ读取共享锁所著的资源信息


02

获取锁信息


多个用户或进程,可以同时加S类型的锁.加锁信息可以在事务代码SM12中看到

SAP小技巧 通过ENQUEUE_READ读取共享锁所著的资源信息


03

ENQUEUE_READ函数


SM12中的锁信息也可以通过函数

ENQUEUE_READ读取

传入要读取的锁名称

执行后可以获取与SM12中同样的结果.

SAP小技巧 通过ENQUEUE_READ读取共享锁所著的资源信息
SAP小技巧 通过ENQUEUE_READ读取共享锁所著的资源信息


04

解析出结果


传出内表中的字段GARG 串赋值到 ZSHKONT_LOCK 中,可以解析出锁住的科目金额信息


高级方案的详细说明

  • 读取科目预算表配置表,如果存在.继续执行增强. 否则退出增强

  • 读取科目BSEG中的借方总额 ,如果已经超过了配置表中的预算额, 报错.

  • 如果没有超过, 先加S锁,锁住当前凭证的金额 锁的_scope参数使用默认值2(更新成功后解锁)

  • 再读取所有用户锁住的金额. 如果BSEG中的借方总额+锁金额合计>限额.报错.

  • 如果没有超出. 则凭证保存成功后,系统会自动解锁.

这样就可以确保科目借方总额不会超过配置的科目预算金额.


总结

SAP锁实际是一个逻辑锁: SAP在指定的服务器中开放一个内存区域. 

加锁就是在该区域中保存一条记录. 基于锁的类型, 检查该区域中是否存在相同主键的记录.

X 只要存在记录,再次加锁均失败.

E 如果存在记录,并且记录的会话ID与当前加锁的会话ID不一致,则报错. 如果不存在记录,或者会话ID一致,变更加锁次数,返回成功信息

S 不查询记录,直接写入一条新的记录.

借用SAP锁区域,读取S锁的条目并统计其中的数量或金额总额.即可完成读取其他用户占用的资源信息 .

标准可用量占用也使用了类似的逻辑(基于可用量配置确定是否启用锁占用).

锁资源是有限的,一旦锁资源用完,会导致所有需要加锁的应用报错. 实际使用时应避免大量的加锁或者找BASIS增大锁资源的参数.


THE

END

约定

如果你对这篇文章感兴趣,请帮忙点赞,在看,分享.       



          ABAP开发技巧