I trigger del database sono malvagi? [chiuso]


187

I trigger di database sono una cattiva idea?

Nella mia esperienza sono cattivi, perché possono provocare effetti collaterali sorprendenti e sono difficili da eseguire il debug (specialmente quando un grilletto spara un altro). Spesso gli sviluppatori non pensano nemmeno di vedere se c'è un trigger.

D'altra parte, sembra che se si ha la logica che deve verificarsi negli straordinari, una nuova FOOviene creata nel database, quindi il posto più sicuro per metterlo è un trigger di inserimento sulla tabella FOO.

L'unica volta che utilizziamo i trigger è per cose davvero semplici come l'impostazione di ModifiedDate.


31
Questa è una domanda totalmente legittima ma non mi piace molto il titolo sensazionalista. Penso a qualcosa del tipo "Quali sono i problemi più importanti da considerare quando si implementano i trigger di database?" sarebbe molto meglio.
Tamas Czinege,

2
La domanda è chiusa per l'aggiunta di risposte, ma vedi anche I trigger del database sono sicuri per i vincoli di integrità della tabella? . (Spoiler: no, non lo sono)
Mifeet,

16
Questo sito mi fa incazzare così tanto. Questa è una GRANDE domanda, ma come molte altre è chiusa perché alla gente manca l'immaginazione di accettare domande che non si adattano al primitivo formato binario di domande e risposte che per qualche ragione aliena si sentono in dovere di seguire.
Quibblesome

1
La logica di business in un trigger è problematica (male, se vuoi). La logica del database in un trigger non è problematica (integrità, registrazione).
Greg Gum,

1
Mi piace fare affidamento su IDE per la navigazione del codice e capire cosa sta succedendo. Non posso farlo se metà della logica è nel database e l'altra metà nel linguaggio di programmazione preferito. Invece di trigger, trovo più facile creare un controller che ogni richiesta debba passare. Tutti i "trigger" possono invece essere applicati lì.
Muhammad Umer,

Risposte:


147

I principali problemi con i trigger sono

  • Sono completamente globali - si applicano indipendentemente dal contesto dell'attività della tabella;
  • Sono furtivi; è facile dimenticare che sono lì fino a quando non ti fanno del male con conseguenze indesiderate (e molto misteriose).

Questo significa solo che devono essere usati con attenzione per le circostanze appropriate; che nella mia esperienza è limitato a problemi di integrità relazionale (a volte con granularità più fine di quanto si possa ottenere in modo dichiarativo); e di solito non per scopi commerciali o transazionali. YMMV.


20
Questi sono 2 vantaggi, in alcuni casi.
Johnno Nolan,

18
"Stealthy" è un'ottima parola, sì - ben detto. Questo è esattamente il motivo per cui tendo a evitarlo: troppo spesso vengono dimenticati o ignorati. Nella mia esperienza personale, i grilletti rivisitati sono spesso accompagnati da un tocco alla mia stessa fronte.
Christian Nunciato,

5
Globale è il motivo per cui sono buoni e necessari per l'integrità dei dati e cose come l'auditing. Non è un aspetto negativo, è un vantaggio.
HLGEM,

4
quindi @ RobertŠevčík-Robajz, stai dicendo che tutti gli sviluppatori che conosci sono incompleti?
HLGEM,

3
@HGLEM, d'accordo che dovrebbe esserci uno specialista per elaborare i trigger. Scenario di vita reale - non c'è. Scenario di vita reale: giorni trascorsi nel tentativo di identificare un bug relativo a un trigger dimenticato. Scenario di vita reale: la logica di trigger viene disperatamente spostata nella logica dell'applicazione dove può essere facilmente rifattorizzata e testata dall'unità. È la vita reale di cui mi occupo che mi fa dire "stai lontano dai grilletti" ... non è colpa dei grilletti in quanto non è colpa delle pietre che le finestre si rompono.
Rbjz,

80

