zl程序教程

您现在的位置是:首页 >  数据库

当前栏目

SAP LUW Database update discuss mengniu 蒙牛

DatabaseSAP update
2023-09-14 09:03:06 时间

发送时间:2014年6月9日 下午8:54

另外我刚才做了测试,即使采用SET UPDATE TASK LOCAL将history table和header table的update强行塞到一个work process里,按照SAP现在的代码设计,也不可能做到将这两张表的update做成一个原子操作。就是说即使header table update出错,也不会对history table的更新有任何影响。

Sent: Sunday, July 20, 2014 10:35 PM

Hi Jerry,

百忙之中打扰你, 我问个小问题, 对于你当时的结论, 这个我有点想不通, 既然已经使用了local update, 按道理也算是把两张表放在了一个SAP LUW里, 为什么header出错, history table仍旧可以更新到DB呢?

Sent: Monday, July 21, 2014 12:19 PM

“采用SET UPDATE TASK LOCAL将history table和header table的update强行塞到一个work process里 ”并不等于两张表的update放在同一个LUW里。这两种说法不是同一回事。

用个例子说明:

有两张表:

用一个report测试,表1是直接online update,表2在update function module里update,由于有了SET UPDATE TASK LOCAL的keyword,使得function module ZINSERT_TABLE2 也在当前work process内执行。

data: ls_jerry1 type ZJERRYTABLE1,
ls_jerry2 type ZJERRYTABLE2.

ls_jerry1-client = sy-mandt.
ls_jerry1-inumber = 'i042416'.
ls_jerry1-name = 'WANGJER'.
insert ZJERRYTABLE1 FROM ls_jerry1.

CALL FUNCTION 'ZINSERT_TABLE2' IN UPDATE TASK.

SET UPDATE TASK LOCAL.

COMMIT WORK AND WAIT.

function module内只是一个很简单的assert语句用于模拟update function module出错的情况:

F8执行report,收到期望中的update function module执行出错的提示:

但是SE16 里table1里检查table1 已经有一条entry成功插入了:

再来模拟table1 update不成功,但是table2 update成功的scenario. 将update function module改成update table2: report 仍然保持不变,这样table1的update会由于duplicate key而失败。 report执行完之后,table1仍然只有1条数据,但是table2已经insert成功了。 究其原因,在这个例子里,table1和table2的update并不是放在同一个SAP LUW里的。这行ABAP OPEN SQL insert 语句(insert ZJERRYTABLE1 FROM ls_jerry1.), 什么时候会真正地把数据写到database server里?当遇到显式的database commit( COMMIT WORK ), 或者隐式的database 操作时,表1的操作就会立即写到database里,而与表2无关。 关于这两种不同的database commit方式,可以查看ABAP help: # Sent: Monday, July 21, 2014 1:56 PM 你要证明的这一点 1. 表1在normal的work process里进行update,表2通过update function module进行update。 n 如果表2更新出错,或者是更新表2的update function module 没有通过COMMIT WORK 触发,就会出现表1成功更新,但表2未更新的inconsistent状态。

你当时提供的第一段代码的结果是:
结果: 表1成功更新,表2更新失败( 对应的entry未插入到数据库里)。
Terry comment:表1仍旧在当前dialog wp里被隐式提交,而表2是在显式提交后转移到新的update wp里, 一旦在更新完表1之后, 再对表2的更新处理上失败,表1是不会被roll back的。这是root cause。
而且另外一个点是,印度开发若干年前曾经使用set update task local的方式(也就是local update)对表1进行处理(后来因为产生其他issue而放弃了local update,同时也没有使用in update task方式, 直接使用的了online更新),现在想来这样 也是无济于事,表1依旧是在当前dialog wp里被处理,并没有和表2结合成一个SAP LUW. 所以始终还是会出现破坏数据原子性的问题。

当前在蒙牛的case里

红框处的两个表更新是在一个function做的, 已经确认没有使用in update task方式。那么它的DB提交肯定是在自己当前的dialog wp里做的, 不会转移到update wp去做。

然后它下面的26行记录, 都是使用了call function in update task方式(我check了 代码), 把这13个function存储在VBMOD里, 是bundle在一个SAP LUW, 它们拥有唯一共同的update key,这个很清晰没有问题。
那么这13个update,才需要在另外一个update wp里去提交, 在这两个work process 转换的过程中, 按照我们今天探讨的内容, 是否说明上边那两张表就被隐式的先提交了; 随后SAP LUW里的13个function才被在update wp里提交到数据库里, 这样说是否更符合我们今天得到的认知。继续往下顺延这个逻辑, 如果那两张表发生了隐式提交, 那就意味着即使后边的这13个update在commit过程的中间步骤出错,也只会回滚该SAP LUW内的13个update, 而不会回滚 那两个已经隐式提交的表。

这也就是出现了history表已经插入, 而status状态未更新的现象的原因。

通过查看过去的错误记录, 红框所示行 , 5月14号发生的update error

看到这13个function被bundle到一起,

查看上面第一行 CMS_SI_INDEX_SAVE_DB, 我们知道他是用来更新CMSD_SI表的, 下面是要进行传值的内表, 红框所示的这几行数据需要在CMSD_SI表更新成PROC状态

但是实际的CMSD_SI这几条状态都是unpr状态,这是由于上述的update error导致更新没有成功。

同样CMSD_LO_STATUS这张表的status也没有被修改成proc

但是查看相应的历史表记录,却发现这一批数据已经被插入了history表, 佐证了你之前的分析结论。
CMSD_CI_HISTORY

蒙牛的情况就是下面这种, 一模一样, header表和history表在dialog process被commit了 随后的update process去更新 随后的13个sap luw内的function,如果出现不可预料的错误, 则回滚这13个function, 但是在dialog提交的两个update已经无法回滚 和下面的结论一致

要获取更多Jerry的原创文章,请关注公众号"汪子熙":