web-dev-qa-db-fra.com

Fonction déterministe dans mysql

J'ai été confondu avec un concept apparemment simple. Mysql définit la fonction déterministe comme une fonction 

produit toujours le même résultat pour les mêmes paramètres d'entrée

Donc, dans ma compréhension, les fonctions comme

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;

ne sont pas déterministes (il n'y a aucune garantie qu'il n'y ait pas de suppression/mise à jour/insertion entre 2 appels à la fonction). Dans le même temps, j’ai vu de nombreuses fonctions qui font à peu près la même chose, c’est-à-dire une valeur de retour basée sur le résultat des requêtes, et déclarée comme étant DETERMINISTIC. On dirait que je manque quelque chose de très fondamental.

Quelqu'un pourrait-il clarifier cette question? 

Merci.

Mise à jour Merci à ceux qui ont répondu (+1); jusqu'à présent, il semble qu'il y ait une utilisation généralisée du mot clé DETERMINISTIC. Il est encore difficile de croire pour moi que tant de gens le fassent, alors je vais attendre un peu pour d'autres réponses. 

27
a1ex07

De la référence MySQL 5.0:

L’évaluation de la nature d’une routine repose sur «l’honnêteté» du créateur: MySQL ne vérifie pas qu’une routine déclarée DETERMINISTIC est dépourvue d’énoncés produisant des résultats non déterministes. Cependant, une déclaration erronée d'une routine peut affecter les résultats ou les performances. Déclarer une routine non déterministe comme DETERMINISTIC peut entraîner des résultats inattendus en obligeant l'optimiseur à faire des choix de plan d'exécution incorrects. Déclarer une routine déterministe comme NONDETERMINISTIC peut diminuer les performances en empêchant l'utilisation des optimisations disponibles. Avant MySQL 5.0.44, la caractéristique DETERMINISTIC est acceptée, mais n’est pas utilisée par l’optimiseur.

Donc, voilà, vous pouvez marquer une routine stockée avec DETERMINISTIC même si ce n'est pas le cas, mais cela pourrait entraîner des résultats inattendus ou des problèmes de performances.

14
Xint0

Les résultats DETERMINISTIC ne font pas référence à différents ensembles de résultats renvoyés à des moments différents (en fonction des données ajoutées entre-temps). De plus, il s'agit d'une référence aux jeux de résultats sur différentes machines utilisant les mêmes données. Si, par exemple, 2 machines exécutent une fonction incluant uuid () ou référençant des variables de serveur, celles-ci doivent être considérées comme NON DETERMINISTES. Ceci est utile par exemple dans la réplication car les appels de fonction sont stockés dans le journal binaire (maître) puis exécutés par l'esclave. Pour plus de détails et des exemples, voir http://dev.mysql.com/doc/refman/5.0/fr/stored-programs-logging.html

L'utilisation de DETERMINISTIC est donc correcte (99% du temps) et ne doit pas être considérée comme une utilisation abusive.

11
Jon Gilbert

Je pense que votre routine est déterministe. La documentation n'est pas très claire et cela a amené beaucoup de gens à être très déconcertés par ce problème, qui concerne en réalité plus la réplication qu'autre chose.

Envisagez une situation dans laquelle la réplication est configurée entre deux bases de données. La base de données master conserve un journal de toutes les routines stockées exécutées, y compris leurs paramètres d'entrée, et envoie ce journal à l'esclave. L'esclave exécute les mêmes routines stockées dans le même ordre avec les mêmes paramètres d'entrée. Est-ce que la base de données esclave contient maintenant des données identiques à la base de données maître? Si les routines stockées créent des GUID et les stockent dans la base de données, non, les bases de données maître et esclave seront différentes et la réplication sera interrompue.

Le but principal de l'indicateur DETERMINISTIC est d'indiquer à MySQL si l'inclusion d'appels à cette routine stockée dans le journal de réplication entraînera des différences entre la base de données master et les esclaves répliqués, et constitue donc un danger.

Lorsque vous décidez si le drapeau DETERMINISTIC est approprié pour une routine stockée, pensez-le comme suit: Si je commence avec deux bases de données identiques et que j'exécute ma routine sur les deux bases de données avec les mêmes paramètres d'entrée, mes bases de données seront-elles toujours identiques? S'ils le sont, ma routine est déterministe.

Si vous déclarez que votre routine est déterministe lorsqu'elle ne l'est pas, les répliques de votre base de données principale risquent de ne pas être identiques à l'original, car MySQL ne fera qu'ajouter l'appel de procédure au journal de réplication et l'exécution de la procédure sur l'esclave ne produit pas des résultats identiques. .

Si votre routine n'est pas déterministe, MySQL doit alors inclure les lignes concernées dans le journal de réplication. Si vous déclarez votre routine non déterministe alors que ce n'est pas le cas, le journal de réplication contiendra toutes les lignes affectées, alors que l'appel de procédure aurait suffi, ce qui pourrait avoir un impact sur les performances.

6
bikeman868

Vous ne manquez rien. Cette fonction est non déterministe. Si vous le déclarez déterministe, votre base de données ne fondra pas, mais cela pourrait affecter les performances. Sur le site MySQL : "Déclarer une routine non déterministe comme DETERMINISTIC peut conduire à des résultats inattendus en obligeant l'optimiseur à faire des choix de plan d'exécution incorrects." Mais MySQL n’impose ni ne vérifie si votre routine déterministe déclarée est réellement déterministe - MySQL dit que vous savez ce que vous faites.

2
John Watson

Le déterminisme est important si la réplication est activée ou peut l’utiliser un jour. Un appel de fonction non déterministe qui provoque un changement de ligne (update ou insert), par exemple, devra être répliqué à l'aide de binary (basé sur les lignes), où une fonction déterministe peut être répliquée à l'aide de l'instruction . Cela devient intéressant à regarder. vos exemples SQL ci-dessus, lesquels se produiront de la même manière (donneront le même résultat) lorsqu’ils sont répliqués à l’aide d’instructions, et lesquels doivent être répliqués à l’aide du résultat obtenu dans le maître (basé sur les lignes). Si les instructions sont exécutées avec le verrouillage approprié et peuvent être exécutées dans le même ordre sur l'esclave, elles sont en effet déterministes. Si l'ordre de verrouillage/instruction utilisé par l'esclave (pas de simultanéité, traitement en série des instructions dans l'ordre de leur lancement) signifie que la réponse peut être différente, la fonction doit alors être non déterministe.

0
dooku