首页 > 代码库 > 4.锁——避免重复启动同一程序

4.锁——避免重复启动同一程序

/*************************************************
四、主题: 锁——避免重复启动同一程序

   锁 捕捉唯一性

*************************************************/

=============================================================================
 CREATE TABLE TEST5
 (
  ID    NUMBER(5),
  NAME  VARCHAR(10),
  UIID   NUMBER(5)
 );
 
 INSERT INTO TEST5 VALUES(1,‘A‘,NULL);
 INSERT INTO TEST5 VALUES(2,‘B‘,NULL);
 INSERT INTO TEST5 VALUES(3,‘C‘,NULL);
 INSERT INTO TEST5 VALUES(4,‘Aa‘,1);
 INSERT INTO TEST5 VALUES(5,‘Ab‘,1);   
 
=============================================================================

4.1.判断是否是否加上了锁
 --SESSION_1
 UPDATE TEST5
    SET NAME = NAME;
   
 不提交,然后新打开一个窗口,执行下面语句:
 --SESSION_2
 SELECT * FROM TEST5; --能正常获取数据
 SELECT * FROM TEST5 FOR UPDATE NOWAIT; --资源站正忙,无法获取数据,说明SESSION_1 已经加上了锁。
 
 --若SESSION_1 提交了,则 SESSION_2 就能得到数据
 
4.2.在得知被锁后,退出不执行后续语句
  SESSION_1 不提交修改。
  --SESSION_2
  -----------------------------------------------
    DECLARE
     E_FAILED_TO_LOCK EXCEPTION;
     V_ID NUMBER;
     PRAGMA EXCEPTION_INIT (E_FAILED_TO_LOCK,-54);
    BEGIN
     SELECT ID INTO V_ID FROM TEST5 WHERE ID=1 FOR UPDATE NOWAIT;
    EXCEPTION
    WHEN E_FAILED_TO_LOCK THEN
         RAISE_APPLICATION_ERROR(-20004,‘IT‘S LOCKED!‘);
    null; 
    END;
    /

  -----------------------------------------------
    --提示:IT‘S LOCKED!
    若想执行正确,可以先提交SESSION_1.
   
4.3. 与上面一样,利用主键,防止重复记录。
     若是INSERT INTO 时,主键冲突,则EXCEPTION 执行NULL,忽略异常继续前进。
     --此处,一般用MERGE INTO 来解决最好。
  
4.4.获取机器IP\终端号\SID等
    SELECT USERENV(‘SESSIONID‘) FROM DUAL;
    SELECT USERENV(‘TERMINAL‘)  FROM DUAL;
    SELECT SYS_CONTEXT(‘USERENV‘,‘IP_ADDRESS‘) FROM DUAL;
    SELECT SYS_CONTEXT(‘USERENV‘,‘CURRENT_USER‘) FROM DUAL;
    SELECT SID FROM V$MYSTAT WHERE ROWNUM=1;
   
4.5.构造检查机制,防止失败执行报错,给出提示。