¿Realmente necesito disparadores para la base de datos relacional, por ejemplo, PostgreSQL?


10

Sé que los desencadenantes se pueden usar para validar los datos almacenados para mantener la base de datos coherente. Sin embargo, ¿por qué no realizar la validación de datos en el lado de la aplicación antes de almacenarlos en la base de datos?

Por ejemplo, almacenamos clientes y queremos realizar alguna validación que no se puede hacer fácilmente en el nivel DDL. https://severalnines.com/blog/postgresql-triggers-and-stored-function-basics

Otro ejemplo es la auditoría.

Actualizar

Cómo los disparadores y la transacción de la base de datos funcionan juntos. Por ejemplo, si quisiera realizar la validación de los datos que se están insertando. Se realiza dentro de una transacción. ¿Qué sucede antes: la transacción se confirma o se ejecuta el disparador?


However, why not perform validation of data on the application side before storing them into the database?bueno, estos dos no son mutuamente excluyentes. Es probable que valide diferentes cosas en ambos lados. Si bien las validaciones en el lado de la aplicación están centradas en el negocio, las validaciones en la base de datos están más centradas en los datos. Piense en una base de datos alimentada por varias y diferentes aplicaciones.
Laiv

¿Necesitará insertar datos de una fuente externa que solo está haciendo un volcado de datos sin sentido en su sistema? Si es así, es posible que tenga casos en los que necesite insertar los datos en un formato no válido para su posterior corrección. En este caso, los desencadenantes causarán un sinfín de problemas. Solo ten esto en cuenta. A veces no quieres que se ejecute un disparador.
Greg Burghardt

Su actualización debe ser una pregunta en sí misma, tal vez en SO, pero su pregunta ya tiene una respuesta en Administradores de bases de datos . En resumen, incluso un activador "después de la actualización" se ejecuta antes de que se confirme la transacción, y si se lanza una excepción dentro del activador, provocará una reversión.
Doc Brown

@GregBurghardt La mayoría de las bases de datos tienen declaraciones que pueden usarse para deshabilitar los desencadenantes para ese tipo de actividades.
Blrfl

1
@Blrfl: Sí, pero debe tener en cuenta que esos desencadenantes podrían desactivarse temporalmente para todos los usuarios conectados, cuando solo desea deshabilitar condicionalmente esas comprobaciones para la sesión actual.
Greg Burghardt

Respuestas:


12

Depende del tipo de sistema de aplicación que esté creando:

  • Si está creando un sistema centrado en la aplicación que contiene solo una aplicación principal, con una base de datos dedicada específicamente para esta aplicación, e idealmente un equipo responsable de la evolución de la aplicación y la base de datos en paralelo, puede mantener toda la lógica de validación y también auditar lógica dentro de la aplicación.

    El principal beneficio de esto es que no tiene que distribuir la lógica de negocios entre la aplicación y la base de datos, por lo que el mantenimiento y la evolución del sistema a menudo se vuelve más fácil. Como beneficio adicional, no vincula demasiado la aplicación a un tipo específico de DBMS o proveedor de DBMS. Obviamente, este enfoque es necesario si su aplicación quiere poder usar un sistema de base de datos liviano que no proporciona disparadores.

  • Sin embargo, si crea un sistema en el que muchas aplicaciones diferentes comparten una base de datos común, y no puede prever de antemano qué aplicaciones le escribirán en el futuro, o qué equipos desarrollarán aplicaciones para completar datos en la base de datos en el futuro, entonces es mejor que su base de datos sea responsable de garantizar la mayor consistencia de datos posible. Y ahí es donde los desencadenantes se vuelven realmente útiles. En sistemas más grandes, las restricciones referenciales a menudo no son suficientes para esto, pero un disparador que llama a un procedimiento almacenado puede implementar casi cualquier tipo de validación que necesite.

Otra razón para usar desencadenantes puede ser el rendimiento: en modelos de datos complejos, no es raro encontrar reglas de coherencia complejas que requieren el uso de muchos datos adicionales que no forman parte del conjunto de trabajo actual disponible en la aplicación cliente. Transferir todos esos datos a través de la red primero para hacer posible la validación en el lado del cliente puede tener un impacto notable en el rendimiento.

Vea también esta publicación anterior de SE: Application Logic Vs DB Triggers para la limpieza de la base de datos

Así que decida por sí mismo qué tipo de sistema está construyendo, luego puede tomar una decisión fundada si los disparadores son la herramienta adecuada para su caso o no.


3

Creo que la pregunta es sobre la responsabilidad de la calidad de los datos.

La respuesta depende de cómo veas el sistema.

Si ve la base de datos como un servicio independiente, distinto y autónomo separado de la aplicación, la base de datos es responsable de garantizar la coherencia y la calidad de los datos que contiene. Esencialmente porque esa base de datos podría ser utilizada por una aplicación diferente, por lo que no puede confiar en que la segunda aplicación tenga los mismos comportamientos de calidad y consistencia. En estas circunstancias, la base de datos debe diseñarse para exponer una API y un comportamiento autónomo. En esta vista hay al menos dos aplicaciones, una de ellas es la base de datos y la otra es la aplicación que la usa.

