正如注释中所指出的,使用锁定 read ( SELECT ... FOR UPDATE) 语句发出的行锁不会传播到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;
Run Code Online (Sandbox Code Playgroud)
以下脚本使用 pragmaAUTONOMOUS_TRANSACTION来发出新事务,成功执行(例如在 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;
Run Code Online (Sandbox Code Playgroud)
因此,可以更改 中的其他行以及指向 中锁定行的tab1外键列。tab2tab1
正如预期的那样,尝试更新锁定的行:
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;
Run Code Online (Sandbox Code Playgroud)
...将失败并显示错误消息:
ORA-00060: 等待资源时检测到死锁
| 归档时间: |
|
| 查看次数: |
640 次 |
| 最近记录: |