¿Los desencadenantes de la base de datos son malos? [cerrado]

187

¿Los desencadenantes de la base de datos son una mala idea?

En mi experiencia, son malvados, porque pueden provocar efectos secundarios sorprendentes y son difíciles de depurar (especialmente cuando un disparador dispara a otro). A menudo, los desarrolladores ni siquiera piensan en ver si hay un disparador.

Por otro lado, parece que si tiene una lógica que debe ocurrir cada vez que se crea una nueva FOOen la base de datos, el lugar más infalible para colocarla es un disparador de inserción en la tabla FOO.

La única vez que usamos disparadores es para cosas realmente simples como configurar el ModifiedDate.

WW.
fuente
31
Esta es una pregunta totalmente legítima, pero no me gusta el título sensacionalista. Creo que algo así como "¿Cuáles son los temas más importantes a considerar al implementar los desencadenantes de la base de datos?" Estaría mucho mejor.
Tamas Czinege
2
La pregunta está cerrada para agregar respuestas, pero vea también ¿Son seguros los desencadenantes de la base de datos para las restricciones de integridad de la tabla cruzada? . (Spoiler: no, no lo son)
Mifeet
16
Este sitio me molesta mucho. Esta es una GRAN pregunta pero, como muchas otras, está cerrada porque las personas carecen de imaginación para aceptar preguntas que no encajan en el formato binario primitivo de preguntas y respuestas que, por alguna razón extraña, se sienten obligadas a seguir.
Triste
1
La lógica de negocios en un disparador es problemática (malvada, por así decirlo). La lógica de base de datos en un desencadenador no es problemática (integridad, registro).
Greg Gum
1
Me gusta confiar en IDE para la navegación de código y comprender lo que está sucediendo. No puedo hacer eso si la mitad de la lógica está en la base de datos y la otra mitad en el lenguaje de programación de elección. En lugar de disparadores, me resulta más fácil crear un controlador por el que cada solicitud debe pasar. Todos los 'disparadores' pueden aplicarse allí en su lugar.
Muhammad Umer

Respuestas:

147

Los principales problemas con los desencadenantes son

  • Son completamente globales: se aplican sin importar el contexto de la actividad de la tabla;
  • Son sigilosos; Es fácil olvidar que están allí hasta que te lastimen con consecuencias no deseadas (y muy misteriosas).

Esto solo significa que deben usarse con cuidado para las circunstancias adecuadas; que en mi experiencia se limita a problemas de integridad relacional (a veces con una granularidad más fina de la que se puede obtener declarativamente); y generalmente no para fines comerciales o transaccionales. YMMV.

dkretz
fuente
20
Esas son 2 ventajas, en algunos casos.
Johnno Nolan
18
"Sigilo" es una gran palabra, sí, bien dicho. Eso es exactamente por lo que tiendo a evitarlos: con demasiada frecuencia se olvidan o se ignoran. En mi experiencia personal, la revisión de los desencadenantes suele ir acompañada de un golpe en la frente.
Christian Nunciato
55
Global es la razón por la cual son buenos y necesarios para la integridad de los datos y cosas como la auditoría. No es una desventaja, es una ventaja.
HLGEM
44
entonces @ RobertŠevčík-Robajz, ¿estás diciendo que todos los desarrolladores que conoces son incompetentes?
HLGEM
3
@HGLEM, de acuerdo en que debería haber un especialista para resolver los desencadenantes. Escenario de la vida real: no lo hay. Escenario de la vida real: días dedicados a tratar de identificar un error relacionado con un activador olvidado. Escenario de la vida real: la lógica de activación se está empujando desesperadamente a la lógica de la aplicación, donde se puede refactorizar fácilmente y probar la unidad. La vida real con la que trato me hace decir "mantente alejado de los disparadores" ... no es culpa de los disparadores ya que no es culpa de las piedras que las ventanas se rompan.
Rbjz
80

No, en realidad son una buena idea. Si hay un problema con sus desencadenantes específicos, entonces no los está haciendo bien, pero eso generalmente significa que hay un problema con su implementación, no el concepto de los desencadenantes en sí :-).

