original:http://scnblogs.techweb.com.cn/tcsapbw/archives/1788.html
在前面【Lock】关于Lock后,有朋友问到:我已经了解到了SAP Lock的机制原理了,现在该如何创建Lock object,貌似在调用Enqueue FM时可以omit一些parameter,既可以在SE11创建Lock-object时omit一些key-field也可以在调用FM时omit一些lock parameter?
这里,因为Lock在SAP中使用非常的广泛,也是最基本的一个应用之一.所以这里再做一个总结,继续补充SAP Lock.本篇将主要讨论在Lock中Generic(通用)的应用以及Lock secondary table.
关于Lock,也许平常,我们使用最多的就是:
| 在se11中创建锁对象:指定锁对象table的锁定Key field组合;
然后在程序中,完全指定了锁对象的key fields组合。 |
然而,有时候我们却需要利用现存的锁对象,但我们不一定需要将所有的key field都指定上,这时候Lock的Generic特性就体现出来了。
1.一般性的Generic实例
使用数据库表SBOOK,其结构如下:
创建Lock Object 1: EZ_SBOOK_1
(注意,这里lock mode应为X,便于后文进行Lock的Generic的累加测试)
其中Lock Parameter:
(这里将MANDT去掉,与下面第二部分进行对比)
然后,我们来看一下SBOOK中的数据:
好,程序中使用Lock
ZTEST_LOCK_5:
| *&———————————————————————*
*& Report ZTEST_LOCK_5 * *& * *&———————————————————————* *& Using Lock – Generic Lock * *& * *&———————————————————————*
REPORT ZTEST_LOCK_5 no standard page heading .
*—Data and Types data: ls_zbook type sbook.
start-of-selection.
*—1st Time Lock **Only Lock Argument: Carrid = ‘AA’ Connid = ‘0017′ write:/ ‘1st Time Lock:’, 20 ‘Only Lock Argument: Carrid = ”AA” Connid = ”0017”’. CALL FUNCTION ‘ENQUEUE_EZ_SBOOK_1′ EXPORTING MODE_SBOOK = ‘X’ CARRID = ‘AA’ CONNID = ‘0017′ * FLDATE = * BOOKID = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ * X_BOOKID = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
*—2nd Time Lock **Lock attempt: Carrid = ‘AA’ Connid = ‘0017′ FLDATE = ‘06.03.2002′ write:/ ‘2nd Time Lock:’, 20 ‘Lock attempt: Carrid = ”AA” Connid = ”0017” FLDATE = ”06.03.2002”’. CALL FUNCTION ‘ENQUEUE_EZ_SBOOK_1′ EXPORTING MODE_SBOOK = ‘X’ CARRID = ‘AA’ CONNID = ‘0017′ FLDATE = ‘06032002′ * BOOKID = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ * X_BOOKID = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
*—3rd Time Lock **Lock attempt: Carrid = ‘AA’ write:/ ‘3rd Time Lock:’, 20 ‘Lock attempt: Carrid = ”AA” ‘. CALL FUNCTION ‘ENQUEUE_EZ_SBOOK_1′ EXPORTING MODE_SBOOK = ‘X’ CARRID = ‘AA’ * CONNID = * FLDATE = * BOOKID = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ * X_BOOKID = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
|
最后执行
可以发现,后面两次lock(一次是小范围,一次是大范围)都Lock失败
(疑问:也许您会说,因为锁类型为X嘛,所以在同一个program中不可累加,所以后两次是失败的;Okay,先不论它们锁的对象是否相同,咱们再来做另外两个程序分program地进行测试)
ZTEST_LOCK_6:
| *&———————————————————————*
*& Report ZTEST_LOCK_6 * *& * *&———————————————————————* *& Using Lock – Generic Lock * *& * *&———————————————————————*
REPORT ZTEST_LOCK_6 no standard page heading .
*—Data and Types data: ls_zbook type sbook.
start-of-selection. *—2nd Time Lock **Lock attempt: Carrid = ‘AA’ Connid = ‘0017′ FLDATE = ‘06.03.2002′ write:/ ‘2nd Time Lock:’, 20 ‘Lock attempt: Carrid = ”AA” Connid = ”0017” FLDATE = ”06.03.2002”’. CALL FUNCTION ‘ENQUEUE_EZ_SBOOK_1′ EXPORTING MODE_SBOOK = ‘X’ CARRID = ‘AA’ CONNID = ‘0017′ FLDATE = ‘06032002′ * BOOKID = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ * X_BOOKID = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
|
当上面Lock 5保持运行状态,执行后:
同时ZTEST_LOCK_7:
| *&———————————————————————*
*& Report ZTEST_LOCK_7 * *& * *&———————————————————————* *& Using Lock – Generic Lock * *& * *&———————————————————————*
REPORT ZTEST_LOCK_7 no standard page heading .
*—Data and Types data: ls_zbook type sbook.
start-of-selection. *—3rd Time Lock **Lock attempt: Carrid = ‘AA’ write:/ ‘3rd Time Lock:’, 20 ‘Lock attempt: Carrid = ”AA” ‘. CALL FUNCTION ‘ENQUEUE_EZ_SBOOK_1′ EXPORTING MODE_SBOOK = ‘X’ CARRID = ‘AA’ * CONNID = * FLDATE = * BOOKID = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ * X_BOOKID = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
|
当上面Lock 5保持运行状态,执行后:
但是,如果我们锁“没有发生冲突”的对象(无论是指定的一条,还是有Generic);如下测试程序:
ZTEST_LOCK_8:
| *&———————————————————————*
*& Report ZTEST_LOCK_8 * *& * *&———————————————————————* *& Using Lock – Generic Lock * *& * *&———————————————————————*
REPORT ZTEST_LOCK_8 no standard page heading .
*—Data and Types data: ls_zbook type sbook.
start-of-selection. *—4th time Lock **Lock attempt: Carrid = ‘BB’ write:/ ‘4th Time Lock:’, 20 ‘Lock attempt: Carrid = ”BB” ‘. CALL FUNCTION ‘ENQUEUE_EZ_SBOOK_1′ EXPORTING MODE_SBOOK = ‘X’ CARRID = ‘BB’ * CONNID = * FLDATE = * BOOKID = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ * X_BOOKID = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
|
当上面Lock 5保持运行状态,执行后:
SM12锁对象:
(前面两条可以不用考虑)可以发现,我们的锁对象的Lock Argument中使用了#的Generic;
可以得出结论:
无论是unique指定一条还是使用了Generic,如果有冲突就会lock 失败.
另外,如果未将client作为lock parameter,但其锁定还是generic;
2.有client的generic实例
继续接上;
现在新建一lock object2,不同于lock object1它带上了Client;
它对表SFLIGHT进行加锁,如下:
我们先来看一下SFLIGHT这张表的all client数据(见前面的client specific一章)
测试程序:
| *&———————————————————————*
*& Report ZTEST_LOCK_9 * *& * *&———————————————————————* *& Using Lock – Generic Lock * *& * *&———————————————————————*
REPORT ZTEST_LOCK_9 no standard page heading .
start-of-selection. *—1st Time Lock **Lock attempt: MANDT = space Carrid = ‘LH’ write:/ ‘1st Time Lock:’, 20 ‘Lock attempt: MANDT = space Carrid = ”LH” ‘. CALL FUNCTION ‘ENQUEUE_EZ_SFLIGHT_1′ EXPORTING MODE_SFLIGHT = ‘X’ MANDT = ‘ ‘ CARRID = ‘LH’ * CONNID = * FLDATE = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
*—2nd Time Lock **Lock Argument: MANDT(omit) Carrid = ‘AA’ write:/ ‘2nd Time Lock:’, 20 ‘Lock Argument: MANDT(omit) Carrid = ”AA” ‘. CALL FUNCTION ‘ENQUEUE_EZ_SFLIGHT_1′ EXPORTING MODE_SFLIGHT = ‘X’ * MANDT = CARRID = ‘LH’ * CONNID = * FLDATE = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
*—3rd Time Lock **Lock attempt: MANDT = 810 Carrid = ‘LH’ write:/ ‘3rd Time Lock:’, 20 ‘Lock attempt: MANDT = 810 arrid = ”LH” ‘. CALL FUNCTION ‘ENQUEUE_EZ_SFLIGHT_1′ EXPORTING MODE_SFLIGHT = ‘X’ MANDT = ‘810′ CARRID = ‘LH’ * CONNID = * FLDATE = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
|
这里执行效果为:
此时SM12中锁对象将为:
如果将上面的第一次与第二次还处顺序则结果为:
此时SM12中锁对象将为:
3.关于Lock Paramert中Generic Argument的结论
综上第一部分与第二部分的2个测试,我们可以得出以下结论:
| (1) Lock Argument是跟着锁定对象的table走的,它有多少个key field,那么我们的锁对象就会包含”真正”的多少个parameter;但我们可以在创建锁对象时省略掉自己业务上不需要的parameter,但这里的省略是指在call 加锁FM时没有这个import参数而已;在实际的锁中,它是以Generic的形式存在着;
(2) Generic这是一个通用的参数;就像我们不能对一条相同的数据加两次锁(注意不是S也不是一个program中的多次E)一样,如果在进地加锁时,发生了”冲突”,那么加锁是不成功的。 (3) 对于Client这个参数比较特殊: * 如果lock parameter中将client排除了,那么其lock针对所有client,是generic的(前面总结第一条也说); * 如果lock parameter中包含client,同时 client的parameter没有被指定(也就是Omit掉了),那么lock 只针对当前的client record进行 * 如果lock parameter中包含client,同时client的parameter指定了,那么lock就针对指定的client record进行 * 如果lock parameter中包含client,同时client的parameter指定为space,那么lock针对所有的client的record进行 |
4.关于Lock的主表与从表
这里再记录一下另一个经常使用到的Lock机能,那就是Lock中设置Secondary Tables.如下:
这个锁对象表明主锁是对表sflight进行X锁定,同时,根据外键锁定SBOOK中的相应记录;
当创建主锁时,会将外键作为一个Generic进行同时上附加/secondary锁;
这里,特别要注意的是,二者的表必须是要用外键关系;
如上,使用上面分别创建的两个锁对象,测试程序:
| *&———————————————————————*
*& Report ZTEST_LOCK_10 * *& * *&———————————————————————* *& Using Lock – Generic Lock * *& * *&———————————————————————*
REPORT ZTEST_LOCK_10 no standard page heading .
start-of-selection.
*—1st Time Lock **Lock attempt: Sflight write:/ ‘1st Time Lock:’, 20 ‘Lock attempt: Sflight’. CALL FUNCTION ‘ENQUEUE_EZ_SFLIGHT_1′ EXPORTING MODE_SFLIGHT = ‘X’ * MANDT = CARRID = ‘AA’ CONNID = ‘0017′ FLDATE = ‘06032002′ * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 .
IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
Uline /(80).
*—2nd Time Lock **Lock attempt: sbook write:/ ‘2nd Time Lock:’, 20 ‘Lock attempt: sbook’. CALL FUNCTION ‘ENQUEUE_EZ_SBOOK_1′ EXPORTING MODE_SBOOK = ‘X’ CARRID = ‘AA’ CONNID = ‘0017′ FLDATE = ‘06032002′ * BOOKID = * X_CARRID = ‘ ‘ * X_CONNID = ‘ ‘ * X_FLDATE = ‘ ‘ * X_BOOKID = ‘ ‘ _SCOPE = ‘2′ _WAIT = ‘ ‘ _COLLECT = ‘ ‘ EXCEPTIONS FOREIGN_LOCK = 1 SYSTEM_FAILURE = 2 OTHERS = 3 . IF SY-SUBRC <> 0. write:/ ‘Lock Failed!’. ELSE. write:/ ‘Lock Successed!’. ENDIF.
|
执行结果
此时SM12中查看锁对象
可以发现:当在上主锁时,会对从表也进行加锁(外键以Generic对待)。