SAP ABAP编程 数据库表锁机制

来源:互联网 发布:人工智能 科普书籍推荐 编辑:程序博客网 时间:2024/04/28 05:15
*---------------------------- 综述 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,锁的模式有三种:ESXLOCK PARAMETERS里填写你要根
据哪些字段来锁定表条目。
    
模式E:当更改数据的时候设置为此模式。
    
模式S:本身不需要更改数据,但是希望显示的数据不被别人更改。
    
模式X:和E类似,但是不允许累加,完全独占。
    
如果你在一个程序里成功对一个锁对象加锁之后,如果模式为E,其他用户不能再对这个锁对象加EXS模式
的任意一种锁;
    
如果你在一个程序里成功对一个锁对象加锁之后,如果模式为X,其他用户不能再对这个锁对象加EXS模式
的任意一种锁;
    
如果你在一个程序里成功对一个锁对象加锁之后,如果模式为S,其他用户不能再对这个锁对象加EX模式的
锁,但是可以加S模式的锁;
    
如果你在一个程序里成功对一个锁对象加锁之后,如果模式为E,在这个程序,你还可以再对这个锁对象加E  !!!
S
模式的锁,X模式的不可以。
    
如果你在一个程序里成功对一个锁对象加锁之后,如果模式为X,在这个程序,你不可以再对这个锁对象加E
X
S模式的锁。
    
如果你在一个程序里成功对一个锁对象加锁之后,如果模式为S,在这个程序,你还可以再对这个锁对象加S
式的锁,如果没有别的用户对其加S模式的锁,那么你还可以对其加E模式的锁。X模式的不可以。
    
当激活锁对象的时候,系统会自动创建两个FMENQUEUE_<锁对象名>DEQUEUE_<锁对象名>,分别用来锁
定和解锁。

三、锁定和解锁
    
当用逻辑锁来锁定表条目的时候,系统会自动向LOCK TABLE中写入记录。
    
当调用设置锁的FM时,LOCK PARAMETERS如果没有指明,系统会锁定整个表。当然,LOCK PARAMETER
CLIENT
有点特殊,如果不指定,默认是SY-MANDT;如果指定相应的CLIENT,会锁定对应CLIENT上的相应的表
记录;如果设置为SPACE,则锁定涉及所有的CLIENT
    
当逻辑锁设置失败后,一般会有两种例外。一个是EXCEPTIONFOREIGN_LOCK,意思是已经被锁定了;另一
个是EXCEPTIONSYSTEM_FAILURE
    
有些情况下,程序中设置成功的逻辑锁会隐式的自己解锁。比如说程序结束发生的时候(MESSAGE TYPEA
或者X的时候),使用语句LEAVE PROGRAMLEAVE TO TRANSACTION,或者在命令行输入/n回车以后。
    
在程序的结束可以用DEQUEUE FUNCTION MODULE来解锁(当然如果你不写这个,程序结束的时候也会自动的
解锁),这个时候,系统会自动从LOCK TABLE把相应的记录删除。使用DEQUEUE FUNCTION MODULE来解锁的
时候,不会产生EXCEPTION。要解开你在程序中创建的所有的逻辑锁,可以用FMDEQUEUE_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.
  
DATAit_seqg3 TYPE seqg3 OCCURS 01 WITH HEADER LINE.
  
DATAgname LIKE seqg3-gnamegarg LIKE seqg3-garg.
  
DATABEGIN 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(100TYPE 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

来源: http://2006057145.blog.163.com/blog/static/1747222022011073723234/

0 0
原创粉丝点击