最新消息:ww12345678 的部落格重装上线,希望大家继续支持。

库存关账/重新计算产生的大量冗余日志记录

Uncategorized William 2浏览 0评论

不久后,我需为几个系统安装实例做性能优化,这些实例均面临库存关账性能不佳的问题,且库存关账与用户日常操作之间存在严重冲突。经深入排查发现,两个实例出现性能问题的核心原因均为:库存关账/重计算过程会对 InventSumLogTTS 表执行大量更新操作。由于这两个实例均采用加权平均库存模型,常规的库存重新计算会导致 InventTrans 表产生约 200 万 – 500 万条更新记录,相应地,InventSumLogTTS 表也会新增同等数量的记录。

最关键的问题在于,InventSumLogTTS 表采用悲观锁模式。这意味着,当用户执行订单展开更新或尝试排产生产订单时,系统会遍历所有参与该展开过程的物料对应的全部 InventSumLogTTS 记录。而当前存在数百万条交易记录的情况下,此遍历过程将耗费大量时间。此外,整个订单展开更新流程是作为一个庞大的事务执行的,这使得 InventSumLogTTS 表中所有被更新的记录在事务结束前会一直处于锁定状态。其他用户若尝试排产与当前重排订单存在直接或间接子组件关联的生产订单,都必须等待该事务完成。更有可能的是,与排产物料相关的部分记录是由尚未提交的库存关账事务插入的,因此每次排产遇到这些物料时,都需等待对应事务提交。简而言之,执行库存关账/重新计算操作会导致大部分生产相关功能无法正常使用。

以上描述均针对 Dynamics AX 2009 版本。在 Dynamics AX 2012 版本中,设计人员进行了针对性优化,以支持库存关账/重新计算与生产操作并行执行:

1.  为 InventSumLogTTS 表启用了乐观锁机制;

2.  引入了 InventSumLogTTS 记录的“软删除”功能——ReqTrans 更新函数可将记录标记为已处理,而非直接删除,从而避免对其他进程造成长时间锁定。

我尚未在实际场景中验证该算法的效果,也无法确保它完全解决了 InventSumLogTTS 表的锁定问题,但可以确定的是,2012 版本已修复了其中大部分关键问题。

不过,我仍对这一设计思路的合理性存疑。以下是具体分析:

1.  目前(至少在 4.0 – 2012 R2 版本中),InventSumLogTTS 表仅用于净需求(reqTrans)的动态更新。虽不确定未来是否会有其他用途,但当前该表无其他功能。

2.  物料需求计划(MRP)仅处理处于“预估”状态的库存交易。当库存交易完成收货登记(针对入库)或领料(针对出库)后,从 MRP 视角来看,该交易即成为现有库存的一部分,作为一个整体净需求由 MRP 统一处理,且处理依据是 InventSum 数据(而非库存交易数据)。

3.  若库存交易已完成实际更新(成为现有库存的一部分),净需求更新逻辑仅在该交易首次变更为实际更新状态时应用此变更。如果 InventSumLogTTS 表中某条记录的新旧交易状态均小于或等于“已领料/已登记”,则该记录不会应用于净需求计算,在净需求更新过程中会直接被丢弃。

4.  库存关账/重新计算仅处理远超“预估”状态的库存交易,即已完成实际更新或财务更新的交易。

5.  此外,库存关账/重新计算不会修改任何与 MRP 相关的数量、维度或交易状态字段。需要说明的是,加权平均库存的重新计算/关账过程会生成虚拟库存转移记录,但这些记录与 MRP 无关。

基于以上分析,我得出结论:应直接禁用库存关账/重新计算过程中向 InventSumLogTTS 表写入日志的操作。Dynamics AX 标准版本未实现这一优化,可视为一项设计缺陷。

接下来介绍实操方案:Dynamics AX 提供了禁用 InventSumLogTTS 日志记录的 API,可通过调用函数 appl.inventUpdateOnhandGlobal().inventUpdateOnhand().parmSkipInventSumLogTTS() 来启用或禁用该日志记录功能。需注意的是,事务结束时(无论提交或中止),日志记录会自动重新启用,因此多数情况下只需执行禁用操作即可,无需额外处理。

具体操作步骤如下:

1.  若要在库存关账/重计算过程中禁用 InventSumLogTTS 日志记录,需在 inventCostItemDim 类中所有 ttsbegin; 语句(非 connection.ttsbegin() 函数)之后,插入代码:appl.inventUpdateOnhandGlobal().inventUpdateOnhand().parmSkipInventSumLogTTS(true);

2.  若要在库存关账/重新计算取消过程中禁用该日志记录,需在 inventCostClosingCancel_WorkInvent 类中所有 ttsbegin; 语句之后,插入上述相同代码。

我已在两个安装实例中应用了此修改,效果显著:库存重新计算/关账时间从数天缩短至数小时(效率提升约 15 – 20 倍),且生产操作与库存关账/重新计算之间的锁定问题已完全解决。

英文原文:

Excessive logging from inventory closing /recalculation