Usamos desencadenantes mucho porque coloca la actividad específica de DBMS bajo el control de la base de datos a la que pertenece. Los usuarios de un DBMS no deberían tener que preocuparse por ese tipo de cosas. La integridad de los datos recae en la base de datos en sí, no en las aplicaciones o usuarios que la usan. Sin restricciones y desencadenantes y otras características en la base de datos, las aplicaciones deben cumplir las reglas y solo se necesita una aplicación / usuario malintencionado o con errores para destruir los datos.

Por ejemplo, sin disparadores, no existirían cosas tan maravillosas como columnas autogeneradas y tendría que procesar una función en cada fila al seleccionarlas. Es probable que mate el rendimiento de DBMS, mucho mejor crear la columna generada automáticamente en el momento de inserción / actualización, ya que esa es la única vez que cambia.

Además, la falta de activadores evitaría que las reglas de datos se apliquen en el DBMS, como los activadores previos, para garantizar que las columnas tengan un formato específico. Tenga en cuenta que esto es diferente de las reglas de integridad de datos que generalmente son solo búsquedas de claves externas.

paxdiablo
fuente
9
"procesar una función en cada fila al seleccionarlas". Es mejor usar un índice basado en funciones para este propósito que un disparador.
tuinstoel
10
No necesariamente, el disparador probablemente solo se ejecutará cuando la fila se inserte o actualice. El índice basado en funciones se ejecutará para cada selección. Dependiendo del patrón de uso, uno es probablemente mejor que el otro. Pero ninguno es SIEMPRE mejor que el otro.
jmucchiello
@tuinstoel: Tengo que estar de acuerdo con su declaración algunas veces. Oracle, por ejemplo, solo creará índices basados ​​en funciones si puede probar que la función es determinista. A veces eso simplemente no se puede probar (por ejemplo, si la función implica una búsqueda desde una tabla, incluso si sabe que los datos de la tabla nunca cambian).
Adam Paynter
50

Las herramientas nunca son malas. Las aplicaciones de esas herramientas pueden ser malas.

Andy Webb
fuente
11
Nunca he tenido más conflictos después de leer un comentario. Por un lado, soy pro segunda enmienda y creo que las armas no son intrínsecamente malas: es la persona que las usa. Por otro lado, creo que los desencadenantes SON malvados ... Creo que estoy teniendo una crisis existencial ...
vbullinger
37
@vbullinger las armas no son malas, pero sus desencadenantes sí lo son;)
Darragh Enright
2
: D Las generalizaciones son peligrosas (recursivamente). ¿Has encontrado las 'herramientas' de tortura utilizadas por los inquisidores para 'desencadenar' una confesión? +1 para la perspectiva de todos modos.
Rbjz
22

Estoy de acuerdo. El problema con los desencadenantes son las personas, no los desencadenantes. Aunque es más para mirar, más para considerar y aumenta la responsabilidad de que los codificadores verifiquen las cosas correctamente, no descartamos los índices para simplificar nuestras vidas. (Los índices malos pueden ser tan malos como los desencadenantes malos)

La importancia de los desencadenantes (en mi opinión) es que ...
- Cualquier sistema siempre debe estar en un estado válido
- El código para hacer cumplir este estado válido debe estar centralizado (no escrito en cada SP)

Desde el punto de vista del mantenimiento, un disparador es muy útil para los codificadores competidores y los problemas para los más jóvenes / aficionados. Sin embargo, estas personas necesitan aprender y crecer de alguna manera.

Supongo que se trata de su entorno de trabajo. ¿Tiene personas confiables que aprenden bien y se puede confiar en que sean metódicas? Si no, aparentemente tiene dos opciones:
- Aceptar que tendrá que perder la funcionalidad para compensar
- Aceptar que necesita personas diferentes o una mejor capacitación y administración

Suenan duras, y supongo que lo son. Pero es la verdad básica, en mi mente ...

