SAP/DB LUW
1.DB LUW
DB LUW(Logic Unit Work)是确保数据库更新一致性的机制,是数据库级别的,和底层DBMS有关,和SAP系统无关。如下图,从一致性状态A到B,中间有一系列的数据库操作,一个BD luw以数据库提交commit结束,这些操作要么全都执行,要么全都不执行。当全部执行成功,则数据库进入一致性状态B,如果在此DB luw中发生错误,则将从DB luw开始的所有操作进行回滚,数据库还是在A状态。
这是在数据库级别实现的,和SAP系统无关。
在SAP系统中,DB luw commit and rollback 可以被显式或隐式的触发。
不管是commit还是rollback,结束了一个DB luw,也即是开始了一个新的DB luw。
1.1.显式提交
·Native SQL提交语句
·Calling the function module DB_COMMIT.
·COMMIT WORK语句
1.2.隐式提交
·对话屏幕结束时(跳转另一屏幕)
CALL FUNCTION func DESTINATION dest
CALL FUNCTION func STARTING NEW TASK DESTINATION dest taskname
但RFC事务调用不会触发隐式提交:CALL FUNCTION func IN BACKGROUND TASK DESTINATION dest
·取RFC异步执行结果回调Form中RECEIVE 语句:CALL FUNCTION rfm_name STARTING NEW TASK DESTINATION dest tasknamePERFORMING return_form ON END OF TASK中的RECEIVE RESULTS FROM FUNCTION rfm_name语句会触发
·WAIT UNTIL log_exp [UP TO sec SECONDS]语句
·Sending error messages(E), information messages(I), and warnings(W).
1.3. 显示回滚
·使用Native-SQL进行回滚
·使用ROLLBACK WORK.进行回滚
1.4. 隐式回滚
·runtime error:在程序执行过程中未捕获的异常以及message type X的消息,因为runtime error会导致程序的termination
·因为发送的Message而导致程序的termination(除了A、X类型的消息会导致程序终止外,其他类型的消息在特定的情况下也会导致程序终止,具体请参见《User Dialogs.docx》中的消息显示及处理章节)
Runtime Error:系统不能继续运行,并且ABAP程序终止,以下情况会发生运行时错误:
²未处理的异常(当一个能够被处理的异常却未被处理时;抛出了一个不能够处理的异常)
²X类型消息
² ASSERT断言语句不成立时
2.SAP LUW
sap系统中一个业务操作会有多个对话屏幕,只到save操作成功,才算完成了一个业务。那么仅使用DB luw是不能保证SAP 系统数据一致性的。如下图,如果只是最后屏幕300保存时的DB luw发生错误,那么在数据库级一致性机制作用下只能回滚这一个db luw使数据库处于g状态,而前几个db luw在屏幕结束时已经提交,进行的数据库更新会全部生效,从业务层面上讲,这是不合理的,因为这个业务并没有保存成功,我们需要回滚到A或a状态。SAP luw就是sap在DB luw基础上保证数据库一致性的一种机制。
上图(未使用SAP LUW),绿色表示数据库更新操作。每个dialog steps都会形成一个单独的DB LUW。默认情况下(未通过SAP LUW的绑定方式来实现延迟执行数据库更新操作),每个DB LUW都会提交事务
上图(将多个DB LUW绑定成一个SAP LUW),将每个dialog steps(即DB LUW)中的数据库操作“移”到最后一个dialog steps(即DB LUW)中执行,这里的“移”实质上是一种延迟执行的方式,即先将前面每个dialog steps中的数据库更新操作记录下来,待最后统一由COMMIT来提交。
SAP LUW可以跨多个DB LUW,是一个业务逻辑上的概念,可人为的去定义开始与结束,而DB LUW是不能人为控制的
SAP LUW是DB LUW的一个增强,受体系结构限制,SAP程序每次屏幕切换时(控制权从后台DIALOG进程转移到前台GUI的Session),都会触发一个隐式的数据库提交,一个程序在运行是会产生多个DB 的LUW,这样无法做到全部提交或全部回滚,在某些业务场景下,这种事务的提交机制不足以保证数据的一致性,为此有了SAP LUW机制。
SAP LUW是一种延迟执行的技术,它将本来需要执行的程序块,记录下来(通过特定的方式来调用来实现SAP LUW的绑定:perform XXX on commit、update Funciton module),待系统在执行COMMIT WORK的时候会查询记录,真正执行需要运行的代码。COMMIT WORK一般在最后一个屏幕执行,这样就实现了将跨屏幕的数据更新逻辑绑定到一个DBLUW中(在后台会自动将这一系列的数据操作绑定在同一个数据事务DBLUW里,这样当提交出问题后,数据库事务DBLUW会自动回滚,这样就保证了数据的一致性),实现复杂情况数据更新的一致性
2.1.SAP LUW的绑定方式
2.1.1.Function
可以使用CALL FUNCTION update_function IN UPDATE TASK将多个数据更新绑定到一个database LUW中
此类型的更新函数Update Function中主要实现对数据库数据进行更新操作
² Immediate start:表示V1方式,将此更新函数设置为高优先级V1并运行在同一个SAP LUW中。更新出错后,可以在SM13里重新执行
² Immediate start -no restrat possible:V1方式,将此更新函数设置为高优先级V1并运行在同一个SAP LUW中。出错后不可以在SM13里重新执行
² Start delayed:V2方式,将此更新函数设置为低优先级V2并run in their own update transactions。V1方式更新完成后触发。出错后更新函数可以重启
² Collective run:V2方式,将此更新函数设置为低优先级V2并run in their own update transactions。需使用Collective(RSM13005)程序手动或JOB方式执行
V1与V2区别:
² V1优先级高于V2,V2被设计为依赖于V1,适合执行需要在V1完成后进行的操作
² V1更新使用V1进程处理,V1进程名字一般为UPD,V1进程绑定独立的数据库进程。在V1进程中调度的更新函数如果更新失败,回滚,不再进行V2操作。成功则提交更改到数据库,同时删除所有的SAP锁
² V2更新使用V2进程处理,如果没有配置V2进程则共用V1进程,V2进程名字为UP2,V2更新在独立DB LUW中,V2更新回滚后不会影响到V1更新提交的数据,由于V1更新结束后会删除SAP的锁,所以V2更新是在没有逻辑锁的情况下进行的,V2更新出错后可以在SM13中重新执行
² V1 的执行模式可以为异步、同步或本地;V2只能为异步执行
CALL FUNCTION ... IN UPDATE TASK的Function并不会立即执行,这只是先将它记录到内存(本地方式)或数据库表中(非本地方式),等到COMMIT WORK语句执行时才真正执行。如果在程序执行过程中,没有在Update Function 后面执行COMMIT WORK,则function module不会执行
此种类型的输入参数只能是值传递方式,不允许为引用传递,所以输入参数对应的“传递值”要钩上,并且传递的内容还不能是地址,即不允许为TYP EREF TO方式,只能是TYPE方式
2.1.2.subroutine
PERFORM subr ON { {COMMIT [LEVEL idx]} | ROLLBACK }.
子过程subr不会被马上执行,而是直到COMMIT WORK 或者是ROLLBACK WORK。可以使用LEVEL参数指定优先级,优先级按升序进行排列,较小的会优先执行。如果同样名字的subroutine被注册了多次,在COMMIT WORK时只执行一次,IN UPDATE TASK方式执行的Funciton没有这个限制
由于子过程绑定不需要写数据库表,所以比较更新函数绑定,性能上要高一些,缺点是你不能传递任何参数,它们所使用的必须是global data object,或可通过ABAP memory来共享参数
2.2.开启新的SAP LUW
没有专门类似开启数据库事务的语句(Begin trasaction),SAP LUW会在以下情况自动开启:
²提交COMMIT或回滚ROLLBACK后会开启另一个新的SAP LUW事务
²事务调用会重新开启一个新的SAP LUW
上图中F2不会被执行,因为它处于另一个事务中执行,但没有使用COMMIT WORK,而F1、F3会被执行,因为主调程序中使用了COMMIT WORK。所以事务调用会重新开启一个新的SAP LUW。
dialog modules与上面调用事务(CALL transaction)、调用executable programs (reports)不同的是:dialog modules中不会开启新的SAP LUW,如果dialog modules中调用了update function modules(CALL FUNCTION ... IN UPDATE TASK),则要等到主调程序中的COMMIT WORK时才会真正执行,哪怕在dialog modules中调用了COMMIT WORK也是没有用(不会启动update task)。
另外,由于数据共享问题,尽量不要在dialog modules中使用PERFORM XXX ON COMMIT。
2.3. 同步或异步更新(提交)
COMMIT WORK 异步更新,该语句执行后不会等待所有更新函数都执行完后才继续执行后面的代码
COMMIT WORK AND WAIT同步更新,该语句执行后会等待所有更新函数都执行完后才继续执行后面的代码,执行结果可以通过sy-subrc来判断事务提交是否成功
2.4.本地、非本地方式提交
本地方式:如果在调用UPDATE FUNCTION之前,先调用SET UPDATE TASK LOCAL.语句,这样所有在该语句后使用CALL FUNCTION...IN UPDATE TASK注册的更新函数不会记录到数据库中,而是记录在内存中,在Commit work之后,会从内存取得待执行的函数。在默认情况下,local update不会被设置,在使用COMMIT WORK之后 SET UPDATE TASK LOCAL的效果会被清除掉
本地方式更新只能采用同步方式,即使没有在Commit work后指定了and wait参数,仍然是同步执行
非本地方式:未使用SET UPDATE TASK LOCAL.语句。此方式下,注册的Update Function的名字以及接口实参都会以日志的形式记录到特殊的表。非本地方式即可同步也可异步COMMIT
² 本地方式不将待执行的更新函数写到数据表中,减少了I/O操作,效率上较高,但由于采用的是同步方式,程序需等待更新结果,用户交互时的会感觉程序运行较慢
² 非本地方式会将更新结果记录到数据表中,可以通过SM13查看更新情况,同时由于可以进行异步更新,用户交互时感觉会比较快