SAP中的 UPDATA TASK 和 BACKGROUND TASK
前言:
记录这篇文章起因是调查生产订单报工问题引申出来的一个问题,后来再次调查后了解了其中缘由,大概记录以下,如有不对,欢迎指正。问题原贴如下:
SAP CO11N BAPI_PRODORDCONF_CREATE_TT连续报工异步更新导致COGI解决方案-CSDN博客https://blog.csdn.net/DeveloperMrMeng/article/details/139811212?spm=1001.2014.3001.5501
当时疑惑的点是为什么更新进程明明是被COMMIT WORK AND WAIT触发的,但为什么仍然会有锁定问题,经过后来再次debug后发现了问题所在,在更新进程中,货物移动的处理是放在一个background task异步tRFC去处理的,是一个立即开始独立运行的进程,主程序中的同步提交只会等更新进程执行完,并不会等这个异步tRFC执行完毕,因为是不同的进程,而这个异步tRFC中在货物移动时会再次对订单上锁,所以当这个异步tRFC没处理完时,立即进行下一次报工就有可能出现锁定问题。
tRFC流程:
问题说明:
针对于报工BAPI,大致的执行流程如上图所示,
- 将所有检查通过的数据库提交任务绑定至同一个LUW;
- 由COMMIT WORK AND WAIT触发同步提交;
- Debug模式可以在SM13中观测到所有注册的更新模块,并且主程序中的锁会被带到更新进程中去,系统将按照注册顺序依次执行,通常这些模块中只包含数据库增删改操作,执行完所有模块后,系统统一提交,并释放所有锁,如果失败,则会统一回滚,并会收到一个dump快件,也会释放所有锁;
- 在标准设计中,货物移动的处理是预先存在AFFW表中,由最后一个更新模块(CO_RU_VB_CONFIRMATION_POST)处理,在这个模块中,将货物移动的处理放在了BACKGROUND TASK中,查看F1说明文档可以看到这是一种已过时的用于绑定事务性RFC的技术,通过该方式注册的函数会立即开始,并且独立异步执行,通过进一步debug,发现货物移动的处理涉及生产订单处理时会再次对订单上锁;
- 程序结束,因为IN BACKGROUND TASK注册的函数是独立的进程,所以如果该进程还没有执行完毕,在下一次针对该订单进行报工的时候就会出现锁定错误;
- 本次执行结束后,第二次针对同一订单处理时,如果异步RFC执行完毕,则第二次将会成功处理(报工成功,货物移动成功);
- 如果报工时异步RFC尚未处理完毕,第二次处理则会因为锁定直接报错(报工失败,货物移动失败);
- 如果第二次报工时上一次的异步RFC尚未开始处理,但处理第二次货物移动时刚好上一次的异步RFC处理已经开始,则可能会出现报工成功,货物移动因为锁定进入COGI(报工成功,货物移动失败);
这也是为什么调用了BAPI之后COMMIT WORK AND WAIT或者调用BAPI前指定了SET UPDATE LOCAL TASK没有生效的原因。
标准BAPI Debug确认过程:
设置好断点,并打开系统调试和更新调试。
同步提交后进入更新进程:
SM13可以看到注册了以下的更新函数模块,其中对自动货物移动的处理在最后一个函数中:
继续调试:
针对最后一个函数重点关照:
标准逻辑就是在此处触发异步的TRFC去处理货物移动的逻辑,此时打开TRFC调试,则该函数模块不会立即执行,会使其注册到SM58,方便进行后续手工处理调试,如果不勾选则会立刻执行,不会等待手工处理。
F8执行之后,可以看到此时已返回主程序,针对订单的锁也已经释放,但处理货物移动的函数被我们注册到了SM58,等待处理,所以SM58进行下一步调试,看看里面做了些什么。
SM58:
在下面这段处理中将会对订单再次上锁:
只有等该函数执行结束后才会释放锁,所以如果此时再次对该订单发起报工时就会出现锁定问题。
以上差不就是整个关键的debug过程,为了再次验证这个猜想,我重新写了一份测试代码进行验证,以下代码可以复现还原这个问题。
测试代码:
*&---------------------------------------------------------------------*
*& Report ZUPDATE_TEST
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT zupdate_test.DATA:lt_test TYPE STANDARD TABLE OF ztest_trfc,ls_test TYPE ztest_trfc.DO 1 TIMES.TRY .ls_test-uuid = cl_uuid_factory=>create_system_uuid( )->create_uuid_x16( ).CATCH cx_uuid_error.ENDTRY.ls_test-uname = sy-uname.CALL FUNCTION 'ZNOMAL_TEST'EXPORTINGi_test = ls_test.COMMIT WORK AND WAIT.IF sy-subrc = 0.WRITE:'Update success:',ls_test-uuid.ELSE.WRITE:'Update failed:',ls_test-uuid.ENDIF.
ENDDO.
FUNCTION znomal_test.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(I_TEST) TYPE ZTEST_TRFC
*"----------------------------------------------------------------------CALL FUNCTION 'ENQUEUE_E_TABLE'EXPORTING
* MODE_RSTABLE = 'E'tabname = 'ZTEST_TRFC'
* VARKEY =
* X_TABNAME = ' '
* X_VARKEY = ' '
* _SCOPE = '2'
* _WAIT = ' '
* _COLLECT = ' 'EXCEPTIONSforeign_lock = 1system_failure = 2OTHERS = 3.IF sy-subrc <> 0.MESSAGE 'Lock Failed!' TYPE 'E'.ENDIF.CALL FUNCTION 'ZCALL_UPDATE_TASK' IN UPDATE TASKEXPORTINGi_test = i_test.ENDFUNCTION.
FUNCTION zcall_update_task.
*"----------------------------------------------------------------------
*"*"更新函数模块:
*"
*"*"本地接口:
*" IMPORTING
*" VALUE(I_TEST) TYPE ZTEST_TRFC
*"----------------------------------------------------------------------CALL FUNCTION 'ZBACKGROUND_TASK_TEST' IN BACKGROUND TASKEXPORTINGi_test = i_test.ENDFUNCTION.
FUNCTION zbackground_task_test.
*"----------------------------------------------------------------------
*"*"本地接口:
*" IMPORTING
*" VALUE(I_TEST) TYPE ZTEST_TRFC
*"----------------------------------------------------------------------SET UPDATE TASK LOCAL.DO.SELECT SINGLE * INTO @DATA(ls_lock1) FROM z13065_lock WHERE upd_id = '13065'.IF ls_lock1-zlock = '1'.EXIT.ENDIF.ENDDO.CALL FUNCTION 'ENQUEUE_E_TABLE'EXPORTING
* MODE_RSTABLE = 'E'tabname = 'ZTEST_TRFC'
* VARKEY =
* X_TABNAME = ' '
* X_VARKEY = ' '
* _SCOPE = '2'
* _WAIT = ' '
* _COLLECT = ' 'EXCEPTIONSforeign_lock = 1system_failure = 2OTHERS = 3.IF sy-subrc <> 0.MESSAGE 'Lock Failed!' TYPE 'E'.ENDIF.DO.SELECT SINGLE * INTO @DATA(ls_lock2) FROM z13065_lock WHERE upd_id = '13065'.IF ls_lock2-zlock = '2'.EXIT.ENDIF.ENDDO.* CALL FUNCTION 'ZUPDATE_TASK_TEST' IN UPDATE TASK
* EXPORTING
* is_test = i_test.MODIFY ztest_trfc FROM i_test.COMMIT WORK.ENDFUNCTION.
通过LOCK表中的标识字段可以控制进程执行位置,测试过程就不贴图了,感兴趣的可以自己debug看看,根据观察SM12,SM50,SM13,SM58等标准事务代码中的信息就可以理解整个执行过程。
总结:
大多数标准BAPI的更新都是放在更新进程(CALL FUNCTION XXX IN UPDATE TASK)中去统一提交数据库更新的,可以根据COMMIT WORK是否添加AND WAIT附加项来决定是否同步更新,而CALL FUNCTION XXX IN BACKGROUND TASK则以已单独进程进行异步更新的,独立于对话框程序,属于两种互相独立的更新进程。
参考资料:
在后台任务中调试 FM - SAP Community
什么是LUW?LUW如何运作?不同类型的 LUW ... - SAP 社区
SAP LUW - ABAP 关键字文档
Transactional RFC (tRFC) | SAP Help Portal
相关文章:

