MySQL Ошибка 1418 (HY000): This function has none of DETERMINISTIC (binlog restriction)
Механизм безопасности бинарного логирования хранимых функций
Когда в СУБД MySQL включено бинарное логирование (параметр log_bin = ON, обязательный для репликации и инкрементных бэкапов), сервер осуществляет строгий контроль безопасности пользовательских хранимых функций (Stored Functions) и триггеров. Если функция объявлена без явного указания характеристик детерминизма или модификации данных, либо если пользователь без привилегии SUPER пытается создать недетерминированную функцию, сервер блокирует выполнение DDL-запроса CREATE FUNCTION с системной ошибкой:
«ERROR 1418 (HY000): 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)»
Бизнес-риски
Сбой накатывания миграций БД и развертывания релизов приложений, отказ импорта дампов баз данных (включающих процедуры и триггеры), риск расхождения данных (Data Drift) между Master и Slave серверами.
Классификация характеристик хранимых функций в MySQL
| Характеристика функции | Поведение и влияние на данные | Безопасность для репликации |
|---|---|---|
DETERMINISTIC | При одинаковых входных аргументах функция ВСЕГДА возвращает строго одинаковый результат. | Абсолютно безопасно. |
NOT DETERMINISTIC | Результат зависит от внешних факторов (вызовы NOW(), UUID(), RAND(), чтение меняющихся таблиц). | Опасно (может привести к разным данным на реплике). |
NO SQL | Функция не содержит SQL-инструкций чтения или записи. | Абсолютно безопасно. |
READS SQL DATA | Функция только читает данные (SELECT), но не модифицирует их. | Безопасно при детерминированном чтении. |
MODIFIES SQL DATA | Функция выполняет операции записи (INSERT/UPDATE/DELETE). | Требует строгого аудита детерминизма. |
Регламент исправления хранимых функций и настройки доверия
Сценарий 1: Корректное добавление атрибутов детерминизма в тело функции
Наиболее правильный и архитектурно чистый способ — явно описать поведение функции:
-- ПРИМЕР: Создание детерминированной функции (всегда один результат для одинаковых входных данных):
DELIMITER $$
CREATE FUNCTION `calculate_vat`(price DECIMAL(10,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
NO SQL
BEGIN
RETURN price * 0.20;
END$$
DELIMITER ;Если функция только считывает данные из таблиц:
DELIMITER $$
CREATE FUNCTION `get_user_status`(user_id INT)
RETURNS VARCHAR(50)
READS SQL DATA
BEGIN
DECLARE user_status VARCHAR(50);
SELECT status INTO user_status FROM users WHERE id = user_id LIMIT 1;
RETURN user_status;
END$$
DELIMITER ;Сценарий 2: Включение системного параметра log_bin_trust_function_creators
Если вы разворачиваете стороннюю CMS или унаследованный дамп, где нет возможности вручную переписать сотни функций:
# 1. Включение доверия к создателям функций на лету в консоли MySQL:
SET GLOBAL log_bin_trust_function_creators = 1;
# 2. Персистентное сохранение в my.cnf:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
log_bin_trust_function_creators = 1
# 3. Перезапуск службы не требуется (параметр динамический).Сценарий 3: Выдача необходимых системных привилегий пользователю БД
В MySQL 8.0 создание функций требует привилегии CREATE ROUTINE, а при log_bin_trust_function_creators = 0 также привилегий администратора:
GRANT CREATE ROUTINE, ALTER ROUTINE, EXECUTE ON my_database.* TO 'developer'@'%';
-- Для MySQL 8.0 (если доверие выключено):
GRANT SYSTEM_VARIABLES_ADMIN, REPLICATION_APPLIER ON *.* TO 'developer'@'%';
FLUSH PRIVILEGES;Типовые ошибки администраторов
- Пометка недетерминированной функции как DETERMINISTIC: Если функция использует вызов
UUID()илиNOW()и помечена какDETERMINISTIC, при репликации в форматеSTATEMENTна реплику запишутся совершенно другие значения, чем на мастере. - Импорт дампа утилитой mysqldump без флага --routines: Приводит к потере всех хранимых процедур и функций при миграции на новый сервер.
Специалисты ITSTM настроят политики безопасности бинарного логирования и приведут процедуры в соответствие со стандартами репликации.
Частые вопросы (FAQ)
Почему ошибка 1418 не возникает на локальном сервере разработки?
На локальных серверах разработки бинарное логирование (log_bin) по умолчанию часто отключено, поэтому проверка детерминизма не активируется.
Влияет ли log_bin_trust_function_creators на безопасность?
Включение этого параметра позволяет любому пользователю с правами CREATE ROUTINE создавать функции, которые могут выполнять непреднамеренные модификации данных или замедлять репликацию.
Сбрасывается ли log_bin_trust_function_creators после перезапуска MySQL?
Если параметр был включен только командой SET GLOBAL без внесения в my.cnf, после перезапуска службы он вернется в значение 0 (OFF).
Как посмотреть список всех созданных функций в базе данных?
Выполните запрос: SELECT routine_name, routine_type, is_deterministic, sql_data_access FROM information_schema.routines WHERE routine_schema = 'my_database';