2011-10-30 42 views
27

Me confundí con un concepto aparentemente simple. MySQL define la función determinista como una función queFunción determinista en mysql

siempre provoca el mismo resultado para el mismo parámetros de entrada

Así que en mi entendimiento, funciones 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 (hay no hay garantía de que eliminar/actualizar/insertar 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, el valor de retorno en función del resultado de las consultas y declarado como DETERMINISTIC. Parece que me estoy perdiendo algo muy básico.

¿Alguien podría aclarar este problema?

Gracias.

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

+0

¿Podría indicar un ejemplo de las "muchas funciones" de las que está hablando? – Mat

+0

@Mat: Por ejemplo, http://dev.mysql.com/doc/refman/5.0/en/create-procedure.html (en la sección de comentarios del usuario, busque "CREAR FUNCIÓN db.nombrefnombre" - lee la fila desde db para una identificación aprobada y devuelve un valor basado en el resultado de la selección). – a1ex07

+0

"... comentarios de usuario ..." ... ¿Alguna función real de MySQL que tenga en mente? – Mat

Respuesta

14

Desde el MySQL 5.0 Reference:

Evaluación de la naturaleza de una rutina se basa en la “honestidad” del creador: MySQL no comprueba que una rutina declaró DETERMINISTIC está libre de los estados que producen no determinista resultados. Sin embargo, una descripción errónea de una rutina puede afectar los resultados o afectar el rendimiento. Declarar una rutina no determinista como DETERMINISTIC puede generar resultados inesperados al hacer que el optimizador tome decisiones de plan de ejecución incorrectas. Declarar una rutina determinista como NONDETERMINISTIC podría disminuir el rendimiento al hacer que las optimizaciones disponibles no se utilicen. Antes de MySQL 5.0.44, la característica DETERMINISTIC es aceptada, pero no utilizada por el optimizador.

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

+3

Entonces, ¿podríamos tener siempre un 50% de posibilidades de elegir el equivocado? Estupendo. jaja. Tu comentario me ayudó a entenderlo un poco más. – Cesar

+0

En un "modelo de conjunto anidado", por ejemplo. http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ Estoy usando rutinas para insertar y eliminar nodos. 1) ¿Podemos considerar que actualizar todos los límites de los nodos (agregando 2 a los límites reales) a la derecha (después) del punto de inserción (nodo seleccionado como referencia) es DETERMINISTIC? 2) ¿Por lo tanto, destruir un nodo también? 3) ¿Mover un nodo a la izquierda de su posición real? 4) ¿Mover un nodo a la derecha de su posición actual? – llange

+0

¿Por qué es eso una característica? Tal vez una compilación más rápida si una función es realmente determinista como '3 + x = output'? –

2

No le falta nada. Esta función no es determinista. Declararlo determinista no hará que su base de datos se derrita, pero podría afectar el rendimiento. From the MySQL site: "Declarar una rutina no determinista como DETERMINISTIC puede generar resultados inesperados al hacer que el optimizador realice elecciones incorrectas del plan de ejecución". Pero MySQL no hace cumplir o verifica si su rutina determinista declarada es realmente determinista --- MySQL confía en que sabe lo que está haciendo.

+1

Esta rutina es determinista porque si ejecuta esta rutina en dos bases de datos idénticas, los resultados siempre serán idénticos. – bikeman868

8

DETERMINISTIC resultados no se refiere a los diferentes conjuntos de resultados que se devuelven en momentos diferentes (dependiendo de qué datos se hayan agregado mientras tanto). Además, es una referencia a los conjuntos de resultados en diferentes máquinas que usan los mismos datos. Si, por ejemplo, tiene 2 máquinas que ejecutan una función que incluye uuid() o hace referencia a variables del servidor, entonces éstas deben considerarse NO DETERMINÍSTICAS. 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 las ejecuta el esclavo. Para detalles y ejemplos, vea 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 considerarse un uso incorrecto.

+0

De mysql: 'Una rutina se considera' determinista 'si siempre produce el mismo resultado para los mismos parámetros de entrada, y "no determinista" en caso contrario'. Las definiciones de "función determinística" de otras fuentes también tienen "siempre devuelve el mismo resultado para los mismos parámetros". Usar cierto DML (al menos SELECT) es una operación perfectamente válida dentro del cuerpo de la función. Si dice que no se refiere a diferentes conjuntos de resultados, entonces todas las definiciones son incorrectas ya que 'siempre' implica todas las posibles declaraciones válidas dentro del cuerpo de la función. – a1ex07

+0

"produce el mismo resultado" significa que produce el mismo resultado en la base de datos. No significa que devuelve el mismo conjunto de resultados. ¿Por qué le importaría a MySQL si el conjunto de resultados era diferente cada vez o no? Sin embargo, le importa si los datos almacenados resultantes son diferentes; consulte mi respuesta para obtener más detalles. – bikeman868

+0

Agradezco las respuestas de Jon Gilbert y bikeman868 ... Desearía que hubiera alguna fuente oficial que los respaldara. [Esta respuesta dba.stackexchange.com] (https://dba.stackexchange.com/questions/4079/mysql-deterministic-procedures/4080#4080) por alguien con 23k rep da la respuesta opuesta. –

0

La determinación es importante si tiene la replicación activada o puede usarla un día. Una llamada de función no determinista que causa un cambio de fila (actualización o inserción), por ejemplo, tendrá que ser replicada usando binario (basado en filas) donde, como función determinista, se puede replicar en base a enunciados. Esto se vuelve interesante cuando se analizan los ejemplos de SQL anteriores, cuáles ocurrirán de la misma manera (dar el mismo resultado) cuando se repliquen usando declaraciones y que se deben replicar utilizando el resultado obtenido en el maestro (basado en filas). Si las declaraciones 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/declaración que utiliza el esclavo (sin concurrencia, el procesamiento en serie de las declaraciones en el orden en que se inician) significa que la respuesta puede ser diferente, entonces la función no debe ser determinista.

3

Creo que su 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 cualquier otra cosa.

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

El objetivo principal de la bandera DETERMINISTIC es decirle a MySQL si incluir llamadas a esta rutina almacenada en el registro de replicación dará como resultado diferencias entre la base de datos master y los esclavos replicados, y por lo tanto no es seguro.

Al decidir si el indicador DETERMINISTIC es apropiado para una rutina almacenada, piense de esta 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 ¿seguirán siendo idénticas mis bases de datos? 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 pueden no ser idénticas a las originales porque MySQL solo agregará la llamada de procedimiento al registro de replicación, y ejecutar el procedimiento en el esclavo no produce resultados idénticos.

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

Cuestiones relacionadas