调用加锁解锁函数时应注意的一点儿

文摘   2024-11-14 05:30   上海  

ABAP 锁与数据库锁的全面解析


2234192 - 锁定应用程序启动的增强


https://www.cnblogs.com/jiangzhengjun/p/4293533.html

写家文章就只用DEQUEUE_ALL,那个只是事例。

真实业务场景还是谨慎点,不推荐直接DEQUEUE_ALL



调用锁函数时,有个参数应该注意:


输入参数“_SCOPE”,输入数值为0,1,2。默认是2.


其中2为,事务提交时自动解锁,


为1显示调用解锁函数才解锁。


这个很重要,许多没有被锁的情况是由于事务自动提交(比如程序结束,提交事物commit等)



如果程序比较大,


建议使用1模式,因为调用commit work后,(获取其他的隐式提交),锁会自动释放掉。可能影响数据的正确性



还有,如果调用   DEQUEUE_ALL 来释放锁,虽然写起来省事儿,


但是会把你当前会话里所有的锁释放,


所以如果你调用了别人的程序或函数,或者调用了标准的东西,


不建议使用 DEQUEUE_ALL…… 





SAP 系统中设置锁至关重要。

首先,保持数据的一致性是关键原因之一。在多个用户要访问同样资源的情况下,比如航班预订系统中检查空座位数量时,不希望在检查过程中该重要数据被别人修改,此时 SAP 锁就起到了同步访问、保持数据一致性的作用。

数据库管理系统虽然会物理锁定要修改的行记录,但在 SAP 系统中存在一些特殊情况使得仅靠数据库锁不够。例如,当一个新屏幕显示时,会触发隐式的 DBCOMMIT,释放掉 Database 锁。如果数据是从好几个屏幕收集而来,且在这段时间内数据会分别被锁定,那么仅用 Database 锁就无法满足需求。SAP 系统在应用服务器层面有一个全局的 LOCKTABLE,可以设置逻辑锁来锁定相关的表条目,并有 ENQUEUE 工作进程来管理这些锁。SAP 锁是一种逻辑意义上的锁,有可能锁定的表条目在 DATABASE 上根本不存在。

综上所述,SAP 锁在确保数据完整性和一致性、有效管理并发访问方面发挥着重要作用。

二、锁对象与相关功能模块

(一)锁对象的特性

在 SAP 中,自定义的锁对象都必须以 EZ 或者 EY 开头来命名。一个锁对象里只包含一个 PRIMARY TABLE,可以包含若干个 SECONDARY TABLE。锁的模式主要有三种:E、S、X。

  • 模式 E:当更改数据的时候设置为此模式,只允许一个用户访问表,对其他程序的独占锁及共享锁不起作用。

  • 模式 S:本身不需要更改数据,但是希望显示的数据不被别人更改。多个用户可以同时读取数据,但倘若有个用户在修改数据,则其他就无法再访问数据了。

  • 模式 X:和 E 类似,但是不允许累加,完全独占,独占锁可以在多个不同事务码内申请解锁,但在相应事务码中只能申请一次,此外不接受其他任何锁申请。

当激活锁对象的时候,系统会自动创建两个函数,分别是 ENQUEUE_<锁对象名> 和 DEQUEUE_< 锁对象名 >,用于锁定和解锁。

(二)加锁参数详解

加锁函数中有多个重要参数:

  • 模式参数(MODE_):定义了锁对象里每个基础表的锁模式,可用值包括 S(共享)、E(排他)、X(排他但不累积)。在锁对象中创建表时指定的锁模式就是这个参数的缺省值,但在函数模块被调用时可以覆盖该缺省值。

  • 范围参数(_SCOPE):控制了锁或者锁释放如果被传递给更新程序。_SCOPE = 1 时,锁和锁释放不传递给更新程序,当事务结束时锁被移除;_SCOPE = 2 时,锁或锁释放传递给更新程序,更新程序负责移除锁;_SCOPE = 3 时,锁或锁释放也传递给更新程序,锁必须从交互式程序和更新程序中同时移除。

  • 等待参数(_WAIT):决定了当锁被限制时的行为。初始值时,如果锁尝试由于一个冲突锁而失败了,就会触发 FOREIGN_LOCK 的异常;设置为 X 时,如果锁尝试由于一个冲突锁而失败了,锁尝试会等待一段时间后再试,只有在首次锁尝试过后一定时间后才会触发 FOREIGN_LOCK 异常。

  • 收集参数(_COLLECT):控制了锁请求或锁释放应该是直接执行还是应该先被写入本地锁容器。初始值时,锁请求或锁释放被直接发送给锁服务器;设置为 X 时,锁请求或锁释放被放在本地锁容器中,收集在这个锁容器中的锁请求和锁释放可以在以后调用函数模块 FLUSH_ENQUEUE 时成组的发送给锁服务器。

