SAP锁机制(SAP Locks)经验小结

news2024/11/18 3:22:29

1. 数据一致性与锁

为什么要有锁机制?其背后的核心逻辑在于“保证数据的一致性”。

当数据被应用程序修改时,我们必须要保证修改后的数据具有一致性。在SAP系统中,将一致的数据状态从一个状态变动到另一个一致状态的时间跨度被称为LUW(逻辑工作单元)。

如果在LUW中发生了错误,系统将会自动撤销所有的操作,并将数据的状态回滚到初始的状态。这也就是rollback。

在SAP系统中,有两种类型的LUW,也即DB LUW和SAP LUW。

  • DB LUWs是通过database系统实现的
  • SAP LUWs是通过过特殊的SAP编程技术实现的

相应的,对应两种不同的LUW, SAP 设计了两种不同类型的锁。

  • DB Lock - 数据库系统设定加锁
  • SAP Lock - 在ABAP程序中加锁

在本文中,我将结合实际的开发经验,回顾和总结SAP Lock这个技术点。

2. SAP Locks基础概念

2.1 锁服务器

理论上讲,SAP Locks应当与SAP LUW的生命周期保持一致。

因为SAP系统可以有若干个应用服务器,为了应对不同应用服务器发送的数据请求,必须要有一个独立于应用服务器外的一个application server来处理锁的生命周期,我们通常将这个server称之为锁服务器(lock server)。

2.2 锁对象

SAP Locks的实现是基于lock object这个物理实体。通过SE11我们可以完成对于锁对象的定义。

通过锁对象,我们可以实现对于一行或多行数据的锁定,可以实现对多个数据表中数据的同时锁定(通过在定义锁对象时的外键依赖foreign key dependencies)。

当SE11定义完锁对象时,系统对自动生成一对锁函数,用于加锁和解锁。

下图展示了一个示例的锁对象:ZEGG_DOC_KEY。

有关锁对象的几点经验:

1. 锁对象中的主表,可以是一个实际上的DB表,也可以是一个结构。也就是说,SAP Lock其实是一种逻辑锁,有可能你锁定的表条目在DATABASE上根本就不存在。

2. SAP系统在应用服务器层面有一个全局的LOCK TABLE (SM12查看),用来管理逻辑锁来锁定相关的表条目,这个LOCK TABLE是cross-client的。如果,你的锁对象中,不包含MANDT这种client字段,加锁时,会对所有client上的这条数据进行锁定。

3. 如果primary table对应的structure上含有MANDT字段,在生成锁对象时,其对应的加锁函数上,会默认使用SY-MANDT值作为初始值。

4. SAP Lock支持缺省锁定,若只提供了了部分lock key,则会对缺省的key值全部锁定。举例,若lock key为 BURKS, BELNR 和GJAHR,加锁时,仅提供了 BUKRS = '1000' 其余值缺省,此时则会锁定所有 BUKRS = '1000'  的条目。同理,若加锁时,未提供任何一个lock paramter,则会锁定整个锁对象对应表。

2.3 加锁

加锁时,加锁函数会访问锁服务器的lock table,通过向lock table中写入相应条目来完成上锁动作。如果lock table中已经存在相应的锁条目而无法完成锁定,则会报出异常FOREIGN_LOCK。

下面是一个sample的加锁函数。

在使用加锁函数时,除了key字段外,还要关注几个技术参数。

2.3.1 mode_dbtab

mode_dbtab控制加锁的模式,基础模式有三种,也即E,X,S。

  • 模式E:当更改数据的时候设置为此模式。WriteLock(exclusive lock)
  • 模式X:和E类似,但是不允许累加,完全独占。Enhancedwrite lock (exclusive lock without cumulating)
  • 模式S:本身不需要更改数据,但是希望显示的数据不被别人更改。Read Lock(Shared Locked)

三种模式之间的依赖关系如下:

