Discuss New Concept,New Technic,New Tools, Including EAI,BPM,SOA,Tibco,IBM MQ,Tuxedo, Cloud,Hadoop,NoSQL,J2EE,Ruby,Scala,Python, Performance,Scalability,Distributed,HA, Social Network,Machine Learning.

SAP

Sep 052011
 
 [repost ]关于SAP Lock (二)  September 5, 2011  Posted by on September 5, 2011 at 8:58 pm ERP, SAP Tagged with: , , ,  No Responses »

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对待)。