文章目录

  • MDG数据处理
    • 简介MDG数据处理逻辑
    • 读取Entity Data
    • 修改Entity Data
    • 派生 Derivations
  • 实战:运用技术知识解决实际问题
    • 用户问题
    • 问题分析
      • 展示层
      • BOL层
      • Genil层
      • MDG API层
    • 解决方案和结论

MDG数据处理

简介MDG数据处理逻辑

首先需要从技术角度简单的了解一下SAP MDG数据处理的大体逻辑(正如我一贯认为,MDG是一个技术系统而不是业务系统,所以顾问需要有一定的技术背景,这些技术储备需要比一般的业务顾问多得多)。

在MDG数据处理的过程中,Entity Data来自不同的数据源,包括Active Data和Staging Data(Inactive Data)。活动数据Active Data是指在系统中真正有效的数据,也就是说这些Active Data可以随时被外部的应用和业务过程调用。同时,MDG系统本身也有大量的数据,依赖于Change Request(变更请求)而存在,这些数据独立的存储于Active Data之外。我们于是称之为非活动数据Inactive Data临时数据Staging Data。当这些变更请求被最终审批通过后(Final Approved),与各个变更请求相关的非活动数据被转换为相应的活动数据。这个过程在MDG系统中叫做变更请求的激活Change Request Activation

我们都知道,MDG Entity Type可以被分为两种,Flex Entity Type和Reuse Entity Type。Flex Entity Data没有独立的活动数据存储区,而是将Active和Inactive Data同时存储于MDG 临时表Staging Table中。对于Flex Entity Data的所有读写操作,都是通过MDG抽象层和随后的MDF层进行的。

Reuse Entity Type拥有他们自己的活动数据存储区域。数据的读写一般会从抽象层委托到各自的访问类Access Class。非活动数据则与Flex Entity Type一样,存储在MDG临时表中。除了非活动数据外,Reuse Entity Type还拥有快照数据Snapshot Data。这些快照数据是从活动数据复制而来的,于Reuse Entity被插入进变更请求对象列表Change Request Object List的时候创建。就像非活动数据一样,这些快照数据同样存储于临时表中。对于这些快照和非活动数据的访问总是从抽象层开始,使用MDF来实现。

读取Entity Data

读取Entity Data的过程如下图所示:

Entity Data 可以使用Convenience API, Governance API和External Model API进行读取。无论使用哪种API,读取的请求都会首先委派给MDG抽象层。抽象层负责将请求发送给MDF或访问类,然后将结果进行合并,反馈给调用者。

在一个SAP LUW中还未进行保存的数据,会被放置到MDF的缓存区中。默认情况下,数据读取请求会使用MDF缓存区中的数据作为组成结果的一部分(另一部分为访问类)。

SAP LUW 逻辑工作单元 是SAP技术概念中最为基础和重要的内容之一,提供了多个对话操作过程中保持数据一致性的解决方案。详细内容请参见https://help.sap.com/saphelp_scm50/helpdata/en/41/7af4bfa79e11d1950f0000e82de14a/content.htm?no_cache=true

通常来说,读取的结果取决于请求参数和不同存储位置及MDF缓存区中的数据组合。API中的使用的参数决定了哪些数据将要被读取(例如,读取活动还是非活动数据,需要考虑变更请求内的非活动数据分配情况,Select条件,过滤条件和Edition等)。

修改Entity Data

Entity数据可以由数据写入或派生进行修改。在这两种情况下,修改过程中的数据分别存储于不同的位置,直到它们成为活动数据为止。这个流程参见以下架构图:

Entity Data 可以使用Change Request API, Convenience API 和 Governance API进行读取。无论使用哪种API,修改的请求都会首先委派给MDG抽象层。抽象层包含了它自己的临时增量缓存Delta Buffer知道这一点非常关键,因为这意味着任何对抽象层缓存的修改,都不会被任何读取请求发现。为了让这些修改的内容可以被读取到,需要首先将抽象层的增量缓存转移到MDF缓存中,这一过程称之为Flush。在这样一个Flush期间,一些派生Derivation的调用可能会进一步的变更数据。

