Wie bereits in den Kommentaren darauf hingewiesen, gab die Zeilensperre mit den Verriegelungs lesen (SELECT ... FOR UPDATE
) statement propagiert nicht das Kind Tisch, an dem die FOREIGN KEY
deklariert wird.
Hier ist ein Beispiel, das dies zeigt:
-- 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;
das folgende Skript, das die AUTONOMOUS_TRANSACTION
Pragma verwendet, eine neue Transaktion für die Ausstellung erfolgreich ausgeführt wird (zB in 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;
So Es ist möglich, andere Zeilen in tab1
und auch die Fremdschlüsselspalte in tab2
zu ändern, die auf die gesperrte Zeile in tab1
zeigt.
Wie erwartet, versuchen, die gesperrte Zeile zu aktualisieren:
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;
... wird mit der Fehlermeldung fehlschlagen:
ORA-00060: deadlock detected while waiting for resource
Ja, sie unabhängig sind. Berücksichtigen Sie, dass Sie das Feld t_id sogar ändern und auf einen anderen Datensatz verweisen können. – pablomatico
Danke für die schnelle Antwort pablomatico. Ich werde es versuchen – hnadiger
Welche Version von Oracle? Ist 't_id' in' tab2' indiziert? Und aktualisieren Sie die 't_id' in der untergeordneten Tabelle oder ein anderes Attribut der Zeile? Das Leben wird ein bisschen klebriger, wenn Sie eine alte Version von Oracle verwenden, Ihre Fremdschlüssel nicht indiziert sind und Sie versuchen, die 't_id' in' tab2' zu aktualisieren. –