Oracle 11g 插入+更新导致锁

问题描述 投票:0回答:1

我正在使用 Oracle 11g 数据库,但遇到锁定问题。

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

  • (会话 1)使用已知 id 插入 table1
  • (会话 2)使用另一个已知 id 插入 table1 => 无锁
  • (会话 1)从 table1 更新,其中 id = 第一步中插入的 id => Lock

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

以行独占模式锁定表 table1;

我认为问题是oracle在插入中设置了表锁,或者只是没有获取我要更新的行,但这不是行级表锁的目标吗?

预先感谢您的帮助!


我附上我的脚本:

创建表

    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;
/

最新更新

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

我附上获得锁的执行步骤:

(第一) 在第 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

oracle-database oracle11g locking
1个回答
1
投票

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

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

© www.soinside.com 2019 - 2024. All rights reserved.