SAP中的 UPDATA TASK 和 BACKGROUND TASK
前言: 记录这篇文章起因是调查生产订单报工问题引申出来的一个问题,后来再次调查后了解了其中缘由,大概记录以下,如有不对,欢迎指正。问题原贴如下: SAP CO11N BAPI_PRODORDCONF_CREATE_TT连续报工异步更…...

UDP协议:独特之处及其在网络通信中的应用
在网络通信领域,UDP(用户数据报协议,User Datagram Protocol)是一种广泛使用的传输层协议。与TCP(传输控制协议,Transmission Control Protocol)相比,UDP具有其独特的特点和适用场景…...
支持向量机(Support Vector Machine,SVM)及Python和MATLAB实现
支持向量机(Support Vector Machine,SVM)是一种经典的机器学习算法,广泛应用于模式识别、数据分类和回归分析等领域。SVM的背景可以追溯到1990s年代,由Vladimir Vapnik等人提出,并在之后不断发展和完善。 …...

【RT-thread studio 下使用STM32F103-学习sem-信号量-初步使用-线程之间控制-基础样例】
【RT-thread studio 下使用STM32F103-学习sem-信号量-初步使用-线程之间控制-基础样例】 1、前言2、环境3、事项了解(1)了解sem概念-了解官网消息(2)根据自己理解,设计几个使用方式(3)不建议运行…...
使用nodejs输出著作权申请所需的word版源码
使用nodejs输出著作权申请所需的word版源码 背景 软件著作权申请需要提供一份80页的word版源代码,如果手工复制源码到word文档中,工作量将无聊到让任何一个DAO人员血压爆表,因此我们不得不编写一个简单的文本处理代码,通过自动方…...
[Vite]vite-plugin-react和vite-plugin-react-swc插件原理了解
[Vite]vite-plugin-react和vite-plugin-react-swc插件原理了解 共同的作用 JSX 支持:插件为 React 应用程序中的 JSX 语法提供支持,确保它可以被正确地转换为 JavaScript。Fast Refresh:提供热更新功能,当应用程序在开发服务器上…...
记一次使用“try-with-resources“的语法导致的BUG
背景描述 最近使用try-catch的时候遇到了一个问题,背景是这样的:当第一次与数据库建立连接以后执行查询完毕并没有手动关闭连接,但是当我第二次获取连接的时候报错了,显示数据库连接失败,连接已经关闭。 org.postgres…...

