SAP是一个C/S结构,对数据库LUW在程序中会有一些隐式的DB Commit:

A、当系统输出一个屏幕的时候

B、当系统输出一个Message的时候,尤其是I类型的message( 会出现一个弹出框 )

C、当执行RFC的时候(普通的function不会,意味着可以通过一个commit跨function控制lLUW )

D、CALL Transaction或者sunmit <program name>,

但是在做dialog程序的时候又不得不需要程序做到只有一个luw,这样可以保持数据的一致性。

这时候对不复杂的程序我们可以在初期用内表传递数据,而不是直接update db,但是对于复杂的逻辑,之前已经有现成的函数或者BAPI,我们难以把原有函数copy出来最一些修改,这时候可以通过update function来把这些逻辑几种存放在一个SAP LUW。

SAP LUW:系统中一个DB LUW是不能够完全保证数据一致性的,但是SAP LUW可以跨screen,对多个DB LUW进行绑定,会在最后一个DB LUW提交,是的隐式的db commit不是阵阵的提交。

启用SAP LUW 的三种方法:

1)、update function 的更新方式分为同步、本地、异步;

2)、通过事务RFC(TRFC),CALL FUNCTION IN BACKGROUND TASK | UNIT,把RFC注册成并发的异步执行

3)、通过子程序PERFORM,(perform ....... on commit )

 

1)、update function 的更新方式分为同步、本地、异步;

1、同步RFC ,其执行基于同步通信模式,远程调用时,通信双方都可以使用,调用程序等待远程调用功能处理结束并返回结果。

2、异步RFC , 执行不依靠RFC服务器系统的可用性,被调用的远程功能启动,调用程序继续运行,两者相互分离,远程功能的结果可以稍后接受。日志:SM58

3、事务性RFC,属于异步通信模式,调用程序不接受调用结果而继续运行,但是不立即启动远程功能,。相关RFC可以捆绑只一个事务(即逻辑工作单元LUW),然后通过事务性处理,将LUW内部各个调用功能整体提交或者全部取消,且保证所有操作只执行一次,确保RFC功能的可靠和安全。

一个或者多个IN BACKGROUND TASK都通过一个COMMIT WORK控制;每个事务都有一个ID,不能指定EXPORTING参数,可以设定开始时间。

例如:IDOC的send的function,MASTER_IDOC_DISTRIBUTE

4、队列RFC ,QRFC是对TRFC的一个增强,控制传输数据的处理次序。

3、并行RFC , 实质为异步RFC,在功能上实现多个SAP系统或着同一SAP系统不同服务器,以及应用服务器内部各个工作过程的并行处理,

前3中是RFC的基本模式,队列RFC和并行RFC可以视为基本模式的扩展

同步:需等待返回结果,异步不需要,TRFC无法接受结果,同步异步RFC调用必须可用,TRFC则在调用的时候不必可用,异步只适用SAP内部之间,不能通过T类型的Partner连接至外部系统。

异步RFC和并发RFC的区别:

异步RFC:可以在RFC服务的时候调用,区别与同步执行,调用程序不需要等待结果,继续运行,远程调用功能与调用程序处理功能相互分离,功能返回结果可以了在后续过程被接受。

并发执行:异步调用时接受结果,异步执行可以在多个SAP ABAP系统上并行处理,同一内部系统使用异步调用,并将部分处理负载转移到其他服务器上,并发执行则是不指定运行的服务器,都是在当前应用服务器上处理。

Update function module的更新模式:

异步模式:dialog 程序和update function各自运行,dialog请求到log 透明表,用一个commit work结束,update function被commit 触发并开始运行这些请求,dialog程序继续运行,不会等待update 程序结束,update function在特殊的update work process中运行;

同步模式:用commit work and wait来触发一个同步更新,dialog程序会在update function执行结束再进行下一步处理,程序结束在进行下一步的处理,如果后续处理或者dialog程序的结束需要更新后的结果,要用同步模式,等待update 程序的过程中,dialog程序的dialog work process被释放,更新结束,会重新分配。