No, in realtà sono una buona idea. Se c'è un problema con i tuoi trigger specifici, allora non li stai facendo bene, ma di solito significa che c'è un problema con la tua implementazione, non il concetto di trigger stessi :-).

Utilizziamo i trigger molto perché pone l'attività specifica del DBMS sotto il controllo del database a cui appartiene. Gli utenti di un DBMS non dovrebbero preoccuparsi di questo tipo di cose. L'integrità dei dati risiede nel database stesso, non nelle applicazioni o negli utenti che lo utilizzano. Senza vincoli, trigger e altre funzionalità nel database, è lasciato alle applicazioni per applicare le regole e per distruggere i dati è sufficiente una sola applicazione / utente non valida o errata.

Ad esempio, senza trigger, cose meravigliose come le colonne generate automaticamente non esisterebbero e dovresti elaborare una funzione su ogni riga quando le selezioni. È probabile che uccida le prestazioni del DBMS, molto meglio creare la colonna generata automaticamente al momento dell'inserimento / aggiornamento poiché è l'unica volta che cambia.

Inoltre, la mancanza di trigger impedirebbe l'applicazione di regole di dati nel DBMS come i pre-trigger per garantire che le colonne abbiano un formato specifico. Si noti che questo è diverso dalle regole di integrità dei dati che sono generalmente solo ricerche di chiavi esterne.


9
msgstr "elabora una funzione su ogni riga quando la seleziona". A tale scopo è meglio utilizzare un indice basato sulle funzioni piuttosto che un trigger.
tuinstoel,

10
Non necessariamente, il trigger probabilmente verrà eseguito solo quando la riga viene inserita o aggiornata. L'indice basato sulle funzioni verrà eseguito per ogni selezione. A seconda del modello di utilizzo, uno è probabilmente migliore dell'altro. Ma nessuno dei due è SEMPRE migliore dell'altro.
jmucchiello,

@tuinstoel: devo essere d'accordo con la tua affermazione qualche volta. Oracle, ad esempio, creerà indici basati su funzioni solo se può dimostrare che la funzione è deterministica. A volte questo non può essere provato (ad esempio, se la funzione prevede una ricerca da una tabella, anche se sai che i dati della tabella non cambiano mai).
Adam Paynter,

50

Gli strumenti non sono mai cattivi. Le applicazioni di questi strumenti possono essere malvagie.


11
Non sono mai stato più in conflitto dopo aver letto un commento. Da un lato, sono il secondo emendamento e credo che le pistole non siano intrinsecamente malvagie: è la persona che le usa. D'altra parte, credo che i
fattori

37
Le pistole di @vbullinger non sono cattive, ma i loro grilletti lo sono;)
Darragh Enright,

2
: D Le generalizzazioni sono pericolose (ricorsivamente). Sei venuto dagli "strumenti" di tortura usati dagli inquisitori per "innescare" una confessione? +1 per la prospettiva comunque.
Rbjz,

22

Sono d'accordo. I problemi con i trigger sono le persone, non i trigger. Anche se è più da guardare, più da considerare e aumenta l'onere dei programmatori che controllano le cose correttamente, non scartiamo gli indici per semplificarci la vita. (Gli indici errati possono essere negativi tanto quanto i trigger negativi)

L'importanza dei trigger (nella mia mente) è che ...
- Qualsiasi sistema dovrebbe essere sempre in uno stato valido
- Il codice per applicare questo stato valido deve essere centralizzato (non scritto in ogni SP)

Dal punto di vista della manutenzione, un trigger è molto utile per programmatori concorrenti e problemi per quelli più giovani / dilettanti. Tuttavia, queste persone hanno bisogno di imparare e crescere in qualche modo.

Immagino che dipenda dal tuo ambiente di lavoro. Hai persone affidabili che imparano bene e ci si può fidare di essere metodiche? Altrimenti apparentemente hai due scelte:
- Accetta che dovrai perdere funzionalità per compensare
- Accetta che hai bisogno di persone diverse o di una migliore formazione e gestione

Sembrano aspri, e immagino che lo siano. Ma è la verità di base, nella mia mente ...


