inicio mail me! sindicaci;ón

Atomares Einfügen in PostgreSQL

Oft steht man vor dem Problem, einen Datensatz anhand eines Kriteriums zu finden bzw. ihn, falls nicht vorhanden, einzufügen. Bei derartigen Operationen ist es wichtig darauf zu achten, dass nicht mehrere Prozesse, die quasi gleichzeitig diesen Datensatz suchen, eine race condition hervorrufen.
Hier eine Lösung mittels stored procedure für postgresql. Dabei wird eine race condition zwischen Suche und Einfügen vermieden und nur minimales Locking gebraucht:

CREATE OR REPLACE FUNCTION findOrCreate(
  IN criterion_in text, 
  OUT id int, OUT is_new bool) AS 
$$
DECLARE 
BEGIN
  LOCK TABLE my_table;
  SELECT false, id FROM my_table WHERE criterion=criterion_in INTO is_new, id;

  IF id IS NULL THEN
    INSERT INTO 
      my_table (criterion) 
    VALUES 
      (criterion_in) 
    RETURNING id INTO id;
    
    SELECT true INTO is_new;
  END IF;

  RETURN;
END
$$ language plpgsql;

Man beachte die praktischen OUT-Parameter, die es ermöglichen, diese Funktion wie folgt aufzurufen:

SELECT id, is_new FROM findOrCreate(criterion);

Rückgabewerte sind id und is_new, die einem die Datenbank-Id angeben, und ob diese neu angelegt wurde.

Der Table-Lock wird beim Beenden der Funktion (die immer implizit eine Transaktion ist) automatisch beendet.

Schreibe einen Kommentar