是否允许第二次加锁模式(同一进程内)
第一次加锁模式SEX
S允许允许不允许
E允许允许不允许
X不允许

在同一进程内,在加了S锁或E锁后,仍然可以继续加S锁或E锁。

是否允许第二次加锁模式(不同进程之间)
第一次加锁模式SEX
S允许 不允许不允许
E不允许
X不允许

在不同进程之间,在加了S后,仅可以继续加S锁。

S锁与E锁的经验小结:在仅读取数据时,加S锁,这样保证其它session中,仍然可加S锁读取数据时;在修改数据时,加E锁,这样保证修改数据时,对于数据的唯一锁定。

2.3.2 _scope

_scope参数定义了锁持续的时间,也即加锁后,何时会自动解锁。下面,我们引用SAP官方文档中的一张图,来进一步解释下这个概念。

在开始一个SAP LUW时,系统会创建两个Lock Owner(dialog owner和update owner),_scope参数用于说明这个lock归属于那个lock owner来控制。

含义
_scope = 1锁定仅属于对话所有者(dialog owner),因此仅存在于对话事务中。当调用DEQUEUE函数或事务结束时会解锁,COMMIT WORK或ROLLBACK WORK,并不会让锁失效。
_scope = 2

锁只属于更新所有者(update owner),当在更新任务CALL FUNCTION '...' IN UPDATE TASK和COMMIT WORK时,锁会被继承至此任务中。当更新事务完成时,锁会被释放。

可以使用ROLLBACK WORK,在锁被传递到更新之前释放锁。

注意:仅当调用了CALL FUNCTION '...' IN UPDATE TASK并结合COMMIT WORK时,锁才会被自动释放。仅使用COMMIT WORK并不会释放锁。

经验小结:对于_scope = 2的锁,若在程序中未调用CALL FUNCTION '...' IN UPDATE TASK任务,锁是不会自动释放的,需要手动释放锁;或创建一个dummy的IN UPDATE TASK任务,结合commit work一起使用。 例如下面的示例代码:

" ensure the locks are removed after update task

CALL FUNCTION 'ZGG_UPDATE_DUMMY' IN UPDATE TASK. 


COMMIT WORK AND WAIT.

_scope = 3该锁属于两位所有者( dialog owner 和 update owner)。换句话说,它结合了两者的行为。这个锁在两位所有者中的最后一个释放它后被取消。

2.3.3 _wait 和 _collect

_wait 和 _collect 参数一般使用的较少,其含义如下:

  • _wait :表示如果对象已经被锁定,是否等待后再尝试加锁,最大的等待时间由系统参数 ENQUE/DELAY_MAX控制。
  • _COLLECT:表示是否收集后进行统一提交。COLLECT 是一种缓存与批处理方法,即如果指定了Collect,加锁信息会放到Lock Container 中,Lock Container实际上是一个funciton Group控制的内存区域,如果程序中加了很多锁,锁信息会先放到内存中,这样可以减少对SAP锁管理系统访问。若使Lock Container中的锁生效,需执行FLUSH_ENQUEUE 这个Funciton,将锁信息更新到锁管理系统中,此时加锁操作生效,使用函数RESET_ENQUEUE可以清除Lock Container中的锁信息。

2.4 解锁

SAP锁可以通过删除锁表中的相关条目来手动释放(SM12)。

使用函数模块ENQUEUE设置SAP锁定时,传递给输入参数_SCOPE的值决定了锁定的持续时间。根据形式参数_SCOPE的值,SAP锁定可以如下释放:

加锁值锁的释放方式
_scope = 1

通过调用DEQUEUE函数释放;或等到对话程序结束时自动释放(包含的场景例如:程序自动结束、发生TYPE为A或者X的message、使用语句LEAVE PROGRAM,LEAVE TO TRANSACTION,或者在命令行输入/n回车以后)。

_scope = 2