MatBailie
fuente
3
>>> Los problemas con los desencadenantes son las personas. Sí, si solo las personas pudieran codificar en el ensamblaje, trabajar con una GUI horrible, adivinar correctamente si empujar o tirar de una puerta mal diseñada ... Cualquier "característica" que las personas se equivoquen repetidamente es "malvada".
Fakrudeen
1
@Fakrudeen, cualquier desarrollador que obtiene disparadores incorrectos es incapaz de acceder a una base de datos.
HLGEM
21

Creo que los desencadenantes no solo no son malos, sino que son necesarios para un buen diseño de la base de datos. Los programadores de aplicaciones piensan que las bases de datos solo se ven afectadas por su aplicación. A menudo están equivocados. Si se quiere mantener la integridad de los datos sin importar de dónde provienen los cambios de datos, los disparadores son un requisito y es una tontería evitarlos porque algunos programadores son demasiado etnocéntricos para considerar que algo diferente a su aplicación preciada puede estar afectando las cosas. No es difícil diseñar, probar o solucionar un disparador si es un desarrollador de bases de datos competente. Tampoco es difícil determinar que un desencadenante está causando un resultado inesperado si se te ocurre (como a mí) mirar allí. Si recibo un error que dice que una tabla a la que no estoy haciendo referencia en mi sp tiene un error FK, Sé sin siquiera pensarlo que el desencadenante está causando el problema y también cualquier desarrollador de bases de datos competente. Poner reglas de negocios solo en la aplicación es la causa número uno por la que he encontrado datos incorrectos, ya que otros no tienen idea de que esa regla existe y la viola en sus procesos. Las reglas centradas en datos pertenecen a la base de datos y los desencadenantes son clave para hacer cumplir las más complejas.

HLGEM
fuente
1
Las reglas centradas en datos pertenecen a la base de datos
desde el
me teníasome programmers are too ethnocentric to consider that something other than their prized application may be affecting things
Kid101
13

Mayormente sí.

La dificultad con un disparador es que hace cosas "detrás de la espalda"; el desarrollador que mantiene la aplicación podría no darse cuenta fácilmente de que está allí y hacer cambios que arruinen las cosas sin siquiera darse cuenta.

Crea una capa de complejidad que solo agrega trabajo de mantenimiento.

En lugar de usar un disparador, un procedimiento / rutina almacenada, generalmente se puede hacer para que haga lo mismo, pero de una manera clara y sostenible: llamar a una rutina almacenada significa que el desarrollador puede ver su código fuente y ver exactamente lo que está sucediendo.

MarkR
fuente
12
¡Esta es la ventaja de un disparador, no la desventaja! No se puede garantizar que los procesos almacenados se invoquen para cada cambio en los datos. Hay muchas formas en que se pueden cambiar los datos además de la GUI.
HLGEM
2
HLGEM, eso depende de su control de acceso. Puede denegar cualquier modificación a las tablas directamente, excepto a través de un procedimiento almacenado.
Rbjz
1
Creo que el punto es que si, por ejemplo, los registros en dos tablas SIEMPRE deben crearse y destruirse juntos, sin importar cómo acceda a la base de datos, y sin importar quién es o qué permisos tiene, entonces los disparadores son la única solución legítima . El mero hecho de que incluso sea ​​posible asignar demasiados permisos o incorrectos y esperar que las personas sepan qué procedimientos almacenados se utilizarán, significa que la base de datos está en riesgo de perder su integridad. Es exactamente lo mismo que las relaciones de claves externas. Es simplemente MEJOR y MÁS CONFIABLE impuesto por el motor de base de datos.
Triynko
2
Si los registros siempre deben crearse / destruirse juntos, cree una restricción de verificación que garantice que lo sean. De esa manera, alguien que infringe las reglas obtiene un error, en lugar de un comportamiento oculto que mágicamente hace las cosas bien sin su conocimiento o consentimiento.
MarkR
9

Los desencadenantes son extremadamente potentes y útiles, existen varios escenarios en los que un desencadenante es la mejor solución a un problema.

