2011-10-30 22 views
27

Mi sono confuso con un concetto apparentemente semplice. Mysql definisce funzione deterministica come una funzione cheFunzione deterministica in mysql

produce sempre lo stesso risultato parametri lo stesso ingresso

Così nella mia comprensione, funzioni come

CREATE FUNCTION foo (val INT) READS SQL DATA 
BEGIN 
    DECLARE retval INT; 
    SET retval = (SELECT COUNT(*) FROM table_1 WHERE field_1 = val); 
    RETURN retval; 
END; 

non sono deterministico (c'è nessuna garanzia che cancellazione/aggiornamento/inserimento non avvenga tra 2 chiamate alla funzione). Allo stesso tempo, ho visto molte funzioni che funzionano più o meno allo stesso modo, ovvero restituiscono il valore in base al risultato di query e dichiarato come DETERMINISTIC. Sembra che mi manchi qualcosa di molto semplice.

Qualcuno potrebbe chiarire questo problema?

Grazie.

Aggiornamento Grazie per coloro che hanno risposto (+1); finora sembra che ci sia un diffuso abuso della parola chiave DETERMINISTIC. È ancora difficile credere per me che così tante persone lo facciano, quindi aspetterò un po 'per altre risposte.

+0

Puoi esporre un esempio delle "molte funzioni" di cui stai parlando? – Mat

+0

@Mat: ad esempio, http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html (nella sezione commenti utente, cerca "CREATE FUNCTION db.fnfullname" - legge la riga da db per un ID passato e restituisce il valore in base al risultato di select). – a1ex07

+0

"... commenti utente ..." ... Qualche funzione mysql reale che hai in mente? – Mat

risposta

14

Dal MySQL 5.0 Riferimento:

La valutazione del carattere di una routine si basa sulla “onestà” del creatore: MySQL non controlla che una routine dichiarata deterministico è privo di dichiarazioni che producono non deterministico risultati. Tuttavia, la dichiarazione errata di una routine potrebbe influire sui risultati o influire sulle prestazioni. La dichiarazione di una routine non deterministica come DETERMINISTIC potrebbe portare a risultati imprevisti provocando l'errato utilizzo delle opzioni del piano di esecuzione. Dichiarare una routine deterministica come NONDETERMINISTIC potrebbe ridurre le prestazioni causando l'utilizzo di ottimizzazioni disponibili. Prima di MySQL 5.0.44, la caratteristica DETERMINISTIC è accettata, ma non utilizzata dall'ottimizzatore.

Quindi il gioco è fatto, è possibile contrassegnare una routine memorizzato come DETERMINISTIC anche se non lo è, ma potrebbe portare a risultati imprevisti o problemi di prestazioni.

+3

Quindi potremmo avere sempre il 50% di possibilità di scegliere quello sbagliato? Grande. lol Il tuo commento mi ha aiutato a capirlo un po 'di più. – Cesar

+0

In un "modello di serie nidificato" es. http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ Sto usando le routine per inserire ed eliminare i nodi. 1) Possiamo considerare che l'aggiornamento di tutti i limiti dei nodi (aggiungendo 2 ai limiti effettivi) a destra (dopo) il punto di inserimento (il nodo selezionato come riferimento) è DETERMINISTICO? 2) Quindi distruggendo anche un nodo? 3) Spostare un nodo a sinistra della sua posizione attuale? 4) Spostare un nodo a destra della sua posizione attuale? – llange

+0

Perché è una funzionalità? Compilazione forse più veloce se una funzione è veramente deterministica come '3 + x = output'? –

2

Non ti manca nulla. Questa funzione non è deterministica. Dichiararlo deterministico non causerà la fusione del database ma potrebbe influire sulle prestazioni. From the MySQL site: "La dichiarazione di una routine non deterministica come DETERMINISTIC potrebbe portare a risultati imprevisti causando l'ottimizzazione delle scelte del piano di esecuzione non corrette." Ma MySQL non applica o verifica se la tua routine deterministica dichiarata è effettivamente deterministica --- MySQL si fida che tu sappia cosa stai facendo.

+1

Questa routine è deterministica perché se si esegue questa routine su due database identici, i risultati saranno sempre identici. – bikeman868

8

I risultati DETERMINISTIC non si riferiscono a set di risultati diversi restituiti in momenti diversi (a seconda di quali dati sono stati aggiunti nel frattempo). Inoltre è un riferimento ai set di risultati su macchine diverse che utilizzano gli stessi dati. Se, ad esempio, si hanno 2 macchine che eseguono una funzione che include uuid() o variabili del server di riferimento, queste dovrebbero essere considerate NON DETERMINISTICHE. Ciò è utile ad esempio nella replica perché le chiamate alle funzioni sono memorizzate nel log binario (master) e quindi eseguite anche dallo slave. Per dettagli ed esempi vedere http://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html

