SAP 锁的机制和利用1

*---------------------------- 综述 SAP锁机制 ----------------------------
一、SAP为什么要设置锁:
   1,保持数据的一致性
     如果几个用户要访问同样的资源,需要找到一种同步访问的方法去保持数据的一致性。比如说,在航班预订系
统中,需要检查还有没有空座位,当检查的时候,你不想别人修改重要的数据(空座位的数量)。
   2,仅仅用Database锁是不够的
     数据库管理系统物理锁定了要修改的行记录,其他用户要等到数据库锁释放才能访问这个记录。
     在SAP系统中,当一个新屏幕显示的时候会释放掉Database锁,因为屏幕的改变会触发一个隐式的DB COMMIT
。如果数据是从好几个屏幕收集来的话,而且在这段时间内这些数据会分别被锁定,仅仅用Database锁就不够了。
     SAP系统在应用服务器层面有一个全局的LOCK TABLE,可以用来设置逻辑锁来锁定相关的表条目,并有
ENQUEUE工作进程来管理这些锁。SAP锁是一种逻辑意义上的锁,有可能你锁定的表条目在DATABASE上根本就
不存在。

二、锁对象和其对应的Function Module
    在SE11里创建锁对象,自定义的锁对象都必须以EZ或者EY开头来命名。一个锁对象里只包含一个PRIMARY
TABLE,可以包含若干个SECONDARY TABLE,锁的模式有三种:E,S,X。LOCK PARAMETERS里填写你要根
据哪些字段来锁定表条目。
    模式E:当更改数据的时候设置为此模式。
    模式S:本身不需要更改数据,但是希望显示的数据不被别人更改。
    模式X:和E类似,但是不允许累加,完全独占。
    如果你在一个程序里成功对一个锁对象加锁之后,如果模式为E,其他用户不能再对这个锁对象加E、X、S模式
的任意一种锁;
    如果你在一个程序里成功对一个锁对象加锁之后,如果模式为X,其他用户不能再对这个锁对象加E、X、S模式
的任意一种锁;
    如果你在一个程序里成功对一个锁对象加锁之后,如果模式为S,其他用户不能再对这个锁对象加E、X模式的
锁,但是可以加S模式的锁;
    如果你在一个程序里成功对一个锁对象加锁之后,如果模式为E,在这个程序,你还可以再对这个锁对象加E、  !!!
S模式的锁,X模式的不可以。
    如果你在一个程序里成功对一个锁对象加锁之后,如果模式为X,在这个程序,你不可以再对这个锁对象加E、
X、S模式的锁。
    如果你在一个程序里成功对一个锁对象加锁之后,如果模式为S,在这个程序,你还可以再对这个锁对象加S模
式的锁,如果没有别的用户对其加S模式的锁,那么你还可以对其加E模式的锁。X模式的不可以。
    当激活锁对象的时候,系统会自动创建两个FM,ENQUEUE_<锁对象名>和DEQUEUE_<锁对象名>,分别用来锁
定和解锁。

三、锁定和解锁
    当用逻辑锁来锁定表条目的时候,系统会自动向LOCK TABLE中写入记录。
    当调用设置锁的FM时,LOCK PARAMETERS如果没有指明,系统会锁定整个表。当然,LOCK PARAMETER:
CLIENT有点特殊,如果不指定,默认是SY-MANDT;如果指定相应的CLIENT,会锁定对应CLIENT上的相应的表
记录;如果设置为SPACE,则锁定涉及所有的CLIENT。
    当逻辑锁设置失败后,一般会有两种例外。一个是EXCEPTION:FOREIGN_LOCK,意思是已经被锁定了;另一