为了处理不同缓存区和不同数据的修改场景,抽象层提供了不同的写入模式:

  1. Direct Mode: 在这种模式下,变更的数据被直接写入MDF缓存。不会涉及增量缓存和Flush。
  2. Direct Mode with Derivation:在这种模式下,变更的数据首先被写入增量缓存(包含了预先Collect的变更),然后这个缓存区的所有内容会被转移到MDF缓存(Flushed)。
  3. Collect Mode:在这种写入模式下,变更数据首先会被收集Collect到增量缓存中。不涉及MDF缓存和Flush。

一次Flush可以被应用在任意时间点通过调用对应的Flush方法来实现。此外,当任何读取或写入操作发生时,系统会自动触发一次Flush。

当保存或提交变更请求时,变更的数据作为非活动数据,从MDF缓存写入MDF临时表中。在后续变更请求审批通过并且激活时,这些非活动数据会被转换成活动数据。此流程终结于MDGStage Tables(Flex Entity Types)或Reuse Tables(Reuse Entity Types)。

派生 Derivations

派生(数据推导)可以被用于自动修改数据,而不需要人为交互。MDG提供了多种派生可能,何时、何地、何种派生方式。以下列出最重要的几种派生方式:

  1. Standard Derivations: 标准的派生可以使用BADI USMD_RULE_SERVICE下的方法IF_EX_USMD_RULE_SERVICE~DERIVE_ENTITY或BRF+实现。标准派生一般在使用Gov API或CR API写入数据时自动触发,或者一些特殊情况下由应用手工触发。
  2. Derivations in Access Classes: 访问类接口IF_USMD_PP_ACCESS提供了DERIVE_DATA方法用于实施该种派生。此方法在Flush期间以每个访问类为单元进行调用,并获取增量缓冲区的当前内容,以查明自上次Flush以来收集了哪些数据变更。
  3. Cross entity derivations: 这些派生可以使用BADI USMD_RULE_SERVICE下的方法IF_EX_USMD_RULE_SERVICE2~DERIVE来实现。和上面一种派生类似,此方法同样于Flush中调用,通过获取当前增量缓冲区的数据内容来查明上次Flush依赖Collect了哪些数据变更。Cross 派生位于Access派生后进行调用,可以获取到Access派生中修改的内容。

如果一些额外的Entity Data需要在派生中获取,记住只能使用External Model Interface(永远不要使用Gov或Conv API)。为了避免没有必要的Flush和派生(以免造成死循环),NO_FLUSH参数需要设置为‘X’。

下图总结了几种派生方式的顺序关系:

以上大部分内容翻译自MDG API官方手册:
Master Data Governance Application Programming Interface Guide

实战:运用技术知识解决实际问题

用户问题


用户在使用系统的过程中,发现对于当前状态 = Final Checked Approved的变更请求,也就是已经审批通过并成功激活的变更请求进行查看时,界面丢失ERP Vendors的信息。但如果是通过MDG搜索界面直接搜索该BP,并显示Active Data则不会出现该问题。

问题分析

需要注意到这个问题的关键在于:使用Change Request 显示已经激活的数据,丢失部分信息。使用Object Key直接查询Active Data则没有问题。首先思考,这两种情况的区别在哪里?

  • Change Request Display搜索的条件是CR Number + Object Key。而Search Active
    Data仅使用Object Key作为搜索条件。因为BP是Reuse Mode,所以对于这种已激活的数据,Staging
    Table中不会存在记录。

  • 需要注意的是,只有状态 = Final Approved的数据才会出现这个问题,审批过程中一切正常。说明当非活动数据是可以正常获取的。