3
>>> I problemi con i trigger sono le persone. Sì, se solo le persone potessero codificare in assembly, lavorare con una GUI scadente, indovinare correttamente se spingere o tirare una porta mal progettata ... Qualsiasi "caratteristica" che le persone ripetutamente sbagliano è "malvagia".
Fakrudeen,

1
@Fakrudeen, qualsiasi sviluppatore che fa scattare in modo errato è incompetente ad accedere a un database.
HLGEM,

21

Penso che i trigger non siano non solo malvagi, ma necessari per una buona progettazione del database. I programmatori di applicazioni pensano che i database siano interessati solo dalla loro applicazione. Spesso hanno torto. Se l'integrità dei dati deve essere mantenuta indipendentemente da dove provenga la modifica dei dati, i trigger sono un requisito ed è sciocco evitarli perché alcuni programmatori sono troppo etnocentrici per considerare che qualcosa di diverso dalla loro preziosa applicazione potrebbe influenzare le cose. Non è difficile progettare, testare o risolvere un problema se si è sviluppatori di database competenti. Né è difficile determinare che un innesco sta causando un risultato inaspettato se ti viene in mente (come fa a me) di guardare lì. Se compare un errore che dice che una tabella a cui non sto facendo riferimento nel mio SP ha un errore FK, So senza nemmeno pensarci che il trigger sta causando il problema e quindi dovrebbe qualsiasi sviluppatore di database competente. Mettere le regole di business solo nell'applicazione è la causa numero uno che ho trovato di dati errati in quanto altri non hanno idea che la regola esista e violi nei loro processi. Le regole incentrate sui dati appartengono al database e i trigger sono fondamentali per applicare quelle più complesse.


1
Le regole incentrate sui dati appartengono al database
absin

mi ha fattosome programmers are too ethnocentric to consider that something other than their prized application may be affecting things
Kid101

13

Principalmente sì.

La difficoltà con un grilletto è che fa cose "dietro la schiena"; lo sviluppatore che mantiene l'applicazione potrebbe facilmente non rendersi conto che è lì e apportare modifiche che rovinano le cose senza nemmeno accorgersene.

Crea uno strato di complessità che aggiunge solo lavori di manutenzione.

Piuttosto che usare un trigger, una procedura / routine memorizzata, in genere può essere fatta per fare la stessa cosa, ma in modo chiaro e mantenibile: chiamare una routine memorizzata significa che lo sviluppatore può guardare il suo codice sorgente e vedere esattamente cosa sta succedendo.


12
Questo è il vantaggio di un innesco e non dello svantaggio! Non è possibile garantire che i proc memorizzati siano richiamati per ogni modifica ai dati. Esistono molti modi in cui i dati possono essere modificati oltre alla GUI.
HLGEM,

2
HLGEM, dipende dal tuo controllo di accesso. È possibile negare qualsiasi modifica alle tabelle direttamente se non tramite una procedura memorizzata.
Rbjz,

1
Penso che il punto sia che, per esempio, se i record in due tabelle dovessero SEMPRE essere creati e distrutti insieme, indipendentemente da come si accede al database e indipendentemente da chi si è o quali autorizzazioni si disponga, i trigger sono l'unica soluzione legittima . Il semplice fatto che sia persino possibile assegnare troppe autorizzazioni o errate e aspettarsi che le persone sappiano quali procedure archiviate devono essere utilizzate, significa che il database rischia di perdere la sua integrità. È esattamente lo stesso delle relazioni con le chiavi esterne. È semplicemente MIGLIORE e PIÙ AFFIDABILE applicato dal motore di database.
Triynko,

2
Se i record devono sempre essere creati / distrutti insieme, creare un vincolo di controllo che garantisca che siano. In questo modo qualcuno che infrange le regole ottiene un errore, piuttosto che un comportamento nascosto che rende magicamente le cose giuste senza la loro conoscenza o consenso.
Mark R

9

I trigger sono estremamente potenti e utili, ci sono molti scenari in cui un trigger è la migliore soluzione a un problema.