L'uso di DETERMINISTIC è quindi (99% delle volte) corretto, non da considerare come abuso.

+0

Da mysql: "Una routine è considerata" deterministica "se produce sempre lo stesso risultato per gli stessi parametri di input e" non deterministico "in caso contrario." Anche le definizioni di "funzione deterministica" di altre fonti hanno "restituisce sempre lo stesso risultato per gli stessi parametri". L'utilizzo di un certo DML (almeno SELECT) è un'operazione perfettamente valida all'interno del corpo della funzione. Se dici che non si riferisce a diversi set di risultati, allora tutte le definizioni sono sbagliate poiché "sempre" implica tutte le possibili affermazioni valide all'interno del corpo della funzione. – a1ex07

+0

"produce lo stesso risultato" significa che produce lo stesso risultato nel database. Non significa restituire lo stesso set di risultati. Perché MySQL dovrebbe preoccuparsi se il set di risultati fosse diverso ogni volta o no? Tuttavia, si preoccupa se i dati memorizzati risultanti sono diversi - vedi la mia risposta per maggiori dettagli. – bikeman868

+0

Apprezzo le risposte di Jon Gilbert e bikeman868 ... Vorrei che ci fosse qualche fonte ufficiale che li avrebbe supportati. [Questa risposta dba.stackexchange.com] (https://dba.stackexchange.com/questions/4079/mysql-determinative-procedures/4080#4080) da parte di qualcuno con 23k rep dà la risposta opposta. –

0

Deterministico è importante se la replica è attivata o può essere utilizzata un giorno. Una chiamata di funzione non deterministica che causa una modifica di riga (aggiornamento o inserimento), per esempio, dovrà essere replicata utilizzando binario (basato su righe) dove una funzione deterministica può essere replicata in base all'istruzione. Questo diventa interessante quando si guardano i vostri esempi SQL sopra, quali accadrà lo stesso (dare lo stesso risultato) quando replicati usando statement based, e che dovrebbero essere replicati usando il risultato ottenuto nel master (basato su righe). Se le istruzioni vengono eseguite con il blocco appropriato e possono essere garantite per essere eseguite nello stesso ordine sullo slave, sono effettivamente deterministiche. Se l'ordine di blocco/istruzione utilizzato dallo slave (nessuna concomitanza, elaborazione seriale di istruzioni nell'ordine in cui sono avviati) significa che la risposta può essere diversa, quindi la funzione deve essere non deterministica.

3

Penso che la tua routine sia deterministica. La documentazione non è molto chiara e questo ha portato molte persone a essere molto confuse su questo problema, che in realtà è più sulla replica che su qualsiasi altra cosa.

Considerare una situazione in cui è stata impostata la replica tra due database. Il database master tiene un registro di tutte le routine memorizzate che sono state eseguite, inclusi i loro parametri di input, e invia questo registro allo slave. Lo slave esegue le stesse routine memorizzate nello stesso ordine con gli stessi parametri di input. Il database slave ora contiene dati identici nel database principale? Se le routine memorizzate creano GUID e li memorizzano nel database, no, i database master e slave saranno diversi e la replica verrà interrotta.

Lo scopo principale del flag DETERMINISTIC è di dire a MySQL se includere le chiamate a questa stored procedure nel log di replica comporterà delle differenze tra il database master e gli slave replicati e quindi non è sicuro.

Quando si decide se il flag DETERMINISTIC è appropriato per una stored routine, pensarlo in questo modo: Se inizio con due database identici e eseguo la mia routine su entrambi i database con gli stessi parametri di input, i miei database saranno ancora identici? Se sono così, la mia routine è deterministica.

Se dichiarate che la vostra routine è deterministica quando non lo è, allora le repliche del vostro database principale potrebbero non essere identiche all'originale perché MySQL aggiungerà solo la chiamata di procedura al log di replica e l'esecuzione della procedura sullo slave non non produce risultati identici.

Se la routine non è deterministica, MySQL deve includere le righe interessate nel registro di replica. Se dichiari la tua routine come non deterministica quando non lo è, ciò non interromperà nulla, ma il log di replica conterrà tutte le righe interessate quando sarebbe sufficiente la chiamata alla procedura e questo potrebbe influire sulle prestazioni.

Problemi correlati