(注:commit work 即会进入异步模式,这时候先执行dialog程序,但是update function也会随后执行,此时dialog程序并不一定执行完毕。一般来说dialog响应时间较少,而update function会更长,所以异步更新更常见,也不排除特殊要求性;commit work and  wait 要求执行完update function,才会执行dialog程序 )

本地模式:使用set update task local 来使用update module 在本地执行,用commit work 来关闭SAP LUW,更新汇总同一个dialog work process中进行,dialog等待更新完成(同步),local update 完成之后,会提交一个显示的DB COMMIT,DIALOG程序得以继续执行。LOCAL UPDATE更新请求不会写到VBLOG表中,而是在MAIN MEMORY,其速度笔同步和异步快一点,适合批量模式。且遇到COMMIT WORK 之后,本地执行不再有效。

*&---------------------------------------------------------------------*
*& Report  ZTESTLIAN2
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT ztestlian_update_fm.

TABLES:spfli,sflight.

DATA: ok_code TYPE sy-ucomm,
      save_ok TYPE sy-ucomm.

PARAMETERS:p_carrid TYPE spfli-carrid.
PARAMETERS:p_connid TYPE spfli-connid.

START-OF-SELECTION.
  SELECT SINGLE * FROM spfli WHERE carrid = p_carrid AND connid = p_connid.
  SELECT SINGLE * FROM sflight WHERE carrid = p_carrid AND connid = p_connid.
  CALL SCREEN 0001.

*&---------------------------------------------------------------------*
*&      Module  EXIT  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE exit INPUT.

  save_ok = ok_code.
  CLEAR:ok_code.
  CASE save_ok.
    WHEN 'BACK'.
      LEAVE TO SCREEN 0.
    WHEN 'EXIT'.
      LEAVE TO SCREEN 0.
    WHEN 'CANCEL'.
      LEAVE PROGRAM.
  ENDCASE.

ENDMODULE.                 " EXIT  INPUT
*&---------------------------------------------------------------------*
*&      Module  STATUS_0001  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_0001 OUTPUT.
  SET PF-STATUS 'STATUS_0001'.
*  SET TITLEBAR 'xxx'.

  SELECT SINGLE * FROM spfli WHERE carrid = spfli-carrid AND connid = spfli-connid.
  SELECT SINGLE * FROM sflight WHERE carrid = p_carrid AND connid = p_connid.

ENDMODULE.                 " STATUS_0001  OUTPUT
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0001  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_0001 INPUT.

  save_ok = ok_code.
  CLEAR:ok_code.
  CASE save_ok.
    WHEN 'SAVE1'.
      PERFORM update_1.
    WHEN 'SAVE2'.
      PERFORM update_2.
  ENDCASE.

ENDMODULE.                 " USER_COMMAND_0001  INPUT
*&---------------------------------------------------------------------*
*&      Form  UPDATE_1
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM update_1.

  CALL FUNCTION 'Z_LIAN_UPDATE_FM1'
    IN UPDATE TASK
    EXPORTING
      iv_connid    = spfli-connid
      iv_carrid    = spfli-carrid
      iv_planetype = sflight-planetype.

  CALL SCREEN 0002.

ENDFORM.                    " UPDATE_1
*&---------------------------------------------------------------------*
*&      Form  UPDATE_2
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
*  -->  p1        text
*  <--  p2        text
*----------------------------------------------------------------------*
FORM update_2 .

  CALL FUNCTION 'Z_LIAN_UPDATE_FM2'
    IN UPDATE TASK
    EXPORTING
      iv_connid    = spfli-connid
      iv_carrid    = spfli-carrid
      iv_countryfr = spfli-countryfr
      iv_cityfrom  = spfli-cityfrom
      iv_airpfrom  = spfli-airpfrom
      iv_countryto = spfli-countryto.

  COMMIT WORK AND WAIT.

  wait up to 5 seconds.

