Oracle 11g insert + update导致锁定

时间:2016-11-03 13:38:55

标签: oracle oracle11g locking

我正在使用oracle 11g数据库,而且我遇到了锁定问题。

我有2个会话,我按如下方式执行:

  • (会话1)使用已知id
  • 插入table1
  • (会话2)使用另一个已知的id => INSERT到table1没有锁
  • (会话1)来自table1的更新,其中在第一步中插入了id = id => 锁定

在两个存储过程(插入和更新)中,我包含以下子句:

LOCK TABLE table1 IN ROW EXCLUSIVE MODE;

我认为问题在于oracle正在插入一个表锁,或者它只是没有得到我正在尝试更新的行,虽然,不是行级表锁的目标??

提前感谢您的帮助!

我的剧本:

CRETE TABLE

    CREATE TABLE ARGOXP.T_AREA
    (
      ARE_ID      INTEGER,
      ARE_NOMBRE  VARCHAR2(80 BYTE)                 NOT NULL,
      ARE_DESCRI  VARCHAR2(1000 BYTE),
      ARE_ACTIVO  NUMBER(1)                         NOT NULL
    )
    TABLESPACE ARGOXP
    PCTUSED    0
    PCTFREE    10
    INITRANS   1
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                PCTINCREASE      0
                BUFFER_POOL      DEFAULT
               )
    LOGGING 
    NOCOMPRESS 
    NOCACHE
    NOPARALLEL
    MONITORING;



CREATE UNIQUE INDEX ARGOXP.PK_T_AREA ON ARGOXP.T_AREA
(ARE_ID)
LOGGING
TABLESPACE ARGOXP
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
NOPARALLEL;


CREATE UNIQUE INDEX ARGOXP.UK_ARE_NOMBRE ON ARGOXP.T_AREA
(ARE_NOMBRE)
LOGGING
TABLESPACE ARGOXP
PCTFREE    10
INITRANS   2
MAXTRANS   255
STORAGE    (
            INITIAL          64K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
            BUFFER_POOL      DEFAULT
           )
NOPARALLEL;


ALTER TABLE ARGOXP.T_AREA ADD (
  CONSTRAINT PK_T_AREA
 PRIMARY KEY
 (ARE_ID)
    USING INDEX 
    TABLESPACE ARGOXP
    PCTFREE    10
    INITRANS   2
    MAXTRANS   255
    STORAGE    (
                INITIAL          64K
                MINEXTENTS       1
                MAXEXTENTS       UNLIMITED
                PCTINCREASE      0
               ),
  CONSTRAINT UK_ARE_NOMBRE
 UNIQUE (ARE_NOMBRE)
    USING INDEX 
    TABLESPACE ARGOXP
    PCTFREE    10
    INITRANS   2
    MAXTRANS   255
    STORAGE    (
                INITIAL    

  64K
            MINEXTENTS       1
            MAXEXTENTS       UNLIMITED
            PCTINCREASE      0
           ));

商店程序

CREATE OR REPLACE PROCEDURE ARGOXP."P_T_AREA_I_PK" 
(
pARE_ID T_AREA.ARE_ID%TYPE,
pARE_NOMBRE T_AREA.ARE_NOMBRE%TYPE,
pARE_DESCRI T_AREA.ARE_DESCRI%TYPE := NULL,
pARE_ACTIVO T_AREA.ARE_ACTIVO%TYPE
)
AS
BEGIN
LOCK TABLE T_AREA IN ROW EXCLUSIVE MODE;

  INSERT INTO T_AREA
    ( ARE_ID,
      ARE_NOMBRE,
      ARE_DESCRI,
      ARE_ACTIVO
    )
  VALUES
    ( pARE_ID,
      pARE_NOMBRE,
      pARE_DESCRI,
      pARE_ACTIVO
    );
END;
/



CREATE OR REPLACE PROCEDURE ARGOXP."P_T_AREA_U_PK" 
(
pARE_ID T_AREA.ARE_ID%TYPE,
pARE_NOMBRE T_AREA.ARE_NOMBRE%TYPE,
pARE_DESCRI T_AREA.ARE_DESCRI%TYPE := NULL,
pARE_ACTIVO T_AREA.ARE_ACTIVO%TYPE
)
AS
BEGIN
LOCK TABLE T_AREA IN ROW EXCLUSIVE MODE;

  UPDATE
    T_AREA
  SET
    ARE_ID = pARE_ID,
      ARE_NOMBRE = pARE_NOMBRE,
      ARE_DESCRI = pARE_DESCRI,
      ARE_ACTIVO = pARE_ACTIVO
  WHERE
    ARE_ID = pARE_ID
;
END;
/

最新更新

我们最近几天一直在努力解决这个问题,我们希望分享最新的更新。我们在不使用存储过程的情况下在2个会话中执行插入和更新,这导致非锁定。之后,我们为插入和更新创建了新的存储过程,没有参数。我们只包含存储过程定义和脚本来执行插入或更新。这导致非锁定!但是当我们用参数调用存储过程时,我们得到了锁。

我按照执行步骤来获取锁定:

(FIRST) 在第1场会议中:

DECLARE 
  PARE_ID NUMBER;
  PARE_NOMBRE VARCHAR2(80);
  PARE_DESCRI VARCHAR2(1000);
  PARE_ACTIVO NUMBER;

BEGIN 
  PARE_ID := 70;
  PARE_NOMBRE := '70';
  PARE_DESCRI := '70';
  PARE_ACTIVO := 1;

  ARGOXP.P_T_AREA_I_PK ( PARE_ID, PARE_NOMBRE, PARE_DESCRI, PARE_ACTIVO );
END; 

(第二) 在第2场会议

DECLARE 
  PARE_ID NUMBER;
  PARE_NOMBRE VARCHAR2(80);
  PARE_DESCRI VARCHAR2(1000);
  PARE_ACTIVO NUMBER;

BEGIN 
  PARE_ID := 71;
  PARE_NOMBRE := '71';
  PARE_DESCRI := '71';
  PARE_ACTIVO := 1;

  ARGOXP.P_T_AREA_I_PK ( PARE_ID, PARE_NOMBRE, PARE_DESCRI, PARE_ACTIVO );
END; 

(第三)在第二场会议

DECLARE 
  PARE_ID NUMBER;
  PARE_NOMBRE VARCHAR2(80);
  PARE_DESCRI VARCHAR2(1000);
  PARE_ACTIVO NUMBER;

BEGIN 
  PARE_ID := 1;
  PARE_NOMBRE := 'update number 1';
  PARE_DESCRI := 'update number 2';
  PARE_ACTIVO := 1;

  ARGOXP.P_T_AREA_U_PK ( PARE_ID, PARE_NOMBRE, PARE_DESCRI, PARE_ACTIVO );
END; 

我们在这一步中得到了锁。

我们还使用sysdba用户执行以下查询:

SELECT b.OBJECT_NAME, c.ROW_WAIT_OBJ#,c.ROW_WAIT_FILE#,c.ROW_WAIT_BLOCK#,c.ROW_WAIT_ROW#
   FROM v$locked_object a, dba_objects b, v$session c    
WHERE a.object_id = b.object_id    
    AND a.SESSION_ID = c.sid(+);

获得以下结果:

enter image description here

1 个答案:

答案 0 :(得分:1)

我们发现了问题。我们有另一个表TABLE_2,它引用了表T_AREA(名为AREA_ID的外键字段)。当我们有一个外键但我们在该表中没有索引时,oracle会自动锁定整个表。

因此,解决方案是在TABLE_2中为FK字段添加索引(在本例中为ARE_ID)