Sono anche un ottimo strumento di "hacking". Ci sono spesso situazioni in cui non si ha il controllo immediato sia del codice che del database. Se devi attendere 2 mesi per la prossima versione principale del tuo codice, ma puoi applicare immediatamente una patch al tuo database, allora puoi mettere un trigger su una tabella per eseguire alcune funzionalità aggiuntive. Quindi, quando è possibile il rilascio del codice, è possibile sostituire questo trigger con la versione codificata della stessa funzionalità, se lo si desidera.

Alla fine della giornata, tutto è "malvagio" se non sai cosa sta facendo. Decidere che i grilletti sono perché ci sono sviluppatori che non li capiscono è come sostenere che le auto sono cattive perché alcune persone non possono guidare ...


7

I trigger hanno i loro usi: la registrazione / il controllo e il mantenimento di una data "ultima modifica" sono due usi molto validi che sono stati menzionati nelle risposte precedenti.

Tuttavia, uno dei principi fondamentali del buon design è che le regole di business / la logica di business / qualunque cosa tu voglia chiamarla dovrebbe essere concentrata in un unico posto. Inserire parte della logica nel database (tramite trigger o processi memorizzati) e alcuni nell'applicazione viola tale principio. Duplicare la logica in entrambi i posti è ancora peggio, poiché invariabilmente si sincronizzeranno tra loro.

C'è anche il problema del "principio della minima sorpresa" che è già stato menzionato.


3
È corretto, dovrebbe essere in un unico posto, il database. La logica che influisce sull'integrità dei dati deve SEMPRE essere nel database e mai in un'applicazione in cui potrebbe essere o non essere chiamata quando influisce sui dati nel database.
HLGEM,

1
@HLGEM: dipende dal fatto che il database possa avere accesso alle informazioni che gli consentono di stabilire se i dati sono validi. Non è sempre possibile; quando il validatore si trova in un'altra organizzazione (ad es. per i dettagli della carta di credito o del conto bancario), il DB non può sapere se è giusto - supponendo che questo non sia il DB della banca! - e dovrà fare affidamento sulla domanda di esecuzione. Ciò che non si desidera è avere il database che effettua connessioni casuali a servizi di terze parti, poiché ciò è negativo quando si tratta di distribuzione del server.
Donal Fellows,

@HLGEM: Anche se non sono pronto a escludere completamente l'opzione di inserire tutta la logica dell'applicazione nel database, trovo che tende a funzionare meglio per metterlo altrove, generalmente un livello OO riutilizzabile che può essere utilizzato per tutte le app che accedono il database. Fintanto che la tua app accede al database solo attraverso il livello oggetto, si applicano comunque le stesse garanzie della logica sempre chiamata.
Dave Sherohman,

2
Non ho mai lavorato su un'applicazione aziendale che ha inserito solo dati nel database tramite il livello Oggetto e non voglio lavorarci su. È stupido mettere milioni di importazioni record o aggiornamenti di tutti i prezzi attraverso un processo progettato per gestire un solo record alla volta. Il livello oggetto è esattamente il posto sbagliato per imporre l'integrità dei dati, motivo per cui così tante basi di dati hanno problemi di integrità.
HLGEM,

@HLGEM Per questo motivo sto lavorando su un'estensione del nostro ORM per funzionare come un trigger utilizzando un changeset di tutto all'interno di una transazione. È un po 'sciocco, ma ci impedirà di avere tutta la nostra logica aziendale nell'applicazione tranne le poche volte in cui non lo è (solo poche tabelle richiedono mai un aggiornamento collettivo). Consentirà inoltre a tutti gli sviluppatori di scriverli e utilizzarli nella lingua che preferiscono e in cui è possibile accedere a tutte le astrazioni di oggetti che abbiamo creato.
Adamantish,

6

I trigger sono un buon strumento se usati correttamente. Soprattutto per cose come il controllo delle modifiche, il popolamento di tabelle di riepilogo, ecc.

