Bases de datos

MySQL

Solución al mensaje de error "This function has none of DETERMINISTIC NO SQL or READS SQL DATA"

Última actualización: 23-03-2024 19:22

Hace algún tiempo por problemas que estuve teniendo con MariaDB en mi computadora y para variar no tenía mayores tiempos libres para buscarles solución a fondo y terminé optando por ir de vuelta a MySQL ya que oficialmente los proyectos en los que estaba involucrado iban con esta base de datos y no con MariaDB.

Me surgió este mensaje de error cuando mi script llegó al punto de creación de funciones y procedimientos en la creación de una base de datos:

Error Code: 1418. This function has none of DETERMINISTIC, NO SQL, or READS SQL DATA in its declaration and binary logging is enabled (you might want to use the less safe log_bin_trust_function_creators variable).

Al buscar de qué estaba hablando encontré que en sus últimas versiones MySQL ya tenía opciones de marcar procedimientos y funciones según su comportamiento respecto a la interacción con la base de datos y respecto a los resultados fijos o variables al recibir los mismos parámetros... Así que me di a la tarea de intentar agregar ese detalle a cada función y procedimiento pero al llegar a la base de datos de un proyecto con demasiados objetos de esos busqué un poco más y encontré una respuesta más pragmática en stackoverflow.com en este enlace: https://stackoverflow.com/a/26015334

La solución encontrada fue ejecutar este comando antes de ejecutar el script para hacer que MySQL no tome en cuenta esas marcas que ya puede manejar:

SET GLOBAL log_bin_trust_function_creators = 1;

Me he tomado la libertad de copiar el texto del enlace que mencioné de stackoverflow y ponerlo en castellano por acá:
(si estoy pecando que me avisen para hacer lo que corresponda)

Fuente original de este texto: https://stackoverflow.com/a/26015334

El mejor enfoque es una mejor comprensión y uso de declaraciones deterministas para funciones almacenadas. MySQL utiliza estas declaraciones para optimizar la replicación y es bueno elegirlas con cuidado para tener una replicación saludable.

DETERMINÍSTICA Una rutina se considera “determinista” si siempre produce el mismo resultado para los mismos parámetros de entrada y NO DETERMINÍSTICA en caso contrario. Esto se usa principalmente con procesamiento de cadenas o matemático, pero no se limita a eso.

NO DETERMINISTA Lo contrario de "DETERMINISTA". "Si no se proporciona DETERMINISTIC ni NOT DETERMINISTIC en la definición de rutina, el valor predeterminado es NOT DETERMINISTIC. Para declarar que una función es determinista, debe especificar DETERMINISTIC explícitamente.". Entonces parece que si no se hace ninguna declaración, MySQL tratará la función como "NO DETERMINISTA". Esta declaración del manual está en contradicción con otra declaración de otra área del manual que dice que: "Cuando crea una función almacenada, debe declarar que es determinista o que no modifica datos. De lo contrario, puede ser inseguro para recuperación o replicación de datos. De forma predeterminada, para que se acepte una declaración CREATE FUNCTION, se debe especificar explícitamente al menos uno de DETERMINISTIC, NO SQL o READS SQL DATA. De lo contrario, se produce un error"

Personalmente recibí un error en MySQL 5.5 si no hay declaración, por lo que siempre pongo al menos una declaración de "DETERMINÍSTICO", "NO DETERMINÍSTICO", "NO SQL" o "LEE DATOS SQL" independientemente de otras declaraciones que pueda tener.

LEE DATOS SQL Esto le dice explícitamente a MySQL que la función SOLO leerá datos de bases de datos, por lo tanto, no contiene instrucciones que modifican datos, pero contiene instrucciones SQL que leen datos (eq SELECT).

MODIFICA DATOS SQL Esto indica que la rutina contiene sentencias que pueden escribir datos (por ejemplo, contiene instrucciones ACTUALIZAR, INSERTAR, ELIMINAR o ALTERAR).

NO SQL Esto indica que la rutina no contiene sentencias SQL.

CONTIENE SQL Esto indica que la rutina contiene instrucciones SQL, pero no contiene declaraciones que lean o escriban datos. Este es el valor predeterminado si ninguna de estas características se proporciona explícitamente. Ejemplos de tales declaraciones son SELECT NOW(), SELECT 10+@b, SET @x = 1 o DO RELEASE_LOCK('abc'), que se ejecutan pero no leen ni escriben datos.

Tenga en cuenta que hay funciones de MySQL que no son seguras deterministas, como: NOW(), UUID(), etc., que probablemente produzcan resultados diferentes en diferentes máquinas, por lo que una función de usuario que contenga dichas instrucciones debe declararse como NO DETERMINISTA . Además, una función que lee datos de un esquema no replicado es claramente NO DETERMINÍSTICA. *

La evaluación de la naturaleza de una rutina se basa en la “honestidad” del creador: MySQL no verifica que una rutina declarada DETERMINISTA esté libre de declaraciones que produzcan resultados no deterministas. Sin embargo, declarar incorrectamente una rutina podría afectar los resultados o afectar el rendimiento. Declarar una rutina no determinista como DETERMINISTA podría generar resultados inesperados al hacer que el optimizador tome decisiones incorrectas en el plan de ejecución. Declarar una rutina determinista como NO DETERMINISTA podría disminuir el rendimiento al provocar que no se utilicen las optimizaciones disponibles.