En PostgreSQL NO existen transacciones anidadas reales en el sentido clásico del término. Solo hay una transacción externa y "capas" de puntos de guardado dentro de ella.
El término "transacciones anidadas" en PostgreSQL normalmente significa usar puntos de guardado (savepoints) con los comandos SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT. No son transacciones independientes, sino puntos de control especiales dentro de una transacción externa a los que puedes volver sin deshacer toda la transacción entera.
Un ejemplo de la vida real: estás escribiendo un texto largo en un editor y de vez en cuando le das a ctrl+s. Si la lías, puedes volver a una de las versiones guardadas antes, sin perder todo el progreso.
Comandos para gestionar puntos de guardado
Para manejar transacciones anidadas, PostgreSQL te da tres comandos principales:
SAVEPOINT
Este comando se usa para crear "puntos de guardado" a los que puedes volver si hace falta. Ese punto funciona como un checkpoint en nuestra transacción.
SAVEPOINT mypoint;
ROLLBACK TO SAVEPOINT
Deshace parte de los cambios hechos después del punto indicado, dejando intactos los cambios anteriores dentro de la misma transacción externa.
ROLLBACK TO SAVEPOINT mypoint;
RELEASE SAVEPOINT
Elimina el punto de guardado. Después de eso, ya no puedes volver a él.
RELEASE SAVEPOINT mypoint;
Ejemplo: añadir datos en varias tablas con posibilidad de deshacer
Imagina que curras en un sistema de gestión de pedidos, donde tienes que guardar datos en dos tablas a la vez: orders y order_items. Un error al añadir en una tabla no debería hacer que se deshagan los datos de la otra.
BEGIN; -- Inicio de la transacción
-- Creamos un punto de guardado
SAVEPOINT before_order;
-- Añadimos el pedido en la tabla orders
INSERT INTO orders (order_id, customer_id, date)
VALUES (1, 101, CURRENT_DATE);
-- Si aquí hay un error — nos volvemos atrás
SAVEPOINT before_order_items;
-- Añadimos productos en la tabla order_items
INSERT INTO order_items (order_id, product_id, quantity)
VALUES (1, 2001, 4);
-- Si algo sale mal
-- ROLLBACK TO SAVEPOINT before_order_items;
-- Confirmamos la transacción (guardamos los cambios)
COMMIT;
Si al añadir registros en order_items hay un error, puedes volver al punto before_order_items, y los cambios en la tabla orders se quedan guardados.
Consejos prácticos y errores típicos
Ahora que ya pillas cómo funcionan los comandos SAVEPOINT y ROLLBACK TO SAVEPOINT, aquí tienes unas recomendaciones para no liarla:
- Nombres de los puntos de guardado. Usa nombres claros y únicos para los
SAVEPOINT. Por ejemplo,before_insert,step1y así — te ayudará a orientarte cuando depures. - No te olvides de soltar el
SAVEPOINT. Si ya no vas a volver a ese punto, bórralo conRELEASE SAVEPOINTpara no llenar la transacción de basura. - Transacción anidada ≠ transacción independiente. Recuerda que cuando haces
COMMITse pierden todos los puntos de guardado. Si elCOMMITexterno se ejecuta, ya no hay vuelta atrás. - Bloqueo de datos. Incluso si vuelves a un punto, los bloqueos de registros puestos en la transacción se mantienen. Esto es importante si curras en un entorno multiusuario.
Las transacciones anidadas usando SAVEPOINT y ROLLBACK TO SAVEPOINT te dan una herramienta potente para manejar situaciones complicadas. Ahora puedes dividir las transacciones en etapas flexibles, manejar errores con cuidado y evitar deshacer datos innecesariamente. Recuerda que cada vez que veas la palabra "deshacer", no siempre es motivo de pánico: a veces deshacer es la mejor forma de avanzar.
GO TO FULL VERSION