2017-10-19 22 views
1

J'utilise une requête comme ceci:Est-ce que INSERT ... SELECT une transaction atomique?

INSERT INTO table 
    SELECT * FROM table2 t2 
     JOIN ... 
     ... 
     WHERE table2.date < now() - '1 day'::INTERVAL 
    FOR UPDATE OF t2 SKIP LOCKED 
ON CONFLICT (...) 
    DO UPDATE SET ... 
RETURNING *; 

Ma question porte sur FOR UPDATE t2 SKIP LOCKED. Devrais-je l'utiliser ici? Ou Postgres verrouillera-t-il automatiquement ces lignes avec INSERT SELECT ON CONFLICT jusqu'à la fin de la transaction?

Mon but est d'empêcher les autres applications de capturer (simultanément) des lignes avec le SELECT qui sont déjà capturées par celui-ci.

+1

Il n'y a aucune raison de verrouiller automatiquement les lignes d'une sous-requête dans 'INSERT ... ON CONFLICT' car la sous-commande est exécutée une seule fois. Vous devez verrouiller les lignes explicitement. – klin

Répondre

1

Oui, FOR UPDATE OF t2 SKIP LOCKED est la bonne approche pour empêcher les conditions de course par défaut Read Committed transaction isolation. Le SKIP LOCKED ajouté empêche également les blocages. Sachez que les transactions concurrentes peuvent chacune recevoir un jeu partiel du SELECT - tout ce qui pourrait être verrouillé en premier.

Alors que toute transaction est atomique dans Postgres, il ne serait pas empêcher une autre transaction (également atomique) de la sélection (et l'insertion - ou du moins essayer) la même ligne, parce que SELECTsansFOR UPDATE ne prend pas exclusive lock.

Le Postgres manual about transactions:

Une transaction est dite atomique: du point de vue des autres transactions, il arrive soit complètement ou pas du tout.

connexes:


Clarifications:

  • Une commande SQL DML comme INSERT est toujours automatiquement atomique, car il ne peut pas fonctionner en dehors d'une transaction. Mais vous ne pouvez pas dire que INSERTest une transaction. Mauvaise terminologie.

  • En Postgres tous verrous sont maintenus jusqu'à et libérés à la fin de la transaction en cours.