那么现在主要把关注重点放在非活动数据转换成活动数据的时候会不会出现了什么问题。参照上面所讲述的MDG数据处理逻辑,问题可能发生在MDF或抽象层,由于用户系统存在大量客制化代码,下面通过Debug来追溯问题根源,Debug之前我们需要了解MDG应用的大体架构如下图,既然问题发生在前台,因此需要遵循此架构从展示层开始一步一步查找问题:

展示层

检查UIBB Feeder Class的GET_DATA方法,发现无论是CT_DATA还是MO_COLLECTION中都没有ERP Vendor的相关数据。MO_COLLECTION来自于FPM组件初始化过程,数据内容来自FPM Connector,也就是我们在FPM Configuration中配置的Wire。

Connector是Genil和FPM BOL的桥梁,可以很简单的获取到Connector Class在如下的配置点:

BOL层

将断点置于Connector Class CL_BS_BP_CONNECTOR_BOL_REL的PROCESS_RELATION方法中,该方法可以从父节点通过关系获取到子节点的数据内容。

下面的截图对比了使用CR读取数据和Object Key直接读取活动数据的区别。


我们可以从左边发现CR读取时并没有获取到SP_MULTIPLEASSIGNMENT的关系,这意味着数据丢失发生在更底层。

Genil层

MDG BP模型使用了多个Genil Class应用于不同的Genil Model。在这个例子中,由于ERP Vendor是属于BP Multiple Assignment的,所以让我们将断点设在MLT_ASSIGNMENT的Genil Class中。

通过Debug发现,此时Entity BP_MLT_AS依旧无法获取到数据。

继续在Genil Class中向内部调试,找到了调用API的地方。

MDG API层

让我们来看一下使用CR和只使用Object Key在调用MDG API时存在什么区别。
Display Change Request:参数MV_CREQUEST_ID不为空

Display Business Partner:参数MV_CREQUEST_ID为空

此外他们都使用BP_HEADER = 0005061112作为Object Key。

除了一个参数不同外,还有哪些关键的区别呢?

读取模式。Display CR中的读取模式 = 1(默认),因为在变更请求的不同阶段(状态),读取模式会动态变化。比如处于审批过程中的数据,属于非活动数据,因此需要从临时表中获取数据。但是当变更请求激活后,状态变为Final Approved,此时非活动数据不复存在,当我们尝试Display CR时,会从活动区域来获取数据。所以通过CR的读取模式 = 1,是动态的。

对于Display BP来说,因为本身查看的就是活动数据,所以只用Object Key来读取数据的模式固定 = 3(无非活动数据),这很好理解,会直接从激活区域获取数据。

可是,Debug中却显示,现在即使我们在读取一个Final Approved的CR,逻辑还是指向读取Staging数据,这就是问题所在。激活的ERP Vendor数据肯定无法再去使用Read Staging来获取到。

解决方案和结论

用户的定制化代码导致标准的MDF缓存错乱,引导系统使用了错误的读取模式。对Multiple Assignment这个Entity来说,尝试对于已激活的数据仍使用Read Staging方法进行读取。必然导致获取不到ERP Vendor的数据。当注释掉用户对应的代码后,问题得到了解决。

