2015-10-27 4 views
5

Ich habe eine Tabelle tab1 (t_id, status) und Tabelle tab2 (id, t_id, status) wo in t_id.tab2 hat Fremdschlüssel Bezug auf tab1.t_id.Frage auf FOR UPDATE NOWAIT im Falle von FK in Oracle

Angenommen, eine Oracle-Sitzung s1 erwirbt SELECT FOR UPDATE NOWAIT Sperre für einen Datensatz in tab1 mit t_id=123.

Während NOWAIT Sperre noch von s1 auf tab1 gehalten wird, kann eine andere Sitzung s2 Verbuchungssatz in tab2 mit tab2.t_id=123 (FK)?

+0

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

+0

Danke für die schnelle Antwort pablomatico. Ich werde es versuchen – hnadiger

+0

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. –

Antwort

0

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