Prevent and/or detect cycles in postgres

后端 未结 4 798
刺人心
刺人心 2020-12-06 12:28

Assuming a schema like the following:

CREATE TABLE node (
  id       SERIAL PRIMARY KEY,
  name     VARCHAR,
  parentid INT REFERENCES node(id)
);

4条回答
  •  借酒劲吻你
    2020-12-06 13:10

    While the current accepted answer by @Erwin Brandstetter is ok when you process one update/insert at a time, it still can fail when considering concurrent execution.

    Assume the table content defined by

    INSERT INTO node VALUES
    (1, 'A', NULL),
    (2, 'B', 1),
    (3, 'C', NULL),
    (4, 'D', 3);
    

    and then in one transaction, execute

    -- transaction A
    UPDATE node SET parentid = 2 where id = 3;
    

    and in another

    -- transaction B
    UPDATE node SET parentid = 4 where id = 1;
    

    Both UPDATE commands will succeed, and you can afterwards commit both transactions.

    -- transaction A
    COMMIT;
    
    -- transaction B
    COMMIT;
    

    You will then have a cycle 1->4->3->2->1 in the table. To make it work, you will either have to use isolation level SERIALIZABLE or use explicit locking in the trigger.

提交回复
热议问题