SAP MDG —— 简介MDG数据处理逻辑和MDF缓存区相关推荐

  1. SAP MDG简介相关理解

    文章目录 MDM(Master Data Management)和MDG(Master Data Governance)的区别是什么? 从技术角度看SAP MDG是一个怎样的系统? SAP MDG是一 ...

  2. 《走进SAP(第2版)》——2.5 SAP NetWeaver简介

    本节书摘来自异步社区<走进SAP(第2版)>一书中的第2章,第2.5节,作者: [德]Nancy Muir , Ian Kimbell , 等 更多章节内容可以访问云栖社区"异步 ...

  3. 【FI】SAP ODN简介

    SAP ODN简介 在我国,根据凭证装订的需要(通常按月分成"收"."付"."转"类型),财务记账凭证通常都是按月顺序编号的(即每个月都是从 ...

  4. 【SAP PO】SAP PO 简介:XI、PI、PO的关系与区别

    SAP PO 简介:XI.PI.PO的关系与区别 1. 历史回顾及演变过程 1.1.SAP Exchange Infrastructure (SAP XI) 1.2.SAP Process Integ ...

  5. Ristretto 简介: 一个高性能GO缓存

    Ristretto 简介: 一个高性能GO缓存 原文地址:Introducing Ristretto: A High-Performance Go Cache 原文作者:Dmitry Filimono ...

  6. java memorycache原理_JVM代码缓存区CodeCache原理及用法解析

    一. CodeCache简介 从字面意思理解就是代码缓存区,它缓存的是JIT(Just in Time)编译器编译的代码,简言之codeCache是存放JIT生成的机器码(native code).当 ...

  7. java+cache使用方法_JVM代码缓存区CodeCache原理及用法解析

    一. CodeCache简介 从字面意思理解就是代码缓存区,它缓存的是JIT(Just in Time)编译器编译的代码,简言之codeCache是存放JIT生成的机器码(native code).当 ...

  8. Git的基本使用(用户初始化配置、新建代码库、把文件提交到缓存区、把文件提交到本地仓库等)

    [基本概念] Git: Git是负责对工作区的文件进行版本控制,因为Git装在本地,那么在本地(当前计算机下)就必须要有一个仓库,这个仓库中记录了所有的版本变化. Github: 公网上典型的远程仓库 ...

  9. Linux系统编程:验证kernel内核缓存区大小->4096字节

    Linux系统编程:验证kernel内核缓存区大小->4096字节 李四老师 于 2018-04-04 00:40:04 发布 2778 收藏 2 分类专栏: [Linux编程] [C/C++编 ...

最新文章

  1. Linux 性能监控常用命令
  2. python设置环境路径_window10配置python虚拟环境的路径
  3. 【Linux学习九】负载均衡
  4. 【arduino】继续arduino玩CyberPi童芯派之官方arduino库
  5. 如何正确清理C盘中DriverStore文件夹中文件?
  6. 【STM32】SysTick定时器
  7. 极客大学产品经理训练营:产品经理的项目管理 第14课总结
  8. Petalinux配置
  9. 机器学习如何影响系统设计:Learned Index Structures浅析
  10. 搭建 Kodbox 私有云教程
  11. c语言中的加减乘除字母,C 语言简单加减乘除运算
  12. spring Clound EMERGENCY! EUREKA MAY BE INCORRECTLY CLAIMING INSTANCES ARE UP WHEN THEY'RE NOT. RENEW
  13. 自动化运维为什么是必须的?
  14. 模拟信号隔离器|隔离放大器|隔离变送器 常见问题解答
  15. 学计算机需要自控力,上班族,自控力差,怎样才能静下心好好学习?
  16. Graphite实战
  17. 【Spring学习】Bean生命周期
  18. 有必要创建一个属于自己的维基百科企业词条吗
  19. Uniswap V3流动资金池遭遇网络钓鱼攻击,已损失价值3278ETH的NFT头寸,约合3563644美元。
  20. 2016年指维科技的P2P网贷平台系统市场占有率居榜首

热门文章

  1. CondaSSLError——ProxyError
  2. 如何使用视频合并分割软件将MP4视频合并分割 1
  3. java读取微信消息_android 读取微信聊天内容 示例源码(AccessibilityService)
  4. 客户询价,怎么回最妙!
  5. mysql Convert/Import MWB to SQL File in workbench
  6. AWK 内建变量FS,NF,NR,FNR,RT,RS,ORS,OFS
  7. agree的所有用法
  8. 情人节程序员用HTML网页表白【谢谢你的爱】 HTML5七夕情人节表白网页源码 HTML+CSS+JavaScript
  9. 远算CAE平台-基于Ansys Fluent和Steady-State Thermal的稳态热固耦合模型
  10. 【UnityEditor】Unity将Multiple Sprite分割成多张png小图