个是EXCEPTION:SYSTEM_FAILURE。
    有些情况下,程序中设置成功的逻辑锁会隐式的自己解锁。比如说程序结束发生的时候(MESSAGE TYPE为A
或者X的时候),使用语句LEAVE PROGRAM,LEAVE TO TRANSACTION,或者在命令行输入/n回车以后。
    在程序的结束可以用DEQUEUE FUNCTION MODULE来解锁(当然如果你不写这个,程序结束的时候也会自动的
解锁),这个时候,系统会自动从LOCK TABLE把相应的记录删除。使用DEQUEUE FUNCTION MODULE来解锁的
时候,不会产生EXCEPTION。要解开你在程序中创建的所有的逻辑锁,可以用FM:DEQUEUE_ALL.
   
四、上锁的一般步骤
    先上锁,上锁成功之后,从数据库取数据,然后更改数据,接着更新到数据库,最后解锁。按照这个步骤,才
能保证更改完全运行在锁的保护机制下。
 
S:共享锁  E:写锁  X:排他锁

*1. 使用TCODE: SE11,選擇最後一項[加鎖物件],輸入物件名稱(注意一定要以字母‘EZ’或 ‘EY’開頭,這是SAP內部規定的,如EZTESTING)
*2. 輸入名稱後,按新增,進入界面後輸入要加鎖的Table名,及加鎖類型(E:專用,累計;S:共享;X:專用,不累計)。保存後,系統會自動產生兩個函數: ENQUEUE_EZTESTING(加鎖)和 DEQUEUE_EZTESTING(解鎖)。
*3. 然後在更改記錄前調用加鎖函數對記錄進行鎖定,在修改完成或退出修改後一定要對記錄進行解鎖。
*4. 自定义加鎖及解鎖代碼(参照系统生成代码):(Table:ZTESTING,key: fieldKey)

FORM lock_record USING p_key.
  DATA: it_seqg3 TYPE seqg3 OCCURS 01 WITH HEADER LINE.
  DATA: gname LIKE seqg3-gname, garg LIKE seqg3-garg.
  DATA: BEGIN OF %ztesting,
          mandt    TYPE ztesting-mandt,
          fieldkey TYPE ztesting-fieldkey,
        END OF %ztesting.
*---锁定函数初始化:
  CALL 'C_ENQ_WILDCARD' ID 'HEX0' FIELD %ztesting.

*---对关键字的赋值
  MOVE sy-mandt TO: %ztesting-mandt.
  IF NOT p_key IS INITIAL.
    MOVE p_key TO: %ztesting-fieldkey.
  ENDIF.
  gname = 'ZTESTING'.
  garg = %ztesting.

*---读取是否已经被锁定
  CALL FUNCTION 'ENQUEUE_READ'
    EXPORTING
      gclient = sy-mandt
      gname   = gname
      garg    = garg
    TABLES
      enq     = it_seqg3.

  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.

  IF it_seqg3 IS NOT INITIAL.
    DATA:cmessage(100) TYPE c.
    CONCATENATE p_key '正由' it_seqg3-guname '處理!' INTO cmessage.
    CONDENSE cmessage.
    MESSAGE cmessage TYPE 'E'.
  ELSE.
*---开始锁定记录
*加锁时,不管这个表中有没有这个条目,都会加锁成功(即sy-subrc = 0)。加锁后,再操作同一条目,会提示XXX正在处理!
    CALL FUNCTION 'ENQUEUE_EZTESTING'
      EXPORTING
        mode_ztesting  = 'E'
        mandt          = sy-mandt
        zfieldkey      = p_key
        x_zfieldkey    = ' '
        _scope         = '2'
        _wait          = ' '
        _collect       = ' '
      EXCEPTIONS
        foreign_lock   = 1
        system_failure = 2
        OTHERS         = 3.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
  ENDIF.
ENDFORM.                    "lock_record

*------------------------------ 解鎖 -------------------------------------
FORM unlock_record USING p_key.
  CALL FUNCTION 'DEQUEUE_EZTESTING'
    EXPORTING
      mode_ztesting = 'E'
      mandt         = sy-mandt
      zfieldkey     = p_key
      x_zfieldkey   = ' '
      _scope        = '3'
      _synchron     = ' '
      _collect      = ' '.

ENDFORM.                    "unlock_record

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值