modificar - update de una tabla a otra postgresql
Puntos muertos en PostgreSQL al ejecutar UPDATE (1)
Estoy un poco confundido leyendo sobre los interbloqueos de PostgreSQL.
Un ejemplo típico de punto muerto es:
-- Transaction 1
UPDATE customer SET ... WHERE id = 1
UPDATE customer SET ... WHERE id = 2
-- Transaction 2
UPDATE customer SET ... WHERE id = 2
UPDATE customer SET ... WHERE id = 1
Pero qué pasa si cambio el código de la siguiente manera:
-- Transaction 1
UPDATE customer SET ... WHERE id IN (1, 2)
-- Transaction 2
UPDATE customer SET ... WHERE id IN (1, 2)
¿Habrá una posibilidad de punto muerto aquí?
Esencialmente mi pregunta es: en el segundo caso, ¿PostgreSQL bloquea las filas una por una, o bloquea todo el ámbito cubierto por la condición WHERE
?
¡Gracias por adelantado!
En PostgreSQL, las filas se bloquearán a medida que se actualicen. De hecho, la forma en que esto realmente funciona es que cada tupla (versión de una fila) tiene un campo del sistema llamado xmin
para indicar qué transacción hizo esa tupla actual (mediante inserción o actualización ) y un campo del sistema llamado xmax
para indicar qué transacción expiró esa tupla (por actualización o eliminación). Cuando accede a los datos, verifica cada tupla para determinar si es visible para su transacción, verificando su "instantánea" activa con estos valores.
Si está ejecutando una ACTUALIZACIÓN y una tupla que coincide con sus condiciones de búsqueda tiene un xmin que lo haría visible para su instantánea y un xmax de una transacción activa, se bloquea, esperando que se complete la transacción. Si la transacción que primero actualizó la tupla se revierte, su transacción se reactiva y procesa la fila; Si la primera transacción se confirma, su transacción se reactiva y toma medidas en función del nivel de aislamiento de la transacción actual.
Obviamente, un interbloqueo es el resultado de que esto suceda en filas en orden diferente. No hay un bloqueo de nivel de fila en la RAM que se pueda obtener para todas las filas al mismo tiempo, pero si las filas se actualizan en el mismo orden, no puede tener el bloqueo circular. Desafortunadamente, la sintaxis IN(1, 2)
sugerida no garantiza eso. Las diferentes sesiones pueden tener diferentes factores de costos activos, una tarea de "análisis" de fondo puede cambiar las estadísticas de la tabla entre la generación de un plan y el otro, o puede estar usando un seqscan y verse afectado por la optimización de PostgreSQL que causa un nuevo seqscan para unirse a uno que ya está en progreso y "dar vueltas" para reducir la E / S del disco.
Si realiza las actualizaciones una a la vez en el mismo orden, en el código de la aplicación o utilizando un cursor, solo tendrá un bloqueo simple, no puntos muertos. En general, sin embargo, las bases de datos relacionales son propensas a fallas de serialización, y es mejor acceder a ellas a través de un marco que las reconocerá en base a SQLSTATE y volverá a intentar automáticamente la transacción completa desde el principio. En PostgreSQL, una falla de serialización siempre tendrá un SQLSTATE de 40001 o 40P01.
http://www.postgresql.org/docs/current/interactive/mvcc-intro.html