¿Puedo seleccionar datos insertados en la misma transacción no confirmada?

21

Tal vez esta es una pregunta tonta para principiantes, pero no puedo encontrar una respuesta en ningún lado. En todas partes leí sobre lo Transaction Isolationque resuelve la visibilidad de los datos dentro de las transacciones concurrentes. Mi preocupación es el comportamiento dentro de una sola transacción.

Si comienzo una transacción, inserto algunos datos, ¿podré seleccionarlos inmediatamente después, todavía dentro de la misma transacción, pero no comprometida? En caso afirmativo, ¿se puede cambiar este comportamiento de manera similar al aislamiento de transacción mencionado en el caso de transacciones concurrentes?

Para ser específicos, estoy apuntando a PostgreSQL 9.4.

Número cuatro
fuente

Respuestas:

17

Sí.
Todo lo que hiciste dentro de la misma transacción es visible para comandos posteriores dentro de la misma transacción. Simplemente no a otras transacciones hasta que se haya comprometido. Esto es cierto para todos los niveles de aislamiento, excepto Read uncommitteddonde son posibles "lecturas sucias" (pero eso no afecta su pregunta per se).

Se implementa con el modelo MVCC (Control de concurrencia multiversional) basado en TransactionIdla edad y la visibilidad de cada fila de la tabla. Cada nueva versión de fila escrita en la misma transacción obtiene lo mismo xminy se considera que ha sucedido "al mismo tiempo".

Hay un caso de esquina para múltiples CTE (expresión de tabla común) en el mismo comando. Uno podría pensar que se ejecutan secuencialmente, pero a menos que un CTE haga referencia al otro, su secuencia es arbitraria. Y todos ellos ven la misma instantánea desde el comienzo de la consulta.

Ejemplo:

Ejemplo avanzado:

Erwin Brandstetter
fuente
3

Intentemos :

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$

Ahora, probemos:

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

Funciona ! Como dijo Erwin, todo lo que se hace en una transacción es visible dentro de la transacción. El aislamiento es solo entre diferentes hilos.

Vigota
fuente