Este es el final de una serie de tres partes sobre cómo funcionan las transacciones en Django. Se cubre todo, desde la aplicación y el código del framework hasta la capa de base de datos.
- Parte 1 — Python: Cómo funcionan las transacciones en Django
- Parte 2 — Python: Django, qué NO debes incluir en una transacción
En Q2BSTUDIO, empresa especializada en desarrollo y servicios tecnológicos, trabajamos con las mejores prácticas para asegurar sistemas eficientes y rentables, optimizando cada interacción con la base de datos y asegurando una correcta gestión de transacciones.
Resumen de la Parte 2 - Qué NUNCA debes incluir en una Transacción
En la parte anterior exploramos qué operaciones y código en la base de datos deben evitarse dentro de una transacción para prevenir respuestas lentas y posibles caídas del sistema. También explicamos qué elementos pueden incluirse en una transacción para mantener su comportamiento atómico.
- Permitido dentro de una transacción:
- Operaciones reversibles en la base de datos
- Lógica de negocio relacionada
- Riesgoso dentro de una transacción:
- Consultas lentas
- Operaciones en múltiples tablas
- Migraciones de datos
- Cambios en la estructura del esquema
- No permitido dentro de una transacción:
- Operaciones irreversibles
- Llamadas bloqueantes (como solicitudes de red o lectura de archivos)
Administrar el código dentro de las transacciones nos permite controlar los bloqueos que se mantienen y su duración. Con ello se minimiza el tiempo de ejecución de cada transacción, se reduce la latencia de la base de datos y se evita bloquear otras consultas críticas. Sin embargo, ¿cómo interactúan las operaciones en la base de datos y cuáles pueden entrar en conflicto?
Resumen Rápido
Los bloqueos en la base de datos existen porque múltiples usuarios pueden ejecutar comandos simultáneamente. Por ejemplo, si un usuario intenta eliminar una tabla mientras otro está leyendo sus datos, esto podría causar errores o corrupción de datos. Para evitar esto, cada operación obtiene y mantiene un bloqueo que depende de los permisos que requiera.
Existen dos tipos principales de bloqueos en PostgreSQL: bloqueos de tabla y bloqueos de fila.
- Los bloqueos a nivel de tabla afectan toda la estructura, por lo que son los más riesgosos. Si se mantiene un bloqueo de tabla por mucho tiempo, otras consultas se verán afectadas, generando posibles tiempos de espera y caídas.
- Los bloqueos a nivel de fila afectan solo un registro específico. Son menos riesgosos, pero si una migración de datos bloquea cada fila individualmente, podría bloquear la tabla completa de manera inadvertida.
En Q2BSTUDIO optimizamos el uso de transacciones en Django para minimizar los riesgos de bloqueos y garantizar que el rendimiento del sistema sea óptimo.
Operaciones y su Impacto en Bloqueos
Las siguientes operaciones pueden afectar el acceso a las tablas:
- Operaciones que bloquean todo (lecturas y escrituras):
- ALTER INDEX/TABLE
- DROP TABLE
- TRUNCATE
- REINDEX
- CLUSTER
- Operaciones que bloquean escrituras (inserción, actualización y eliminación de datos):
- CREATE TRIGGER
- ALTER TABLE
- CREATE INDEX
Las migraciones en Django, por ejemplo, pueden contener cambios en el esquema que bloquean el acceso a las tablas. Para evaluar qué hará una migración antes de ejecutarla, se recomienda usar:
./manage.py sqlmigrate APP_NAME MIGRATION_NUM
Esto mostrará qué operaciones se ejecutarán y permitirá anticipar si causarán bloqueos en la base de datos.
Bloqueos en Filas y su Impacto
A diferencia de los bloqueos de tabla, los bloqueos a nivel de fila bloquean solo registros específicos. Sin embargo, si dentro de una transacción se ejecutan múltiples modificaciones a filas, la acumulación de bloqueos puede interferir con otros procesos que intentan modificar la misma tabla.
Por ejemplo, si dentro de una transacción se recorren todas las filas de una tabla para modificar datos, cada fila será bloqueada hasta el final de la transacción, lo que podría impedir otras actualizaciones en la misma tabla. En estos casos, es recomendable evitar envolver toda la operación en una transacción global y en su lugar aplicar transacciones más pequeñas que liberen sus bloqueos una vez que se procesen los datos de cada fila.
Ver el SQL que Ejecutará una Migración en Django
./manage.py sqlmigrate APP_NAME MIGRATION_NUMBER/NAME
Este comando imprimirá las operaciones SQL que se ejecutarán, permitiendo evaluar si afectan el acceso a las tablas. Por ejemplo, una migración que no realiza cambios en la base de datos solo mostrará un comentario:
BEGIN;
-
- Alter field transaction_status on transactions
-
COMMIT;
Mientras que una migración que agrega una nueva columna mostrará un comando ALTER TABLE que puede bloquear otras operaciones:
BEGIN;
-
- Add field reverted to transactions
-
ALTER TABLE 'transactions' ADD COLUMN 'reverted' timestamp with time zone NULL;
COMMIT;
En Q2BSTUDIO recomendamos optimizar las migraciones para evitar bloqueos innecesarios y asegurar la estabilidad de la base de datos.