用Excel处理数据图像,出现交叉怎么办?
一、问题描述 用excel制作X-Y散点图,意外的出现了4个交叉点,而实际上的图表数据是没有交叉的。 二、模拟图表 模拟部分数据,并创建X-Y散点图,数据区域,X轴数据是依次增加的,因此散点图应该是没有交叉的。…...

SpringBoot | 大新闻项目后端(redis优化登录)
该项目的前篇内容的使用jwt令牌实现登录认证,使用Md5加密实现注册,在上一篇:http://t.csdnimg.cn/vn3rB 该篇主要内容:redis优化登录和ThreadLocal提供线程局部变量,以及该大新闻项目的主要代码。 redis优化登录 其实…...

ESP32——物联网小项目汇总
商品级ESP32智能手表 [文章链接] 用ESP32,做了个siri?!开源了! [文章链接]...

flutter:监听路由的变化
问题 当从路由B页面返回路由A页面后,A页面需要进行数据刷新。因此需要监听路由变化 解决 使用RouteObserver进行录音监听 创建全局变量,不在任何类中 final RouteObserver<PageRoute> routeObserver RouteObserver<PageRoute>();在mai…...

Linux多进程和多线程(六)进程间通信-共享内存
多进程(六) 共享内存共享内存的创建 示例: 共享内存删除 共享内存映射 共享内存映射的创建解除共享内存映射示例:写入和读取共享内存中的数据 写入: ### 读取: 大致操作流程: 多进程(六) 共享内存 共享内存是将分配的物理空间直接映射到进程的⽤户虚拟地址空间中, 减少数据在…...
ruoyi后台修改
一、日志文件过大分包 \ruoyi-admin\src\main\resources\logback.xml <!-- 系统日志输出 --> <appender name"file_info" class"ch.qos.logback.core.rolling.RollingFileAppender"><file>${log.path}/sys-info.log</file><!…...

macOS查看系统日志的方法
1、command空格键打开搜索框,输入‘控制台’并打开 2、选择日志报告,根据日期打开自己需要的文件就可以...

数字信号处理及MATLAB仿真(3)——采样与量化
今天写主要来编的程序就是咱们AD变换的两个步骤。一个是采样,还有一个是量化。大家可以先看看,这一过程当中的信号是如何变化的。信号的变换图如下。 先说说采样,采样是将连续时间信号转换为离散时间信号的过程。在采样过程中,连续…...

云端AI大模型群体智慧后台架构思考
1 大模型的调研 1.1 主流的大模型 openai-chatgpt 阿里巴巴-通义千问 一个专门响应人类指令的大模型。我是效率助手,也是点子生成机,我服务于人类,致力于让生活更美好。 百度-文心一言(千帆大模型) 文心一言"…...

算法系列--分治排序|再谈快速排序|快速排序的优化|快速选择算法
前言:本文就前期学习快速排序算法的一些疑惑点进行详细解答,并且给出基础快速排序算法的优化版本 一.再谈快速排序 快速排序算法的核心是分治思想,分治策略分为以下三步: 分解:将原问题分解为若干相似,规模较小的子问题解决:如果子问题规模较小,直接解决;否则递归解决子问题合…...

强化学习编程实战-1-一个及其简单的强化学习实例(多臂赌博机)
1.1 多臂赌博机 一台拥有K个臂的机器,玩家每次可以摇动K个臂中的一个,摇动后,会吐出数量不等的金币,吐出金币的数量服从一定的概率分布,而且不同臂的概率分布不同。 多臂赌博机的问题是:假设玩家共有N次摇地…...

Golang语法规范和风格指南(一)——简单指南
1. 前引 一个语言的规范的学习是重要的,直接关系到你的代码是否易于维护和理解,同时学习好对应的语言规范可以在前期学习阶段有效规避该语言语法和未知编程风格的冲突。 这里是 Google 提供的规范,有助于大家在开始学习阶段对 Golang 进行一…...
数据机构记录顺序表-笔记1
一、线性表的基本概念 数据元素:线性表中的基本单位,每个元素都是线性表的一部分。 数据项:数据元素的具体值。 存储位置:线性表中的元素在内存中的具体存储位置。 线性表按存储结构可以分为顺序表和链表两大类: 1.1…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)
目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 (1)输入单引号 (2)万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...

恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...

密码学基础——SM4算法
博客主页:christine-rr-CSDN博客 专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 编辑…...