Puis-je sélectionner des données insérées dans la même transaction non engagée?

21

C'est peut-être une question stupide pour les débutants, mais je ne trouve aucune réponse nulle part. Partout où j'ai lu ce Transaction Isolationqui résout la visibilité des données dans les transactions simultanées. Ma préoccupation est le comportement au sein d'une même transaction.

Si je lance une transaction, insère des données, vais-je pouvoir les sélectionner juste après - toujours dans la même transaction, mais non validée? Si oui, ce comportement peut-il être modifié d'une manière similaire à l'isolement de transaction mentionné dans le cas de transactions simultanées?

Pour être précis, je cible PostgreSQL 9.4.

Numéro quatre
la source

Réponses:

17

Oui.
Tout ce que vous avez fait dans la même transaction est visible par les commandes ultérieures de la même transaction. Tout simplement pas à d'autres transactions jusqu'à ce qu'elles soient engagées. Cela est vrai pour tous les niveaux d'isolement, sauf Read uncommittedlorsque des "lectures incorrectes" sont possibles (mais cela n'affecte pas votre question en soi).

Il est implémenté avec le modèle MVCC (Multiversion Concurrency Control) basé sur la TransactionIddétermination de l'âge et de la visibilité pour chaque ligne de table. Chaque nouvelle version de ligne écrite dans la même transaction devient la même xminet est considérée comme étant arrivée "en même temps".

Il existe un cas d'angle pour plusieurs CTE (Common Table Expression) dans la même commande. On pourrait penser que celles-ci sont exécutées séquentiellement, mais à moins qu'un CTE ne fasse référence à l'autre, leur séquence est arbitraire. Et tous voient le même instantané depuis le début de la requête.

Exemple:

Exemple avancé:

Erwin Brandstetter
la source
3

Essayons :

CREATE OR REPLACE FUNCTION public.sp_get_user()
 RETURNS json
 LANGUAGE plpgsql
AS $function$BEGIN

INSERT INTO users (name, password) VALUES ('deadeye', 'test');
RETURN row_to_json(row) FROM (SELECT name, password FROM users WHERE name = 'deadeye') row;

END;$function$

Maintenant, testons:

SELECT sp_get_user();
{"name":"deadeye","password":"test"}

Ça marche ! Comme l'a dit Erwin, tout ce qui est fait dans une transaction est visible à l'intérieur de la transaction. L'isolement se fait uniquement entre différents threads.

DeadEye
la source