Por el contrario, la base de datos podría considerarse una forma complicada de archivo que está bajo el control directo y total de la aplicación. En este sentido, la base de datos se convierte en una pura herramienta de serialización y navegación de documentos. Puede proporcionar algunos comportamientos avanzados para admitir consultas y mantenimiento de documentos (como JSON o las herramientas XML) pero, de nuevo, no es necesario (como lo hacen la mayoría de las secuencias de archivos). En este caso, es puramente responsabilidad del programa mantener el formato y contenido correctos dentro del archivo. En esta vista hay una aplicación.

En ambas vistas, la siguiente pregunta es cómo admitir el uso de la base de datos como un archivo elegante o como un servicio separado. Puede lograr esto al:

  • utilizando las herramientas que proporciona la plataforma de base de datos en forma de tablas / vistas / procedimientos almacenados / disparadores / etc.
  • envolver la base de datos en un servicio que todos los clientes deben usar para acceder a la base de datos
  • envolviendo la base de datos en una biblioteca que debe ser utilizada por todos los clientes para acceder a los datos.

Cada uno viene con sus propios pros / contras y dependerá de las limitaciones arquitectónicas del entorno en el que opera el sistema.

Independientemente de la vista que tome, siempre vale la pena validar los datos en los límites.

  • Valide los campos en una IU que ingresa un usuario
  • Valide la solicitud de red / API antes de que salga del cliente
  • Valide la solicitud de red / API en el servidor antes de hacer nada
  • Validar los datos que se pasan a las reglas comerciales
  • Validar los datos antes de ser persistentes
  • Validar los datos después de ser recuperados de la persistencia.
  • Y así sucesivamente

La cantidad de validación garantizada en cada límite depende de lo arriesgado que sea no validarla.

  • multiplicando dos números juntos?
    • obtienes el número equivocado, ¿eso es un problema?
  • invocando un procedimiento en una ubicación de memoria dada?
    • ¿Qué hay en esa ubicación de memoria?
    • ¿Qué sucede si el objeto no existe o está en mal estado?
  • usando una expresión regular en una cadena que contiene kanji?
    • ¿Puede el módulo regex manejar unicode?
    • ¿Puede la expresión regular manejar unicode?

La lógica de validación centralizada es buena, pero los disparadores de imho no son una buena manera de implementar eso. Solía ​​trabajar en un sistema donde múltiples aplicaciones compartían una base de datos, con toda la lógica de validación y los efectos secundarios implementados en la base de datos a través de disparadores y procedimientos almacenados. Salí con la impresión de que es mejor tener un microservicio frente a la base de datos e implementar toda la lógica allí. La lógica no trivial dentro de una base de datos SQL es un antipatrón.
Joeri Sebrechts

1
@JoeriSebrechts Bien, voy a morder: ¿por qué la lógica no trivial en una base de datos es un antipatrón, y qué lo hace más antipatrón que ponerlo en un programa mantenido por separado?
Blrfl

@Blrfl Dos razones, la API para acceder a la lógica en la base de datos es inferior a una API de servicio web (más difícil de versión, más difícil de usar, no fácil de almacenar en caché, ...), y las bases de datos hacen que sea más difícil estructurar y mantener limpiamente código base alojado dentro de ellos. En mi experiencia, es más fácil alojar la lógica en un servicio web frente a la base de datos que dentro de esa base de datos.
Joeri Sebrechts

@JoeriSebrechts Estoy de acuerdo en que la mayoría de las plataformas de bases de datos proporcionan herramientas lamentables para implementar una API creíble, útil y capaz de desarrollarse. En muchos sentidos, es sin duda una invitación a sentir mucho dolor. Mi punto fue que se trata de la perspectiva, darse cuenta de que la base de datos es un archivo sofisticado, o que es realmente un servicio separado conduce a la siguiente pregunta, que es cómo envolver eso para soportar ese estilo de uso. Elaboraré mi respuesta para que quede claro al respecto.
Kain0_0

2

No, nunca debes usar disparadores para hacer la validación.

La base de datos solo es responsable de su propia integridad. Cualquier aplicación que se enfrente a la validación debe realizarla su aplicación

Las bases de datos realizan tres niveles de validación para integridad. El primero es la validación a nivel de campo. Se puede requerir un campo, si no hay ningún valor (nulo) es un error. También puede ser una restricción de verificación; un dominio tiene un número enumerado de valores.

En segundo lugar hay relaciones entre tablas. En una tabla, almacena una o más claves foráneas, relaciona esta tabla con otras tablas y requiere que los valores sean claves válidas para la "otra tabla". Piense en una base de datos de direcciones, donde admitimos direcciones de diferentes países. Una clave de país en una dirección debe apuntar a un país conocido. Si los datos (por ejemplo, un código postal) son válidos, no es una preocupación de esta verificación de integridad.

En tercer lugar y más complicado son los desencadenantes. Como regla general, estos deben abordar (juego de palabras no intencionado) se refiere a reglas de integridad que son condicionales. Para volver al ejemplo de la dirección: si un país no tiene códigos postales, sería un problema si un país en esta lista tuviera un código postal. Por lo tanto, la comprobación sería: si este país no tiene códigos postales, el campo del código postal debería ser nulo.