También son una muy buena herramienta de "pirateo". A menudo hay situaciones en las que no tiene el control inmediato tanto del código como de la base de datos. Si tiene que esperar 2 meses para la próxima versión principal de su código, aún puede aplicar un parche a su base de datos inmediatamente y luego puede poner un disparador en una tabla para realizar alguna funcionalidad adicional. Luego, cuando sea posible la liberación del código, puede reemplazar este disparador con su versión codificada de la misma funcionalidad si lo desea.

Al final del día, todo es "malvado" si no sabes lo que está haciendo. Decidir que los factores desencadenantes se deben a que hay desarrolladores que no los entienden es lo mismo que argumentar que los automóviles son malos porque algunas personas no pueden conducir ...

Día de robin
fuente
7

Los disparadores tienen sus usos: el registro / auditoría y el mantenimiento de una fecha de "última modificación" son dos usos muy buenos que se han mencionado en respuestas anteriores.

Sin embargo, uno de los principios básicos del buen diseño es que las reglas de negocio / lógica de negocios / como quiera llamarlo deben concentrarse en un solo lugar. Poner algo de la lógica en la base de datos (a través de disparadores o procesos almacenados) y algo en la aplicación viola ese principio. Duplicar la lógica en ambos lugares es aún peor, ya que invariablemente se desincronizarán entre sí.

También está el tema del "principio de la menor sorpresa" que ya se ha mencionado.

Dave Sherohman
fuente
3
Eso es correcto, debería estar en un lugar, la base de datos. La lógica que afecta la integridad de los datos SIEMPRE debe estar en la base de datos y nunca en una aplicación donde pueda o no ser llamada cuando afecta los datos en la base de datos.
HLGEM
1
@HLGEM: Eso depende de si la base de datos puede tener acceso a información que le permita saber si los datos son válidos. No siempre es así; cuando el validador está en otra organización (p. ej., para detalles de la tarjeta de crédito o de la cuenta bancaria), el DB no puede saber si es correcto, ¡suponiendo que este no sea el DB del banco! - y tendrá que depender de la aplicación para la ejecución. Lo que no desea es que la base de datos realice conexiones aleatorias a servicios de terceros, ya que eso es malo cuando se trata de la implementación del servidor.
Donal Fellows
@HLGEM: Si bien no estoy listo para descartar por completo la opción de poner toda la lógica de la aplicación en la base de datos, creo que tiende a funcionar mejor para colocarla en otro lugar, generalmente una capa OO reutilizable que se puede usar para todas las aplicaciones que acceden la base de datos. Mientras su aplicación solo acceda a la base de datos a través de la capa de objeto, se seguirán aplicando las mismas garantías de la lógica que siempre se llama.
Dave Sherohman
2
Nunca trabajé en una aplicación comercial que solo insertara datos en la base de datos a través de la capa Objeto y no querría trabajar en una. Es estúpido poner millones de importaciones récord o actualizaciones de todos los precios a través de un proceso diseñado para manejar solo un registro a la vez. La capa de objetos es exactamente el lugar equivocado para hacer cumplir la integridad de los datos, por lo que tantas bases de datos tienen problemas de integridad.
HLGEM
@HLGEM Por esa misma razón, estoy trabajando en una extensión de nuestro ORM para que funcione como un disparador usando un conjunto de cambios de todo dentro de una transacción. Se siente un poco tonto, pero nos impedirá tener toda nuestra lógica de negocios en la aplicación, excepto las pocas veces que no lo es (solo unas pocas tablas necesitan una actualización masiva). También permitirá a todos los desarrolladores escribirlos y usarlos en el lenguaje con el que se sientan más cómodos y donde haya acceso a todas las abstracciones de objetos que hemos construido.
Adamantish
6

Los disparadores son una buena herramienta cuando se usan correctamente. Especialmente para cosas como auditar cambios, completar tablas de resumen, etc.