Ora possono essere "cattivi" se finisci in "inferno di innesco" con un innesco che dà il via ad altri innescatori. Una volta ho lavorato su un prodotto COTS in cui avevano quelli che chiamavano "grilletti flessibili". Questi trigger sono stati memorizzati in una tabella man mano che le punture sql dinamiche venivano compilate ogni volta che venivano eseguite. I trigger compilati farebbero una ricerca e vedrebbero se quella tabella aveva dei trigger flex da eseguire, quindi compilare ed eseguire il trigger "flex". In teoria sembrava un'idea davvero interessante perché il prodotto era facilmente personalizzabile ma la realtà era che il database era praticamente esploso a causa di tutte le compilazioni che doveva fare ...

Quindi sì, sono fantastici se mantieni ciò che stai facendo in prospettiva. Se è qualcosa di piuttosto semplice come auditing, riepilogo, auto-sequencing, ecc., Nessun problema. Basta tenere presente il tasso di crescita della tabella e l'impatto del trigger sulle prestazioni.


6

Ad alto livello ci sono due casi d'uso per i trigger1

1) Far accadere cose "automagicamente". In questo caso, i trigger causano un effetto collaterale, cambiano i dati in modi che non erano previsti a causa dell'inserimento, dell'aggiornamento o dell'eliminazione (primitivi) dell'operatore che è stato eseguito e ha provocato l'attivazione del trigger.

Il consenso generale qui è che i trigger sono davvero dannosi. Perché cambiano la semantica ben nota di un'istruzione INSERT, UPDATE o DELETE. La modifica della semantica di questi tre operatori SQL primitivi morderà altri sviluppatori che in futuro dovranno lavorare sulle tabelle del database che non si comportano più nei modi previsti quando vengono utilizzati su di essi con le primitive SQL.

2) Per applicare regole di integrità dei dati, diverse da quelle che possiamo trattare in modo dichiarativo (usando CHECK, PRIMARY KEY, UNIQUE KEY e FOREIGN KEY). In questo caso d'uso, tutti i trigger sono dati QUERY (SELECT) per verificare se la modifica apportata da INSERT / UPDATE / DELETE è consentita o meno. Proprio come i vincoli dichiarativi fanno per noi. Solo in questo caso (gli sviluppatori) abbiamo programmato l'applicazione.

L'uso di trigger per quest'ultimo caso d'uso non è dannoso.

Sto scrivendo un blog su questo: http://harmfultriggers.blogspot.com


Quando si utilizzano i trigger per l'integrità referenziale, è più difficile di quanto sembri gestire i problemi di concorrenza.
WW.

2
Concordato. Ma è più facile quando si usano altri mezzi?
Toon Koppelaars l'

Direi che il numero uno è dannoso solo se hai sviluppatori incompetenti.
HLGEM,

Ci sono MOLTI sviluppatori incompetenti sebbene lol.
Hashtable

5

So che gli sviluppatori che pensano che i trigger debbano essere sempre utilizzati laddove è il modo più diretto per ottenere le funzionalità che desiderano e gli sviluppatori che non lo faranno mai. È quasi come un dogma tra i due campi.

Tuttavia, personalmente sono completamente d'accordo con MarkR: puoi (quasi) scrivere sempre un codice funzionalmente equivalente al trigger che sarà più evidente e quindi più facile da mantenere.


Tranne che non tutto il lavoro per colpire un database scorre attraverso il codice dell'applicazione.
HLGEM,

5

Non male. In realtà semplificano cose come

1. Registrazione / controllo delle modifiche ai record o persino degli schemi di database

Potresti avere un trigger su ALTER TABLE che ripristina le modifiche nel tuo ambiente di produzione. Ciò dovrebbe impedire qualsiasi modifica accidentale della tabella.


2. Applicazione dell'ingerenza referenziale (relazioni chiave primaria / esterna, ecc.) Su più database


È possibile ripristinare le dichiarazioni DDL?
Andrew Swan,

Generalmente no. L'unico modo per fermarlo è rimuovere tale autorizzazione dagli accessi degli utenti.
jmucchiello,

