在 Oracle 中 FK 的情况下查询 FOR UPDATE NOWAIT
Query on FOR UPDATE NOWAIT in case of FK in Oracle
我有一个 table tab1 (t_id, status)
和 table tab2 (id, t_id, status)
其中 t_id.tab2
有外键引用 tab1.t_id
.
假设 Oracle 会话 s1 获取 SELECT FOR UPDATE NOWAIT
锁定 tab1
中的记录 t_id=123
。
虽然 NOWAIT
锁仍由 s1 在 tab1
上持有,但另一个会话 s2 可以使用 tab2.t_id=123
更新 tab2
中的记录吗(FK)?
正如评论中指出的那样,使用 locking read (SELECT ... FOR UPDATE
) 语句发出的行锁不会传播到子 table 声明 FOREIGN KEY
的地方。
这里有一个例子可以证明这一点:
-- Set up schema
CREATE TABLE tab1 (t_id NUMBER(10), status VARCHAR2(10), PRIMARY KEY (t_id));
CREATE TABLE tab2 (id NUMBER(10), t_id NUMBER(10), status VARCHAR2(10),
PRIMARY KEY (id),
CONSTRAINT fk_tab1 FOREIGN KEY (t_id) REFERENCES tab1 (t_id));
INSERT INTO tab1 (t_id, status) VALUES (123, 'Status1');
INSERT INTO tab1 (t_id, status) VALUES (234, 'Status1');
INSERT INTO tab2 (id, t_id, status) VALUES (1, 123, 'Status2');
INSERT INTO tab2 (id, t_id, status) VALUES (2, 234, 'Status2');
COMMIT;
以下脚本成功执行(例如在 Oracle SQLDeveloper 中):
SET autocommit 0;
SELECT * FROM tab1 WHERE t_id=123 FOR UPDATE NOWAIT;
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE tab1 SET status = 'Status2' WHERE t_id = 234;
UPDATE tab2 SET t_id = 234, status = 'Status2' WHERE t_id = 123;
COMMIT;
END;
因此,可以更改 tab1
中的其他行以及 tab2
中指向 tab1
.
中锁定行的外键列
不出所料,正在尝试更新锁定的行:
SELECT * FROM tab1 WHERE t_id=123 FOR UPDATE NOWAIT;
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE tab1 SET status = 'Status2' WHERE t_id = 123;
COMMIT;
END;
... 将失败并显示错误消息:
ORA-00060: deadlock detected while waiting for resource
我有一个 table tab1 (t_id, status)
和 table tab2 (id, t_id, status)
其中 t_id.tab2
有外键引用 tab1.t_id
.
假设 Oracle 会话 s1 获取 SELECT FOR UPDATE NOWAIT
锁定 tab1
中的记录 t_id=123
。
虽然 NOWAIT
锁仍由 s1 在 tab1
上持有,但另一个会话 s2 可以使用 tab2.t_id=123
更新 tab2
中的记录吗(FK)?
正如评论中指出的那样,使用 locking read (SELECT ... FOR UPDATE
) 语句发出的行锁不会传播到子 table 声明 FOREIGN KEY
的地方。
这里有一个例子可以证明这一点:
-- Set up schema
CREATE TABLE tab1 (t_id NUMBER(10), status VARCHAR2(10), PRIMARY KEY (t_id));
CREATE TABLE tab2 (id NUMBER(10), t_id NUMBER(10), status VARCHAR2(10),
PRIMARY KEY (id),
CONSTRAINT fk_tab1 FOREIGN KEY (t_id) REFERENCES tab1 (t_id));
INSERT INTO tab1 (t_id, status) VALUES (123, 'Status1');
INSERT INTO tab1 (t_id, status) VALUES (234, 'Status1');
INSERT INTO tab2 (id, t_id, status) VALUES (1, 123, 'Status2');
INSERT INTO tab2 (id, t_id, status) VALUES (2, 234, 'Status2');
COMMIT;
以下脚本成功执行(例如在 Oracle SQLDeveloper 中):
SET autocommit 0;
SELECT * FROM tab1 WHERE t_id=123 FOR UPDATE NOWAIT;
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE tab1 SET status = 'Status2' WHERE t_id = 234;
UPDATE tab2 SET t_id = 234, status = 'Status2' WHERE t_id = 123;
COMMIT;
END;
因此,可以更改 tab1
中的其他行以及 tab2
中指向 tab1
.
不出所料,正在尝试更新锁定的行:
SELECT * FROM tab1 WHERE t_id=123 FOR UPDATE NOWAIT;
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
UPDATE tab1 SET status = 'Status2' WHERE t_id = 123;
COMMIT;
END;
... 将失败并显示错误消息:
ORA-00060: deadlock detected while waiting for resource