Función determinista en mysql


Me confundí con un concepto aparentemente simple. Mysql define la función determinista como una función que

Siempre produce el mismo resultado para los mismos parámetros de entrada

Así que en mi entendimiento, funciona como

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;

No son deterministas (no hay garantía de que delete/update/insert no ocurra entre 2 llamadas a la función). Al mismo tiempo, vi muchas funciones que hacen más o menos lo mismo, es decir, valor de retorno basado en el resultado de consultas, y declarado como DETERMINISTIC. Parece que me estoy perdiendo algo muy básico.

¿Podría alguien aclarar este asunto?

Gracias.

Actualización Gracias por aquellos que respondieron (+1); hasta ahora parece que hay un uso indebido generalizado de la palabra clave DETERMINISTIC. Todavía me cuesta creer que tanta gente lo haga, así que esperaré un poco por otras respuestas.

Author: a1ex07, 2011-10-30

5 answers

De la referencia de MySQL 5.0:

La evaluación de la naturaleza de una rutina se basa en la "honestidad" del creador: MySQL no comprueba que una rutina declarada DETERMINISTA esté libre de declaraciones que produzcan resultados no deterministas. Sin embargo, la declaración errónea de una rutina puede afectar los resultados o el rendimiento. Declarar una rutina no determinista como DETERMINISTA podría conducir a resultados inesperados al hacer que el optimizador tome decisiones incorrectas sobre el plan de ejecución. Declarando una la rutina determinista como NO determinista podría disminuir el rendimiento al hacer que no se usen las optimizaciones disponibles. Antes de MySQL 5.0.44, la característica DETERMINISTA es aceptada, pero no utilizada por el optimizador.

Así que ahí lo tiene, puede etiquetar una rutina almacenada como DETERMINISTIC incluso si no lo es, pero podría conducir a resultados inesperados o problemas de rendimiento.

 14
Author: Xint0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-30 17:50:03

Los resultados DETERMINÍSTICOS no se refieren a diferentes conjuntos de resultados que se devuelven en diferentes momentos (dependiendo de los datos que se hayan agregado en el tiempo medio). Además, es una referencia a los conjuntos de resultados en diferentes máquinas que utilizan los mismos datos. Si por ejemplo, tiene 2 máquinas que ejecutan una función incluyendo uuid () o haciendo referencia a variables de servidor, entonces estas no deben considerarse DETERMINISTAS. Esto es útil, por ejemplo, en la replicación porque las llamadas a funciones se almacenan en el registro binario (maestro) y luego también ejecutado por el esclavo. Para más detalles y ejemplos, véase http://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html

El uso de DETERMINISTIC es por lo tanto (99% del tiempo) correcto, no debe ser considerado mal uso.

 8
Author: Jon Gilbert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-18 18:45:28

Creo que tu rutina es determinista. La documentación no es muy clara y esto ha llevado a muchas personas a estar muy confundidas sobre este tema, que en realidad se trata más de replicación que de cualquier otra cosa.

Considere una situación en la que tiene configurada la replicación entre dos bases de datos. La base de datos maestra mantiene un registro de todas las rutinas almacenadas que se ejecutaron, incluyendo sus parámetros de entrada, y envía este registro al esclavo. El esclavo ejecuta lo mismo almacenado rutinas en el mismo orden con los mismos parámetros de entrada. ¿La base de datos esclava contendrá ahora datos idénticos a la base de datos maestra? Si las rutinas almacenadas crean GUID y los almacenan en la base de datos, entonces no, las bases de datos maestro y esclavo serán diferentes y la replicación se romperá.

El propósito principal de la bandera DETERMINISTA es decirle a MySQL si incluir llamadas a esta rutina almacenada en el registro de replicación dará lugar a diferencias entre la base de datos maestra y esclavos replicados, y por lo tanto es inseguro.

Al decidir si el indicador DETERMINISTA es apropiado para una rutina almacenada, piénselo de la siguiente manera: Si empiezo con dos bases de datos idénticas y ejecuto mi rutina en ambas bases de datos con los mismos parámetros de entrada, ¿mis bases de datos seguirán siendo idénticas? Si lo son, entonces mi rutina es determinista.

Si declara que su rutina es determinista cuando no lo es, entonces las réplicas de su base de datos principal podrían no ser idénticas a la original porque MySQL solo agregará la llamada al procedimiento al registro de replicación, y ejecutar el procedimiento en el esclavo no produce resultados idénticos.

Si su rutina no es determinista, entonces MySQL debe incluir las filas afectadas en el registro de replicación. Si declara su rutina como no determinista cuando no lo es, esto no romperá nada, pero el registro de replicación contendrá todas las filas afectadas cuando solo la llamada al procedimiento hubiera sido suficiente y esto podría rendimiento de impacto.

 4
Author: bikeman868,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-31 00:48:38

No te estás perdiendo nada. Esta función no es determinista. Declararlo determinista no causará que su base de datos se derrita, pero podría afectar el rendimiento. Del sitio MySQL: "Declarar una rutina no determinista como DETERMINISTA podría conducir a resultados inesperados al hacer que el optimizador tome decisiones incorrectas sobre el plan de ejecución."Pero MySQL no hace cumplir o comprobar si su rutina determinista declarada es realmente determinista - - - MySQL confía en que usted sabe lo que es hacer.

 2
Author: John Watson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-10-30 17:50:12

Deterministic es importante si tiene la replicación activada o puede usarla algún día. Una llamada a una función no determinista que causa un cambio de fila (actualizar o insertar), por ejemplo, tendrá que ser replicada usando binario (basado en filas) donde como una función determinista puede ser replicada basada en sentencias. Esto se vuelve interesante cuando se observan los ejemplos SQL anteriores, cuáles sucederán lo mismo (darán el mismo resultado) cuando se replican usando instrucciones basadas, y cuáles deben replicarse usando el resultado obtenido en el maestro (basado en filas). Si las sentencias se ejecutan con el bloqueo apropiado y se puede garantizar que se ejecuten en el mismo orden en el Esclavo, entonces son de hecho deterministas. Si el orden de bloqueo / sentencia que utiliza el Esclavo (sin concurrencia, procesamiento en serie de sentencias en el orden en que se inician) significa que la respuesta puede ser diferente, entonces la función debe ser no determinista.

 0
Author: dooku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-21 05:34:22