sql >> Base de Datos >  >> RDS >> PostgreSQL

interbloqueo postgresql

Estos son dos comentarios que se insertan con el mismo content_id. Simplemente insertando el comentario se eliminará un bloqueo COMPARTIDO en la fila de contenido, para evitar que otra transacción elimine esa fila hasta que se complete la primera transacción.

Sin embargo, el activador luego pasa a actualizar el bloqueo a EXCLUSIVO, y esto puede bloquearse mediante una transacción simultánea que realiza el mismo proceso. Considere la siguiente secuencia de eventos:

Txn 2754                      Txn 2053
Insert Comment
                              Insert Comment
Lock Content#935967 SHARE
  (performed by fkey)
                              Lock Content#935967 SHARE
                                (performed by fkey)
Trigger
Lock Content#935967 EXCLUSIVE
(blocks on 2053's share lock)
                              Trigger
                              Lock Content#935967 EXCLUSIVE
                              (blocks on 2754's share lock)

Así que punto muerto.

Una solución es inmediatamente tomar un bloqueo exclusivo en la fila de contenido antes insertando el comentario. es decir,

SELECT 1 FROM content WHERE content.id = 935967 FOR UPDATE
INSERT INTO comment(.....)

Otra solución es simplemente evitar este patrón de "recuentos en caché" por completo, excepto cuando pueda demostrar que es necesario para el rendimiento. Si es así, considere mantener el recuento almacenado en caché en otro lugar que no sea la tabla de contenido, p. una mesa dedicada para el mostrador. Eso también reducirá el tráfico de actualización a la tabla de contenido cada vez que se agregue un comentario. O tal vez simplemente vuelva a seleccionar el conteo y use memcached en la aplicación. No se puede evitar el hecho de que donde sea que almacene este conteo en caché será un cuello de botella, debe actualizarse de manera segura.