我正在使用 Oracle 11g 数据库,但遇到锁定问题。
我有 2 个会话,执行方式如下:
在两个存储过程(插入和更新)中,我都包含以下子句:
以行独占模式锁定表 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(+);
得到以下结果:
我们发现了问题。我们还有另一个表 TABLE_2,它引用了表 T_AREA(称为 AREA_ID 的外键字段)。当我们有外键但该表中没有索引时,Oracle 会自动锁定整个表。
因此,解决方案是在 TABLE_2 中为 FK 字段(本例中为 ARE_ID)添加索引