(三)解锁方式与注意点

解锁的方法主要有两种:手动释放和自动解锁。手动释放可以通过调用解锁函数 DEQUEUE 来实现,在程序结束时,可以使用 DEQUEUE FUNCTION MODULE 来解锁,系统会自动从 LOCK TABLE 把相应的记录删除,且不会产生 EXCEPTION。自动解锁的情况有多种,比如程序结束发生的时候(MESSAGE TYPE 为 A 或者 X 的时候),使用语句 LEAVE PROGRAM,LEAVE TO TRANSACTION,或者在命令行输入 “/n” 回车以后,程序结束时也会自动解锁。使用解锁函数时需要注意,解锁的调用必须与加锁时的参数 MODE_保持相同的值,否则可能无法正确解锁。另外,如果调用 DEQUEUE_ALL 来释放锁,虽然写起来省事儿,但是会把当前会话里所有的锁释放,所以如果调用了别人的程序或函数,或者调用了标准的东西,不建议使用 DEQUEUE_ALL。

三、上锁的一般步骤

在 SAP 实际业务中,上锁的一般步骤包括先上锁,上锁成功之后,从数据库取数据,然后更改数据,接着更新到数据库,最后解锁。这个步骤对于保证数据安全至关重要。

首先,先上锁可以确保在进行后续操作时,数据不会被其他用户或进程意外修改。例如,在一个复杂的业务场景中,多个用户可能同时对同一组数据进行操作。如果没有先上锁,就可能出现数据不一致的情况。比如在库存管理系统中,两个用户同时对同一批货物的库存数量进行修改,一个用户增加库存,另一个用户减少库存,如果没有上锁机制,最终的库存数量可能会出现错误。

上锁成功后,从数据库取数据。这个步骤确保了获取的数据是在锁定状态下的,不会在读取过程中被其他用户修改。以销售订单管理系统为例,当一个用户在处理一个销售订单时,先对该订单进行上锁,然后从数据库中读取订单的详细信息。这样可以保证在处理订单的过程中,订单的信息不会被其他用户修改,从而确保了数据的准确性。

接着,更改数据。在这个阶段,用户可以根据业务需求对数据进行修改。由于数据已经被上锁,其他用户无法同时对该数据进行修改,从而避免了数据冲突。例如,在员工信息管理系统中,当一个管理员在修改一个员工的信息时,其他管理员无法同时对该员工的信息进行修改,确保了数据的一致性。

然后,更新到数据库。将修改后的数据更新到数据库中,确保数据的最新状态被保存下来。在财务报表生成系统中,当一个用户对财务数据进行修改后,需要将更新后的数据及时更新到数据库中,以便其他用户能够获取到最新的财务信息。

最后,解锁。解锁操作可以释放对数据的锁定,让其他用户可以对该数据进行操作。如果不及时解锁,可能会导致其他用户无法访问该数据,从而影响业务的正常进行。例如,在项目管理系统中,当一个项目经理完成对一个项目的修改后,需要及时解锁该项目,以便其他项目成员能够继续对该项目进行操作。

总之,按照先上锁,再取数据、更改数据、更新数据库,最后解锁的步骤进行操作,可以保证更改完全运行在锁的保护机制下,确保数据的安全性和一致性。

四、实际业务中的问题与解决方案

在实际项目中,经常会遇到一些问题,其中数据重复处理问题就是一个比较常见的情况。以一个具体的项目为例,在接口较多的情况下,通过接口接收数据后做一个 ALV 程序来执行数据处理。然而,在程序执行时,数据还没处理完,另一个同事又打开了这个程序,导致同一个单据可能会被处理两次。