在COMMIT WORK前通过DEQUEUE函数释放(但这没什么业务意义,因为_scope  = 2时,我们一定是希望锁持续至COMMIT WORK触发的更新任务执行完成。唯一有效的场景是,在加完_scope  = 2的锁后(COMMIT WORK执行前),程序发生了异常,此时捕获异常后,在CATCH分支需要DEQUEUE手动解锁,否则这个锁会在程序结束后,继续存在)。

通过IN UPDATE TASK任务结合commit work一起使用,在COMMIT WORK执行结束后,自动解锁。

_scope = 3

更新函数和对话程序都必须释放锁:

  • 更新释放锁对应于_SCOPE = 2
  • 对话程序中释放锁对应于_SCOPE = 1

最终锁释放由最后释放锁的动作决定。

注意:如果要使用函数模块 DEQUEUE 来在更新之外释放 SAP 锁定,那么形式参数 _SCOPE 必须被赋予一个大于或等于与函数模块 ENQUEUE 的同一形式参数传入的值。

下图是一个默认生成的dequeue函数,可以看到,dequeue时,其默认的scope是3。

2.5 上锁的一般步骤

先上锁,上锁成功之后,从数据库取数据,然后更改数据,接着更新到数据库,最后解锁。按照这个步骤,才能保证更改完全运行在锁的保护机制下。

3. 小结

本文总结了SAP Lock的工作原理,并分享了实际使用中的经验。希望本文对你有帮助!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1713381.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

宝塔安装java环境Jdk1.8

1.打开宝塔——选择“终端”——输入SSH的服务器IP和SSH账号,选择密码验证,输入密码 2。登录成功后,输入:yum list java-1.8*,用于列出所有与 “java-1.8” 相关的软件包 yum list java-1.8* 3.安装Jdk1.8: yum insta…

登峰造极,北斗相伴——纪念人类首次登顶珠穆朗玛峰71周年

71年前的今天,1953年5月29日11时30分,人类实现了一个伟大的壮举:首次登上了珠穆朗玛峰,这座海拔8848.86米的世界最高峰。这是一次充满了艰辛、勇气和智慧的探险,也是一次改变了人类历史和文化的探险。 自那以后&#…

有没有好用的供应商协同软件,能实现文件的便捷协作?

制造业供应商间文件协作非常频繁,而频繁的文件协作也是保证业务有效开展的基础,对于确保生产流程的顺畅和高效至关重要。以下是一些常见的制造业供应商文件协作的例子: 采购订单和合同:采购订单是供应商和制造商之间最基本的文件协…

力扣hot100:23. 合并 K 个升序链表

23. 合并 K 个升序链表 这题非常容易想到归并排序的思路,俩升序序列合并,可以使用归并的方法。 不过这里显然是一个多路归并排序;包含多个子数组的归并算法,这可以让我们拓展归并算法的思路。 假设n是序列个数,ni是…

ROS运行文件(LaunchFile)和参数(Parameter)

本文主要介绍ROS的Launch File和Parameter概念,通过Launch File启动单个或多个节点,并通过Parameter配置启动参数。 更多内容,访问专栏目录获取实时更新。 当你的应用中包含了很多工作包,每个工作包了又包含了多个节点时&#xff…

本地部署大模型的几种方式

现在大模型可谓是满天飞, 只要你稍微关注时下的AI资讯, 几乎每天都有新的AI大模型出现. 这之中当然有诸如GhatGPT, Gemini这样的私有化大模型, 更吸引人关注的可能是开源的可私有化部署的一些大模型. 比如Meta前两天开放的Lamma 3, Google的Gemma开源模型, 国内也有Qwen以及YI等…

java海滨学院班级回忆录源码(springboot)

风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的海滨学院班级回忆录。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: 海滨学院班级回忆录的…

高速公路边坡监测预警系统解决方案

一、概述 高速公路是国家交通大动脉,高速公路的安全、稳定是人民生命安全的保障。高速公路地基和边坡在线监测系统是交接高速公路运行状态的耳目,是保证高速公路稳定、安全保障人民生命财产安全、充分发挥高速公路国家交通大动脉的重要手段。高速边坡在线…