In alcuni motori di database è possibile (ad esempio PostgreSQL).
Nicolás,

@Andrew - In SQL Server puoi. SQL Server 2005+ ha anche trigger DDL che si attivano su eventi come ALTER TABLE.
Martin Smith,

4

No, non sono cattivi - sono solo fraintesi MrGreen

I trigger hanno un uso valido, ma troppo spesso come un hack retrò che alla fine peggiora le cose.

Se stai sviluppando un DB come parte di un'applicazione, la logica dovrebbe essere sempre nel codice o negli sprocs che effettuano la chiamata. I trigger porteranno solo a debug-dolore in seguito.

Se capisci come il blocco, il deadlock e come i DB accedono ai file su disco, allora usare i trigger nel modo giusto (ad esempio controllo o archiviazione dell'accesso diretto al DB) può essere davvero prezioso.


4

Dire che sono cattivi è un'esagerazione ma possono causare delle maglie. Quando l'attivazione di un grilletto provoca altri grilletti, diventa davvero complicato. Diciamo che sono fastidiosi: http://www.oracle.com/technology/oramag/oracle/08-sep/o58asktom.html

Fare la logica di business in Oracle con i trigger è più difficile di quanto sembri a causa di problemi con più concorrenza. Non vedi le modifiche in un'altra sessione fino a quando non viene eseguito il commit delle altre sessioni.


4

Non sono sicuramente cattivi. Ho trovato i trigger preziosi durante il refactoring degli schemi di database, durante la ridenominazione di una colonna o la divisione di una colonna in due colonne o viceversa (esempio: caso nome / cognome) e assistenza alla transizione.

Sono anche molto utili per l'auditing.


4

Questa risposta si applica specificamente a SQL Server. (sebbene possa applicarsi anche ad altri RDBMS, non ne ho idea. Avrei preferito dargli una risposta qui, ma questo è stato chiuso come un inganno.)

Un aspetto non menzionato finora in nessuna delle risposte è la sicurezza. Poiché, per impostazione predefinita, i trigger vengono eseguiti nel contesto dell'utente che esegue l'istruzione che provoca l'attivazione del trigger, ciò può causare una minaccia alla sicurezza a meno che tutti i trigger non vengano esaminati.

L'esempio fornito in BOL sotto l' intestazione " Gestione della sicurezza dei trigger " è di un utente che crea un trigger contenente il codice GRANT CONTROL SERVER TO JohnDoe ;per aumentare le proprie autorizzazioni.


3

Se ci sono effetti collaterali, è un problema in base alla progettazione. In alcuni sistemi di database, non esiste altra possibilità per impostare un campo di incremento automatico, ad es. Per un campo ID chiave primaria.


3

Penso che possano essere malvagi, ma solo cattivi come qualsiasi altra cosa in fase di sviluppo.

Anche se non ho molta esperienza con loro, li ho avuti su un recente progetto a cui ho lavorato che mi ha portato a questa conclusione. Il problema che ho con loro è che possono causare la logica di business in due posizioni, una libreria di codici e un database.

Lo vedo come un argomento simile con l'utilizzo di sprocs. Avrai spesso sviluppatori che sono davvero bravi a scrivere la logica di business nel database nel database, mentre le persone che non lo sono avranno la loro logica di business altrove.

Quindi la mia regola empirica è guardare qual è la struttura del tuo progetto. Se sembra fattibile avere una logica di business memorizzata nel database, potrebbe essere utile disporre di trigger.


1

In effetti, abbastanza spesso i trigger vengono utilizzati in modo improprio. In realtà nella maggior parte dei casi non ne hai nemmeno bisogno. Ma ciò non li rende necessariamente cattivi.

Uno scenario che mi viene in mente in cui i trigger sono utili è quando hai un'applicazione legacy per la quale non hai il codice sorgente e non c'è modo di cambiarlo.


1

L'idea di trigger non è malvagia, limitare la nidificazione di trigger è malvagia.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.