为了解决这个问题,团队决定给程序执行的时候增加锁对象。最初的设计是在 ALV 界面上,当用户在 ALV 上的复选框中勾选的时候,触发 DATA_CHANGE 事件,然后触发锁定函数,自动上锁,用户取消勾选的时候,再触发解锁函数,解锁当前行。当第一个用户勾选的时候,加上锁,此时第二个用户再想要勾选,则会报错。

但是,这个方案又暴露出了另外一个问题。由于程序会循环调用 MIGO 进行过账,过账之后要调用 BAPI:BAPI_TRANSACTION_COMMIT 或者 BAPI_TRANSACTION_ROLLBACK 进行提交数据或回滚,当第一个需要过账的单子过完帐之后,提交或者回滚数据的时候,会有 CALL FUNCTION 'BUFFER_REFRESH_ALL,会导致程序在 ALV 界面上加的全部锁对象都释放,另一个用户此时就可以勾选,这样还是会导致凭证重复生成。

针对这个问题,团队找到了两个替代方案:

一、把过账部分的程序另外 COPY 出来,做一个过账处理程序

原来程序走到过账的时候,通过 SUBMIT 或者 CALL TRANSCATION 的方式,调用过账处理程序。这样的话,即可有效避免由于数据提交导致的锁对象失效的问题。不过,这个方案的缺点在于,有的时候,需要得到过账的返回结果在取数的那个程序上显示出来,但是通过此方法得不到过账的结果。具体代码没有写,有兴趣的同学可以测试。

二、在用户在调用 BAPI 进行过账之前,锁定数据

此时需要注意的是,需要在之前增加校验逻辑,判断当前单据是否已经过账,如果已经过账,则直接返回过账结果,如果没有过账,则锁定单据,并且过账,等调用完 BAPI 之后,等待自动解锁。此方案的问题是,会有效率上的问题需要处理。目前采用了第二个解决方案。

欢迎各位大神给出新的思路,能彻底解决这个问题。

五、总结与展望

SAP 锁在实际业务中发挥着至关重要的作用。它通过有效的并发控制机制,确保了在多个用户同时访问相同数据时,数据的完整性和一致性得到保护。无论是在库存管理、销售订单管理、员工信息管理还是财务报表生成等系统中,SAP 锁都为数据的准确性和安全性提供了坚实的保障。

在实际业务中,我们了解到了 SAP 锁的多种模式,如模式 E、S、X,不同的模式适用于不同的业务场景,能够满足各种数据访问需求。同时,加锁函数中的多个参数,如模式参数、范围参数、等待参数和收集参数等,为我们提供了更加灵活的锁控制方式。

上锁的一般步骤,即先上锁、取数据、更改数据、更新数据库、最后解锁,是保证数据安全的重要流程。这个步骤确保了数据在整个处理过程中都处于锁定状态,避免了数据被意外修改。

然而,SAP 锁也并非完美无缺。在实际业务中,我们遇到了数据重复处理等问题,虽然通过增加锁对象和采用替代方案等方式解决了部分问题,但仍然存在一些效率问题和局限性。例如,在采用第二个解决方案时,虽然能够避免凭证重复生成,但会有效率上的问题需要处理。

展望未来,我们期待有更好的解决方案来解决 SAP 锁在实际业务中存在的问题。随着技术的不断发展,可能会出现更加智能、高效的锁机制,能够更好地满足复杂业务场景下的数据一致性需求。同时,也希望在 SAP 系统的不断升级和改进中,能够进一步优化锁的性能和管理方式,为用户提供更加稳定、可靠的数据处理环境。

总之,SAP 锁在实际业务中具有重要的作用,但也需要我们不断地探索和改进,以适应不断变化的业务需求和技术发展。

是老周,如果你喜欢我的文字,请记得点击⬇️关注我。


码字不易,文章下拉,右边点个【赞】和【在看】吧!!

猜您还喜欢合集:


解决方案

SAP优化

ABAP新语法

SAP Note

SAP

ABAP

懒人鱼


猜您还喜欢文章:

聊聊ABAP动态编程

SAP这样优化:乙方开心,甲方放心!

浅谈SAP/SSO介绍及应用

浅谈SAP/ 文档管理解决方案

浅谈SAP/某化学纤维行业客户-优化案例


曰天曰地
我要到哪里去↔️ 灵台方寸山,斜月三星洞。假如有一天全人类不存在,怎么证明人类存在过。AI怎么考古?会怎么考古⚠️
 最新文章