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

Evite los bloqueos de acceso exclusivo en las tablas a las que se hace referencia cuando DROPping en PostgreSQL

Para cualquiera que esté buscando en Google y tratando de entender por qué su tabla desplegable (o quitar clave externa o agregar clave externa) se atascó durante mucho tiempo:

PostgreSQL (Revisé las versiones 9.4 a 13) las restricciones de clave externa en realidad se implementan mediante activadores en ambos extremos de la clave externa .

Si tiene una tabla de empresa (id como clave principal) y una tabla de cuenta_bancaria (id como clave principal, id_empresa como clave externa que apunta a empresa.id), entonces en realidad hay 2 activadores en la tabla cuenta_bancaria y también 2 activadores en la empresa mesa.

nombre_tabla tiempo trigger_name nombre_función
cuenta_bancaria DESPUÉS DE LA ACTUALIZACIÓN RI_ConstraintTrigger_c_1515961 RI_FKey_check_upd
cuenta_bancaria DESPUÉS DE INSERTAR RI_ConstraintTrigger_c_1515960 RI_FKey_check_ins
empresa DESPUÉS DE LA ACTUALIZACIÓN RI_ConstraintTrigger_a_1515959 RI_FKey_noaction_upd
empresa DESPUÉS DE ELIMINAR RI_ConstraintTrigger_a_1515958 RI_FKey_noaction_del

La creación inicial de esos activadores (cuando se crea la clave externa) requiere el bloqueo EXCLUSIVO DE LA FILA COMPARTIDA en esas tablas (solía ser el bloqueo EXCLUSIVO DE ACCESO en la versión 9.4 y anteriores). Este bloqueo no entra en conflicto con los "bloqueos de lectura de datos", pero entrará en conflicto con todos los demás bloqueos, por ejemplo, un simple INSERTAR/ACTUALIZAR/ELIMINAR en la tabla de la empresa.

La eliminación de esos disparadores (al soltar la clave externa o la tabla completa) requiere el bloqueo ACCESS EXCLUSIVE en esas tablas. ¡Este bloqueo entra en conflicto con cualquier otro bloqueo!

Así que imagine un escenario, donde tiene una transacción A en ejecución que primero hizo una SELECCIÓN simple de la tabla de la compañía (lo que provocó que retuviera un bloqueo de ACCESO COMPARTIDO para la tabla de la compañía hasta que la transacción se confirme o revierta) y ahora está haciendo otro trabajo para 3 minutos. Intenta eliminar la tabla bank_account en la transacción B. Esto requiere el bloqueo ACCESS EXCLUSIVE, que deberá esperar hasta que se libere primero el bloqueo ACCESS SHARE. o tal vez INSERTAR/ACTUALIZAR/ELIMINAR), se pondrán en cola para esperar en el bloqueo de ACCESO EXCLUSIVO, que está esperando en el bloqueo de ACCESO COMPARTIDO.

Las transacciones de ejecución prolongada y los cambios de DDL requieren un manejo delicado.