Java——执行流程

一、执行流程 1、示例 //第一个Java程序 public class Hello{public static void main(String[] args){System.out.println("Hello World!");} } 编译: 执行: 我们可以看到这里的是类名,而不是字节码文件名 Hello.class &#…

从tensorflow导入EarlyStopping能运行但是一直提示未解析

在pycharm中导入早停机的库时,碰上一个问题 from tensorflow.keras.callbacks import EarlyStopping这一条代码中,EarlyStopping一直有个红色波浪线,代表着找不到这个库,提示未解析啥的。 但是运行是可以运行的,虽然可…

Android Context 详解

一、什么是Context? Context是一个抽象基类。在翻译为上下文,是提供一些程序的运行环境基础信息。 Context下有两个子类,ContextWrapper是上下文功能的封装类(起到方法传递的作用,主要实现还是ContextImpl&#xff0…

[oeasy]python019_ 如何在github仓库中进入目录_找到程序代码_找到代码

继续运行 🥋 回忆上次内容 上上次 真写了万行代码 这 万行代码 都是写在明面上的 这次 使用git命令 下载了 github上面的仓库 下载仓库 之后 又该 怎么办呢?🤔 进入目录 首先看看 目前 在哪个目录 pwd present working directory 当前目…

在全志H616核桃派开发板上进行音频配置的方法详解

耳机口​ 核桃派板载的3.5mm音频输出口,该接口有一定的输出功率,可以使用耳机或者带功放的扬声器都可以播放声音。 查看音频设备​ 可以使用下面指令来查看音频信息: aplay -l音频播放测试​ 播放系统自带wav音频文件测试, 下面指令的au…

【wiki知识库】03.前后端的初步交互(展现所有的电子书)

📝个人主页:哈__ 期待您的关注 目录 一、🔥今日目标 二、📂前端配置文件补充 三、🌏前端Vue的改造 四、💡总结 一、🔥今日目标 在上一篇文章当中,我已带大家把后端的一些基本工…

脑图工具 在学习系统架构中的使用

系统,有人把它比作一个黑盒,有人比作一个树洞。呃,其实二者都隐含的表达了一个意思,盘根错节,一言难尽,欲说还休,说了又像是隔靴搔痒,感觉没说透。 学习,理解和展示一个…

信创操作系统生态

信创操作系统生态 中标麒麟 官网https://www.cs2c.com.cn/scheme/product/7.html 银河麒麟 官网 https://www.kylinos.cn/ 中科方德 官网 https://www.nfschina.com/index.php?catid30 中兴新支点(中兴公司自研的linux操作系统) 官网 http:/…

Facebook开户 | Facebook的CTR是什么?

在当今数字化的营销领域,了解和利用各种指标是成功的关键。其中一个关键指标是CTR,即点击率(Click-Through Rate)。 在Facebook广告中,CTR是一个至关重要的度量标准,它不仅可以衡量广告的效果,还…

男士内裤哪种款式舒服?五条实用技巧让你轻松挑选

对于很多男生来说,依然很难挑到真正舒适的内裤。比如卡臀卡裆,走路时不时还得提拉一下,真的很尴尬。又紧又闷的内裤!尤其是炎热的夏天,黏糊糊的贼难受!到底有没有一款舒适透气男士内裤呢?那今天…

LeetCode516:最长回文子序列

题目描述 给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。 子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。 代码 /*dp[i][j]:[i,j]的回文子序列长度为d…

Remix IDE 创建和部署第一个合约HelloWorld

Remix IDE 地址 https://remix.ethereum.org/ 流程步骤: 创建一个新文件 输入文件名保存 在文件资源管理器中,点击新建文件图标创建一个新文件,并给它命名。在 Remix 中,默认的文件扩展名是 .sol ,如果文件名没有…