Ahora pueden ser "malvados" si terminas en "gatillo infierno" con un gatillo que inicia otros gatillos. Una vez trabajé en un producto COTS donde tenían lo que llamaron "disparadores flexibles". Estos desencadenantes se almacenaron en una tabla a medida que se compilaban picaduras dinámicas de SQL cada vez que se ejecutaban. Los activadores compilados buscarían y verían si esa tabla tenía algún activador flexible para ejecutar y luego compilarían y ejecutarían el activador "flexible". En teoría, esto parecía una idea realmente genial porque el producto se personalizaba fácilmente, pero la realidad era que la base de datos prácticamente explotó debido a todas las compilaciones que tenía que hacer ...

Así que sí, son geniales si mantienes lo que estás haciendo en perspectiva. Si es algo bastante simple como la auditoría, el resumen, la secuencia automática, etc., no hay problema. Solo tenga en cuenta la tasa de crecimiento de la tabla y cómo el desencadenante afectará el rendimiento.

tmeisenh
fuente
6

En un nivel alto hay dos casos de uso para los desencadenantes1

1) Hacer que las cosas sucedan "automágicamente". En este caso, los desencadenantes causan un efecto secundario, cambian los datos de formas que no se esperaban dado que el operador (primitivo) inserta, actualiza o elimina que se ejecutó y provocó el disparo del disparador.

El consenso general aquí es que los desencadenantes son realmente dañinos. Porque cambian la semántica bien conocida de una instrucción INSERT, UPDATE o DELETE. Cambiar la semántica de estos tres operadores primitivos de SQL morderá a otros desarrolladores que más adelante en el futuro necesitarán trabajar en las tablas de su base de datos que ya no se comportan de la manera esperada cuando se operan con las primitivas de SQL.

2) Para hacer cumplir las reglas de integridad de datos, distintas de las que podemos tratar de manera declarativa (usando CHECK, PRIMARY KEY, UNIQUE KEY y FOREIGN KEY). En este caso de uso, todo lo que hacen los desencadenantes son los datos de CONSULTA (SELECCIONAR) para verificar si el cambio realizado por INSERT / UPDATE / DELETE está permitido o no. Al igual que las restricciones declarativas lo hacen por nosotros. Solo en este caso nosotros (los desarrolladores) hemos programado la aplicación.

Usar disparadores para este último caso de uso no es dañino.

Estoy blogueando sobre eso en: http://harmfultriggers.blogspot.com

Toon Koppelaars
fuente
Cuando se utilizan disparadores para la integridad referencial, es más difícil de lo que parece manejar los problemas de concurrencia.
WW.
2
Convenido. ¿Pero es más fácil cuando se usan otros medios?
Toon Koppelaars
Yo diría que el número uno solo es perjudicial si tienes desarrolladores incompetentes.
HLGEM
Hay MUCHOS desarrolladores incompetentes aunque jajaja.
tabla hash
5

Sé que los desarrolladores que piensan que los disparadores siempre deben usarse donde sea la forma más directa de lograr la funcionalidad que desean, y los desarrolladores que nunca lo harán. Es casi como un dogma entre los dos campos.

Sin embargo, personalmente estoy completamente de acuerdo con MarkR: puede (casi) siempre escribir código funcionalmente equivalente al desencadenante que será más llamativo y, por lo tanto, más fácil de mantener.

DanSingerman
fuente
Excepto que no todo el trabajo para llegar a una base de datos fluye a través del código de la aplicación.
HLGEM
5

No es malvado En realidad simplifican cosas como

1.Inicio de sesión / auditoría de cambios en registros o incluso esquemas de bases de datos

Podría tener un activador en ALTER TABLE que revierta los cambios en su entorno de producción. Esto debería evitar cualquier modificación accidental de la tabla.


2. Hacer cumplir la integridad referencial (relaciones de clave primaria / extranjera, etc.) en múltiples bases de datos

Chris
fuente
¿Puede revertir las declaraciones DDL?
Andrew Swan el
En general no. La única forma de detener eso es eliminar ese permiso de los inicios de sesión de los usuarios.
jmucchiello
En algunos motores de bases de datos puede (por ejemplo, PostgreSQL).
Nicolás
@ Andrew - En SQL Server puedes. SQL Server 2005+ también tiene desencadenadores DDL que se activan en eventos como ALTER TABLE.
Martin Smith
4