ENDFORM.                    " UPDATE_2

SE37中的update function还分4种模式,属于两种类型:V1和V2。

V1类型:1)、立即启动,如果发生错误可以用SM13手动重启更新,会清除有问题的应用程序错误;2)、立即启动(不可重启),发生错误是不可以重启;

V2类型:1)、延迟启动:V2类型出现错误,可以随时重新启动处理;2)、Collective run,V2更新的特殊模式,所有修改不直接更新,而是再V1更新之后,但只有在收集程序RSM13005被调用后

V1 和V2 对比:

1)、所有V1请求都在单独的DB LUW里,只有在V1执行后才会处理V2,V2也是在单独的LUW里执行。

2)、V2里处理的DB CHANGES一般都是紧接着V1的CHANGES( MAIN CHANGES )后执行

3)、V1可以分为可以重新启动和不可重新启动,V2发生的时候可以重新启动,再次处理。

4)、V2的collective run 是SAP 内部使用,相应的V2请求并不是在V1执行后直接执行,而且仅仅是在RSM130005被调用后才执行。

5)、V1请求,同步异步都会放在VBLOG这个table中,本地更新则是放在MAIN MEMORY,V2请求总是放在VBLOG中

6)、V1都会用UPD组颇为一个单独的DB LUW来处理,V1更新成功,系统会删除V1请求和所有V1更新任务上的锁,并设置DB COMMIT,然后触发V2,

 

下面再介绍以下update function怎么debug:

在debugging setting 中将Update debugging复选框,并点击保存,在函数中运行commit work 之后,会自动进入更新任务表SM13

Immediate start 表示v1方式更新,出错之后可以在SM13中重新执行;

Immediate start-no restart possible v1出错后不可以在SM13中再重新执行,有些更新脱离具体程序之后更新可能会带来数据不一致;

Start delayed 表示V2方式,在V1方式更新之后完成后触发,

Collective run表示 V2方式,需要用Collective( RSM13005 )程序手动或JOB执行

In update task 使用v1更新可以在commit work的时候执行所有的update function

分享一个实例:

需求在于为CJ20N和CN22修改预留单增加日志,但这都是集成模块,修改预留单数量在CN22中还会伴随网络,计划成本多部分的更新,在CJ20N在还会增加项目,WBS,SO等一系列内容的检查和更新,这一切的更新都是在多个PERFORM 或者FUNCTION中实现的,他们要想做到一致性必须要用到SAP LUW。

首先提交所用到的语法 commit work 和commit work and wait的区别就不再细说,我起初认为在提交的时候如果进入DEBUG模式,执行完更新SQL语句后在后面的update的函数在做SELECT的时候可以得到我更新后的值,所以我在commit work  and wait 前面的一个增强点加上一个perform ... on commit,但实际上虽然dubug已经已经执行了这段代码,但是实际上并没有更新数据库,所以我还是在commit work and wait之后的增强点去写的这段逻辑,当然这多逻辑在前面没有执行提交语句的时候也是不会执行的,这是为了在后面的CJ20N里面保证数据依旧是一次提交的。

当然上面的那个问题可以通过 ABAP MEMORY来解决,但是可能需要在另一个做一下增强。

做好增强之后出现另一个问题,在项目和WBS提交的时候使用到的是 commit work 异步提交模式,此时我后面所写的增强逻辑在读数据库的时候,不能读到最新的状态,所以必须写上等待0.5秒。但是请注意:WAIT UP语句有提交数据库的作用,所以在增强里面是一般是禁止使用WAIT UP语句的,我这里是由于刚刚做完提交,所以没啥问题。但是如果必须在增强里面加上等待应使用如下函数:

CALL FUNCTION 'ENQUE_SLEEP'

      EXPORTING

        seconds = 1

      EXCEPTIONS

        OTHERS  = 2.

注:两种语法都是Numeric类型,都应该是整数,上图中的0.5秒会被四舍五入变为1.