La validación es la preocupación de la aplicación. El hecho de que un código postal alemán consista solo en dígitos es un control que la aplicación debe hacer, no la base de datos. La línea es delgada, por lo que es posible que necesite pensar / debatir en algunos casos si algo debe estar en un disparador (proteger la integridad de su base de datos) o en la aplicación (validación de cara al usuario).


Solo quería agregar que si el OP necesita agregar una regla de validación compleja que debe estar en la base de datos, siempre puede usar procedimientos almacenados como una alternativa más segura.
Borjab

@ Borjab: Validación como para mantener la base de datos correcta, tal vez. ¿Pero el usuario se enfrenta a la validación? No.
Menno Hölscher

1
Su primera declaración dice "nunca use disparadores para hacer la validación" , pero debajo de usted escribe: "sí, puede usar disparadores para ciertos tipos de validación, y no está intrínsecamente claro dónde trazar la línea". Esto se lee bastante contradictorio. Recomendaría eliminar su primera oración, eso mejoraría mucho su respuesta. Ah, y su última oración no responde la pregunta de actualización de OP, ya que "antes / después" no tiene nada que ver con la transacción. También recomendaría eliminarlo. (vea mi comentario debajo de la pregunta de los OP).
Doc Brown

@DocBrown La distinción es entre proteger la base de datos de la corrupción y la validación del usuario. Entonces, en "cualquier validación adicional" me refiero a la validación de cara al usuario. ¿Cómo podría hacer esta distinción más clara? Para empezar, eliminé el "más allá".
Menno Hölscher

2
Está perfectamente bien hacer la validación en la base de datos. Así como está bien hacerlo en la aplicación. Ambos tienen sus ventajas. Hacer su validación en la aplicación significa que debe tener mucho cuidado cada vez que ejecuta SQL sin su ORM, que es necesario para casi todas las aplicaciones complejas.
Qwertie

1

La auditoría es un ejemplo clásico del uso efectivo de los desencadenantes. He encontrado algunos errores cometidos por el probador (moviendo un cliente de un nivel de servicio a otro) gracias a una tabla de Auditoría que fue implementada por disparadores. Recomiendo encarecidamente utilizar disparadores para la auditoría.

La validación se puede hacer en el nivel frontal, pero he visto errores extraños en la base de datos que he manejado (personas que nacieron en 3000, etc.), y como algunos de ellos los hice yo mismo, recomiendo tener una capa adicional. de validación en la base de datos, por si acaso. Por supuesto, esos tipos de errores podrían evitarse con restricciones de verificación, y muchas veces son más efectivos (en MS SQL son el método preferido; siempre verifique la documentación).


1

Debido a que la pregunta es acerca de si realmente necesitamos disparadores para bases de datos relacionales, aquí hay algunos otros casos de uso donde usar disparadores:

  1. Para auditar como se describe en las otras respuestas.
  2. Auditoría en el sentido más amplio: si se modifica una entrada de la base de datos, un desencadenante puede registrar el evento para el procesamiento posterior erróneo, por ejemplo, exportaciones nocturnas a otra aplicación.
  3. Desencadenantes para vistas: los desencadenantes se pueden definir instead of. Con este medio, uno puede insertar, actualizar y eliminar entradas de una vista. Los desencadenantes pueden extender estas acciones en varias tablas. Esta es una forma de hacer que una vista restringida esté disponible sin exponer los detalles de las tablas subyacentes.
  4. Para guardar explícitamente los cambios de la base de datos: suponga una relación N: M entre la tabla A y B y una tabla intermedia R. Puede definir restricciones de clave externa de R a A, así como B, especificando que la entrada en R se debe descartar si la entrada correspondiente en B se elimina. Sin embargo, la lógica de negocios a veces requiere que las entradas en A deben tener al menos una relación con una entrada en B. En este caso, un desencadenante en la eliminación de R puede ayudar a hacer cumplir esta lógica: si para una entrada en A la última entrada en R se elimina, entonces el disparador puede eliminar A. En la vista centrada en la aplicación, se necesitan al menos dos vueltas. Este es un ejemplo de validación. Se pueden concebir otros ejemplos: además de los casos de uso (1), (2),
  5. Confianza: a veces los administradores de bases de datos cambian las entradas en la línea de comandos que no usan su aplicación. Los administradores trabajan con cuidado y saben lo que hacen. Sin embargo, a veces pueden estar equivocados. Si la consistencia es crítica, un gatillo es su cinturón de seguridad.

Como inconveniente, la lógica de negocios se distribuye entre las capas y esto es una desventaja importante para el mantenimiento. Como escribió otro autor, es un límite delgado entre la aplicación y la base de datos y la elección no siempre es clara. Mi opinión personal es que los disparadores suponen una carga para los desarrolladores. Pueden ahorrar tiempo en el desarrollo. Definitivamente mejoran la experiencia del usuario porque aumentan el rendimiento en conexiones de red lentas.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.