No, no son malvados, simplemente son malentendidos :-D

Los disparadores tienen un uso válido, pero con demasiada frecuencia como un retro-pirateo que finalmente empeora las cosas.

Si está desarrollando una base de datos como parte de una aplicación, la lógica siempre debe estar en el código o en los sprocs que realizan la llamada. Los disparadores solo conducirán a un dolor de depuración más adelante.

Si comprende cómo bloquear, bloquear y cómo los DB acceden a los archivos en el disco, puede ser realmente valioso usar disparadores de la manera correcta (por ejemplo, auditar o archivar el acceso directo a DB).

Keith
fuente
4

Decir que son malvados es una exageración pero pueden causar mallas. Cuando el disparo de un disparador hace que se disparen otros disparadores, se vuelve realmente complicado. Digamos que son problemáticos: http://www.oracle.com/technology/oramag/oracle/08-sep/o58asktom.html

Hacer lógica de negocios en Oracle con disparadores es más difícil de lo que parece debido a problemas de concurrencia múltiple. No verá cambios en otra sesión hasta que se confirmen las otras sesiones.

tuinstoel
fuente
4

Definitivamente no son malvados. Encontré factores desencadenantes valiosos durante la refactorización de los esquemas de la base de datos, al cambiar el nombre de una columna o al dividir una columna en dos columnas o viceversa (ejemplo: caso de nombre / apellido) y ayudar a la transición.

También son muy útiles para la auditoría.

Stefano Borini
fuente
4

Esta respuesta se aplica específicamente a SQL Server. (aunque también puede aplicarse a otros RDBMS, no tengo idea. Hubiera preferido darlo aquí como respuesta , pero eso se cerró como un engaño de esto).

Un aspecto no mencionado en ninguna de las respuestas hasta ahora es la seguridad. Debido a que, de manera predeterminada, los desencadenantes se ejecutan en el contexto del usuario que ejecuta la instrucción que hace que se active el desencadenador, esto puede causar una amenaza de seguridad a menos que se revisen todos los desencadenantes.

El ejemplo dado en BOL bajo el encabezado " Gestión de la seguridad del disparador " es de un usuario que crea un disparador que contiene el código GRANT CONTROL SERVER TO JohnDoe ;para escalar sus propios permisos.

Martin Smith
fuente
3

Si hay efectos secundarios, es un problema por diseño. En algunos sistemas de bases de datos, no hay otra posibilidad de establecer un campo de aumento automático, es decir, para un campo de ID de clave principal.

Xn0vv3r
fuente
3

Creo que pueden ser malvados, pero solo tan malvados como cualquier otra cosa en desarrollo.

Aunque realmente no tengo mucha experiencia con ellos, los tuve en un proyecto reciente en el que trabajé que me ha llevado a esta conclusión. El problema que tengo con ellos es que pueden hacer que la lógica de negocios termine en dos ubicaciones, una biblioteca de códigos y una base de datos.

Lo veo como un argumento similar con el uso de sprocs. A menudo tendrá desarrolladores que son realmente buenos en SQL escribiendo lógica de negocios en la base de datos, mientras que las personas que no lo sean tendrán su lógica de negocios en otra parte.

Entonces, mi regla general es ver cuál es la estructura de su proyecto. Si parece viable tener una lógica de negocios almacenada en la base de datos, podría ser útil tener disparadores.

Aaron Powell
fuente
1

De hecho, con frecuencia los desencadenantes están siendo mal utilizados. En realidad, en la mayoría de los casos, ni siquiera los necesitas. Pero eso no los hace necesariamente malos.

Un escenario que me viene a la mente donde los desencadenantes son útiles es cuando tienes una aplicación heredada para la que no tienes el código fuente y no hay forma de cambiarlo.

ibz
fuente
1

La idea de los desencadenantes no es mala, limitar la anidación de los desencadenantes es malo.

alpav
fuente