PostgreSQL Antipatterns: lucha contra las hordas de los "muertos"

Las características de los mecanismos internos de PostgreSQL permiten que sea muy rápido en algunas situaciones y no tan rápido en otras. Hoy nos detendremos en un ejemplo clásico de un conflicto entre cómo funciona un DBMS y lo que un desarrollador hace con él: ACTUALIZACIÓN vs principios de MVCC .

Brevemente trama de un excelente artículo :
Cuando se modifica una línea con el comando ACTUALIZAR, se realizan dos operaciones: BORRAR e INSERTAR. En la versión actual de la línea , xmax se establece igual al número de la transacción que realizó ACTUALIZACIÓN. Luego se crea una nueva versión de la misma línea; su valor xmin coincide con el valor xmax de la versión anterior.
Algún tiempo después de la finalización de esta transacción, la versión antigua o nueva, según cuál COMMIT/ROOLBACK, será reconocida como "muerta" (tuplas muertas) al pasar VACUUMpor la mesa y limpiarse.



Pero esto no sucederá de inmediato, pero los problemas con los "muertos" se pueden adquirir muy rápidamente, con la actualización múltiple o masiva de registros en una tabla grande, y un poco más tarde, ante una situación que VACUUM no podrá ayudar .

# 1: me gusta moverlo


Supongamos que su método de lógica de negocios funciona por sí mismo y de repente se da cuenta de que sería necesario actualizar el campo X en algún registro:

UPDATE tbl SET X = <newX> WHERE pk = $1;

Luego, a medida que avanza, descubre que el campo Y también debe actualizarse:

UPDATE tbl SET Y = <newY> WHERE pk = $1;

... y luego también Z - ¿por qué jugar algo?

UPDATE tbl SET Z = <newZ> WHERE pk = $1;

¿Cuántas versiones de este registro tiene ahora en la base de datos? Sí, 4 piezas! De estos, uno es relevante, y 3 tendrán que recoger [auto] VACUUM por usted.

¡No hagas así! Utilice la actualización de todos los campos en una solicitud ; casi siempre, la lógica del método se puede cambiar así:

UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;

# 2: ¡El uso ES DISTINTO DE, Luke!


Entonces, aún quería actualizar muchos, muchos registros en la tabla (durante el uso de un script o convertidor, por ejemplo). Y algo como esto vuela en el guión:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;

Aproximadamente en este formulario, se encuentra una consulta con bastante frecuencia y casi siempre para no completar un nuevo campo vacío, sino para corregir algunos errores en los datos. Además, la exactitud de los datos ya existentes no se tiene en cuenta en absoluto , ¡sino en vano! Es decir, el registro se está reescribiendo, incluso si era exactamente lo que quería, ¿por qué? Correcto:

UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>;

Muchas personas no son conscientes de la existencia de un operador tan maravilloso, así que aquí hay una hoja de trucos para que IS DISTINCT FROMotros operadores lógicos puedan ayudar:

... y un poco sobre operaciones en ROW()expresiones complejas :

# 3: Reconoceré a mi querido ... bloqueando


Ejecute dos procesos paralelos idénticos , cada uno de los cuales está dirigido a la marca de grabación, que está "en funcionamiento":

UPDATE tbl SET processing = TRUE WHERE pk = $1;

Incluso si estos procesos hacen cosas substancialmente independientes entre sí, pero dentro del marco de una ID, en esta solicitud, el segundo cliente "se bloquea" hasta que se complete la primera transacción.

Solución n. ° 1 : la tarea se reduce a la anterior.

Simplemente agregue nuevamente IS DISTINCT FROM:

UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;

De esta forma, la segunda solicitud simplemente no cambiará nada en la base de datos, ya existe "todo como debería", por lo tanto, no se producirá ningún bloqueo. Además, el hecho de la "inexistencia" del registro ya se procesa en el algoritmo aplicado.

Decisión número 2 : bloqueos de asesoramiento

Un gran tema para un artículo separado en el que puede leer sobre los métodos de aplicación y el "rastrillo" de los bloqueos de recomendación .

Solución # 3 : sin [d] llamadas inteligentes

Pero exactamente, exactamente, ¿debería tener un trabajo simultáneo con el mismo registro ? ¿O aún te equivocaste con los algoritmos de llamadas de lógica de negocios del lado del cliente, por ejemplo? ¿Y si lo piensas? ..

All Articles