63.5. Comprobaciones de unicidad de índices #

PostgreSQL hace cumplir las restricciones de unicidad de SQL utilizando índices únicos, que son índices que no permiten múltiples entradas con claves idénticas. Un método de acceso que admite esta característica establece amcanunique en verdadero. (En la actualidad, solo b-tree lo admite). Las columnas enumeradas en la cláusula INCLUDE no se consideran al hacer cumplir la unicidad.

Debido a MVCC, siempre es necesario permitir que existan físicamente entradas duplicadas en un índice: las entradas podrían referirse a versiones sucesivas de una única fila lógica. El comportamiento que realmente queremos hacer cumplir es que ninguna captura instantánea de MVCC pueda incluir dos filas con claves de índice iguales. Esto se desglosa en los siguientes casos que deben comprobarse al insertar una nueva fila en un índice único:

Además, inmediatamente antes de reportar una violación de unicidad según las reglas anteriores, el método de acceso debe volver a comprobar la vigencia de la fila que se está insertando. Si está confirmada muerta, entonces no se debe reportar ninguna violación. (Este caso no puede ocurrir durante el escenario ordinario de insertar una fila que acaba de ser creada por la transacción actual. Sin embargo, puede suceder durante CREATE UNIQUE INDEX CONCURRENTLY).

Requerimos que el método de acceso al índice aplique estas pruebas por sí mismo, lo que significa que debe acceder al montón para comprobar el estado de confirmación de cualquier fila que se muestre que tiene una clave duplicada según el contenido del índice. Esto es, sin duda, feo y no modular, pero ahorra trabajo redundante: si hiciéramos una búsqueda separada, la búsqueda de índice para una fila en conflicto se repetiría esencialmente al buscar el lugar para insertar la entrada de índice de la nueva fila. Además, no hay una forma obvia de evitar condiciones de carrera a menos que la comprobación de conflicto sea una parte integral de la inserción de la nueva entrada de índice.

Si la restricción de unicidad es diferible, existe una complejidad adicional: necesitamos poder insertar una entrada de índice para una fila nueva, pero diferir cualquier error de violación de unicidad hasta el final de la sentencia o incluso más tarde. Para evitar búsquedas repetidas innecesarias en el índice, el método de acceso al índice debe realizar una comprobación de unicidad preliminar durante la inserción inicial. Si esto muestra que definitivamente no hay ninguna tupla viva en conflicto, habremos terminado. De lo contrario, programamos una nueva comprobación para cuando sea el momento de hacer cumplir la restricción. Si en el momento de la nueva comprobación, tanto la tupla insertada como alguna otra tupla con la misma clave están vivas, entonces se debe reportar el error. (Ten en cuenta que para este propósito, viva significa en realidad cualquier tupla en la cadena HOT de la entrada del índice está viva). Para implementar esto, a la función aminsert se le pasa un parámetro checkUnique que tiene uno de los siguientes valores: