SAP ABAP编程 数据库表锁机制

*---------------------------- 综述 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

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

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值