Si varias instancias de una aplicación Heroku están accediendo a una base de datos (usando SQLAlchemy), ¿cómo se evitan las colisiones e inconsistencias?

El hecho de que haya varias aplicaciones de Heroku accediendo a la base de datos no es consecuencia de esta respuesta. El hecho es que hay muchas conexiones que acceden y modifican simultáneamente los datos, y cuando esto sucede, existe la posibilidad de conflicto.

Por lo tanto, estoy leyendo esta pregunta como “¿Cómo maneja Postgres el acceso concurrente?”. Intentaré cubrir lo suficiente para comprender los conceptos básicos de concurrencia en Postgres desde la perspectiva de un desarrollador de aplicaciones.

La primera parte de esta respuesta es la implementación de Postgres del Control de concurrencia de versiones múltiples (MVCC). La forma en que funciona MVCC es que cuando se modifica una fila, de hecho, se crea una nueva fila en el disco y la información de visibilidad de la transacción se registra tanto en la fila anterior como en la nueva. Esta visibilidad de transacción básicamente le dice a Postgres qué ID de transacción (un número creciente para todas las transacciones que cree) puede ver la fila.

Digamos que está actualizando un conjunto de filas en una transacción (X). Las transacciones que comenzaron antes de la transacción X continuarán viendo las versiones anteriores de la fila, mientras que las transacciones que comienzan después de X verán las nuevas versiones.

MVCC es lo que hace que las lecturas de Postgres no bloqueen las escrituras.

Ahora a la pieza más interesante, que son los conflictos causados ​​por el acceso concurrente al mismo recurso que causa lo que se llama anomalías.

Digamos que tiene muchas transacciones concurrentes actualizando las mismas filas. Para comprender lo que sucede allí, debe aprender sobre los niveles de aislamiento de transacciones (Documentación: 9.3: Aislamiento de transacciones primero. Cada nivel de aislamiento más alto es más estricto sobre los tipos de conflictos que permite y define comportamientos bien conocidos para cuando lo hacen. Es mejor leer el documentos que se han repetido aquí. También es de destacar que Postgres es la única base de datos hasta la fecha que admite la serialización verdadera (Serializable – PostgreSQL wiki), y es útil en varios puntos de la infraestructura de Heroku Postgres.

Finalmente, es importante saber que hay varios modos de bloqueo en Postgres (Documentación: 9.3: Bloqueo explícito). En particular, es crucial comprender que varios tipos de consultas adquieren bloqueos de diferentes modos y que estos bloqueos pueden entrar en conflicto entre sí. Cuando hay un conflicto, solo una consulta puede continuar y la otra espera. En Heroku Postgres puedes rastrear las conexiones en espera desde los registros de tu aplicación (Heroku Postgres Metrics Logs), o puedes usar los comandos `heroku pg: locks` y` heroku pg: block` disponibles desde el complemento pg-extras toolbelt (heroku / heroku -pg-extras).

Recomiendo leer todo el capítulo de concurrencia del excelente manual de Postgres: Documentación: 9.3: Control de concurrencia