In my previous post, I stated that InventSumLogTTS table is not updated after related inventory transaction was physically posted. I was totally wrong.

In a while I had to make some performance tuning for a couple of installations, which suffered from bad inventory closing performance and overall conflicts between inventory closing and regular user work. After looking closer onto the problem, in both cases, I found out that the main reason for performance issues is a large set of updates to inventSumLogTTS table, coming from inventory closing/recalculation process. Since both installations use Weighted Average inventory model, routine inventory recalculation was causing some 2-3-5 millions of updates to InventTrans table and, respectively, creation of the same number of records in inventSumLogTTS table. The worst part of it is that InventSumLogTTS table is locked in pessimistic mode. It means, that if your users are running an order explosion update or trying to schedule production order, the system will start iterating over all InventSumLogTTS records for all items, which somehow participate in the explosion. Since now we have several millions of transactions, it will take some time. Since all explosion update process is run as a one big fat transaction, all updated records in inventSumLogTTS will remain locked till end of this transaction and all other users, trying to schedule another production order, which happens to share any of direct or indirect subcomponents with order being re-scheduled, will have to wait till the transaction ends. Also, most probably, part of the records related to scheduled items were inserted by inventory closing in not yet committed transaction(s). And every time when scheduling bumps into one of these items, it have to wait till transaction will commit. Shortly speaking, any attempt to run inventory closing/recalculation safely prevent most of production-related functionality.

Everything I said is related to DAX2009. In DAX2012, designers made some provisions to support inventory closing/recalculation execution in parallel with production operation.First of all – they enabled optimistic locking for InventSumLogTTS table. Second – they invented ‘Soft Deletion’ of inventSumLogTTS records, so the reqTrans update function can mark records as processed without causing long  locks to other processes (because of actual deletion). I have not checked this algorithm in practical usage and I am not sure that they addressed 100% of locking issues for inventSumLogTTS table, but I can believe that in version 2012 they addressed the most of them.

Yet, I am not sure that the very approach is correct. Let’s look into the following statements.

  1. Right now (at least – as of versions 4-2012R2) InventSumLogTTS is used only for dynamic update of net requirements (reqTrans). I do not know how it can be used in future, but now this table do not have any other use.
  2. MRP deals only with inventory transactions in, so to say, ‘Estimated’ statuses. After inventory transaction was registered (for receipts) or picked (for issues), from MRP point of view, it becomes a part of inventory-on-hand, one big net requirement which processed by MRP as a whole and it is based on inventSum data (not on inventory transactions).
  3. If an inventory transaction were physically updated (becomes a part of inventory-on-hand), then net requirements update logic apply this change ONLY on first change to physically updated status. If both new and old transaction statuses in a record of inventSumLogTTS are below or equal to Picked/Registered, then this record is not applied to net requirements and simply dropped during net requirement update process.
  4. Inventory closing/recalculation deal ONLY with inventory transactions who are well behind ‘Estimated’ status. It process transactions which were already Physically or Financially updated.
  5. Moreover, inventory closing/recalculation DO NOT change any of quantity/dimension/transaction status fields, which are somehow related to MRP. Well – I remember that average inventory recalculation/closing creates  dummy inventory transfers, but they are irrelevant for MRP.

So, I can simply draw a conclusion that any logging to inventSumLogTTS from inventory closing/recalculation should be simply disabled. The very fact that this was not made in a standard version of Dynamics AX can be considered as a design bug.

Now let’s come to more practical part. Dynamics AX do have API to disabling logging to InventSumLogTTS. You can call the following function: appl.inventUpdateOnhandGlobal().inventUpdateOnhand().parmSkipInventSumLogTTS() to enable or disable logging to inventSumLogTTS. I must mention, that in the end of transaction (commit or abbort), logging is re-enabled automatically, so in most cases you just need to disable logging and then do nothing.

Practically speaking – to disable logging to inventSumLogTTS during inventory closing/recalculation, you need insert a call to appl.inventUpdateOnhandGlobal().inventUpdateOnhand().parmSkipInventSumLogTTS(true); after every ttsbegin; statement (but not connection.ttsbegin() function), you find in the inventCostItemDim class. To disable logging for inventory closing/recalculation cancellation, you need to insert the same call (again – after every ttsbegin;  statement) into the class inventCostClosingCancel_WorkInvent. 

I made this change for two installations and I had quite positive results: Inventory recalculation/closing time dropped from days to hours (about 15-20 times) and all locking between production operations and inventory closing/recalculation have been gone.

Usual disclaimer: Use this thing with care, first try it in TEST environment, I am not sure about future compatibility and compatibility with your customizations and so on. Anyway – even in the worst case, InventSumLogTTS is cleared out on every MRP regeneration for dynamic plan, so It is not very big deal to skip this updates. In the worst case, just imagine that you ran unsuccessful session of MRP regeneration. 😉

转载请注明:ww12345678 的部落格 | AX Helper » 库存关账/重新计算产生的大量冗余日志记录

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址