Fonction déterministe en mysql

je me suis confondu avec un concept apparemment simple. Mysql définit la fonction déterministe comme une fonction qui

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

D'après ce que j'ai compris, 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 que delete/update/insert n'arrive pas entre 2 appels à la fonction). En même temps, j'ai vu beaucoup de fonctions qui font à peu près la même chose, i.e. retourner la valeur basée sur le résultat des requêtes, et déclarée comme DETERMINISTIC. Il semble que je manque quelque chose de très basique.

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 est une généralisation abusive de l' DETERMINISTIC mot clé. Il est toujours difficile de croire pour moi que tant de gens le font, donc je vais attendre un peu pour d'autres réponses.

27
demandé sur a1ex07 2011-10-30 21:27:14

5 réponses

à Partir de la base de données MySQL 5.0 Reference:

L'appréciation de la nature d'une routine est basée sur "l'honnêteté" du créateur: MySQL ne vérifie pas qu'une routine déclarée déterministe est libre de déclarations qui produisent des résultats non déterministes. Toutefois, une mauvaise déclaration d'une routine peut avoir une incidence sur les résultats ou le rendement. Déclarer une routine non déterministe comme déterministe pourrait conduire à des résultats inattendus en amenant l'optimiseur à faire des choix de plan d'exécution incorrects. Déclarer une routine déterministe comme non déterministe pourrait diminuer la performance en faisant en sorte que les optimisations disponibles ne soient pas utilisées. Avant MySQL 5.0.44, la caractéristique déterministe est acceptée, mais pas utilisée par l'optimiseur.

Donc là vous l'avez, vous pouvez marquer un stockées routine DETERMINISTIC même si ce n'est pas le cas, mais cela peut conduire à des résultats inattendus ou à des problèmes de performance.

14
répondu Xint0 2011-10-30 17:50:03

les résultats déterministes ne font pas référence à des ensembles de résultats différents retournés à des moments différents (selon quelles données ont été ajoutées dans le temps moyen). De plus, il s'agit d'une référence aux ensembles de résultats sur différentes machines utilisant les mêmes données. Si, par exemple, vous avez 2 machines qui exécutent une fonction incluant uuid() ou des variables de serveur de référence, alors celles-ci devraient être considérées comme non déterministes. C'est utile par exemple dans la réplication parce que les appels de fonction sont stockés dans le binaire log (master) et ensuite aussi exécuté par l'esclave. Pour plus de détails et des exemples, voir http://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html

L'utilisation de DÉTERMINISTIC est donc (99% du temps) correcte, à ne pas considérer comme un abus.

8
répondu Jon Gilbert 2012-06-18 18:45:28

je pense que votre routine est déterministe. La documentation n'est pas très claire et cela a conduit beaucoup de gens à être très confus sur cette question, qui est en fait plus sur la réplication que toute autre chose.

envisagez une situation où vous avez la réplication établie entre deux bases de données. La base de données principale conserve un journal de toutes les routines stockées qui ont été exécutées, y compris leurs paramètres d'entrée, et envoie ce journal à l'esclave. L'esclave exécute le même stock routines dans le même ordre et avec les mêmes paramètres d'entrée. La base de données des esclaves contiendra-t-elle maintenant des données identiques à celles de la base de données principale? Si les routines stockées créent des GUIDs et les stockent dans la base de données alors non, les bases de données maître et esclave seront différentes et la réplication sera cassée.

le but principal du drapeau déterministe est de dire à MySQL si l'inclusion des appels à cette routine stockée dans le journal de réplication entraînera des différences entre la base de données principale et les esclaves répliqués, et est donc dangereux.

au moment de décider si le drapeau déterministe est approprié pour une routine stockée, pensez-y comme ceci: 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? Si ils sont alors ma routine est déterministe.

si vous déclarez que votre routine est déterministe alors qu'elle ne l'est pas, alors les répliques de votre base de données principale pourraient ne pas être identiques à L'original parce que MySQL ajoutera seulement l'appel de procédure au Journal de réplication, et l'exécution de la procédure sur l'esclave ne produit pas de résultats identiques.

si votre routine n'est pas déterministe, MySQL doit inclure les lignes affectées dans le journal de réplication à la place. Si vous déclarez que votre routine n'est pas déterministe alors que ce n'est pas le cas, cela ne cassera rien, mais le journal de réplication contiendra toutes les lignes affectées alors que juste l'appel de procédure aurait été assez et cela pourrait avoir un impact sur la performance.

4
répondu bikeman868 2017-05-31 00:48:38

vous ne ratez rien. Cette fonction est non-déterministe. Le déclarer déterministe ne fera pas fondre votre base de données, mais il pourrait affecter les performances. Depuis le site de MySQL: "déclarer une routine non déterministe comme déterministe pourrait conduire à des résultats inattendus en amenant l'optimiseur à faire des choix de plan d'exécution incorrects."Mais MySQL ne fait pas appliquer ou vérifier si votre routine déterministe déclarée est réellement déterministe - - - MySQL croit que vous savez ce que vous êtes en train de faire.

2
répondu John Watson 2011-10-30 17:50:12

déterministe est important si vous avez la réplication allumé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é en utilisant le binaire (basé sur la ligne) où comme une fonction déterministe peut être répliqué basé sur la déclaration. Ceci devient intéressant lorsque vous regardez vos exemples SQL ci-dessus, lesquels se produiront de la même manière (donner le même résultat) lorsqu'ils seront répliqués en utilisant une instruction basée, et qui devraient être répliqués en utilisant le résultat obtenu dans le master (en lignes). Si les instructions sont exécutées avec le verrouillage approprié et peuvent être garanties d'exécuter dans le même ordre sur L'esclave, alors elles sont en effet déterministes. Si l'ordre de verrouillage / instruction que L'esclave utilise (pas de simultanéité, traitement en série des instructions dans l'ordre où elles sont lancées) signifie que la réponse peut être différente, alors la fonction doit être non déterministe.

0
répondu dooku 2015-08-21 05:34:22