Подтвердить что ты не робот

Детерминированная функция в mysql

Я запутался в простой концепции. Mysql определяет детерминированную функцию как функцию, которая

всегда производит тот же результат для тех же входных параметров

Итак, в моем понимании, такие функции, как

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;

не являются детерминированными (нет гарантии, что удаление/обновление/вставка не происходит между двумя вызовами функции). В то же время я видел много функций, которые почти одинаковы, т.е. Возвращают значение на основе результатов запросов и объявляются как DETERMINISTIC. Похоже, я пропускаю что-то очень простое.

Может ли кто-нибудь прояснить эту проблему?

Спасибо.

Обновление Спасибо за тех, кто ответил (+1); пока это похоже на распространенное злоупотребление ключевыми словами DETERMINISTIC. Мне все еще трудно поверить, что так много людей делают это, поэтому я буду немного ждать других ответов.

4b9b3361

Ответ 1

Из справки MySQL 5.0:

Оценка характера подпрограммы основана на "честности" создателя: MySQL не проверяет, что в обычной декларации DETERMINISTIC нет инструкций, которые производят недетерминированные результаты. Однако неправильное использование процедуры может повлиять на результаты или повлиять на производительность. Объявление недетерминированной процедуры как DETERMINISTIC может привести к неожиданным результатам, заставив оптимизатора сделать неправильные варианты плана выполнения. Объявление детерминированной подпрограммы как НЕДЕТЕРМИНИСТИЧЕСКОЙ может привести к снижению производительности за счет того, что доступная оптимизация не будет использоваться. До MySQL 5.0.44 признак DETERMINISTIC принимается, но не используется оптимизатором.

Итак, у вас есть это, вы можете пометить хранимую процедуру как DETERMINISTIC, даже если это не так, но это может привести к неожиданным результатам или проблемам с производительностью.

Ответ 2

Результаты DETERMINISTIC не относятся к разным наборам результатов, возвращаемым в разное время (в зависимости от того, какие данные были добавлены в среднем времени). Более того, это ссылки на результирующие наборы на разных машинах с использованием одних и тех же данных. Если, например, у вас есть 2 машины, которые запускают функцию, включая uuid() или ссылающиеся на переменные сервера, тогда они должны рассматриваться как НЕ ДЕТЕРМИНИСТИЧЕСКИЕ. Это полезно, например, для репликации, поскольку вызовы функций хранятся в двоичном журнале (мастер), а затем выполняются ведомым. Подробнее и примеры см. http://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html

Использование DETERMINISTIC, таким образом, (99% времени) правильное, не считающееся неправильным использованием.

Ответ 3

Я думаю, что ваша рутина детерминирована. Документация не очень ясна, и это привело к тому, что многие люди были очень смущены этой проблемой, что на самом деле больше связано с репликацией, чем с чем-либо еще.

Рассмотрим ситуацию, когда у вас установлена ​​репликация между двумя базами данных. Основная база данных хранит журнал всех сохраненных процедур, которые были выполнены, включая их входные параметры, и отправляет этот журнал в подчиненный. Ведомое устройство выполняет те же хранимые процедуры в том же порядке, что и те же входные параметры. Будет ли ведомая база данных теперь содержать идентичные данные в основной базе данных? Если хранимые процедуры создают GUID и сохраняют их в базе данных, тогда нет, основная и подчиненная базы данных будут разными, и репликация будет нарушена.

Основная цель флага DETERMINISTIC заключается в том, чтобы сообщить MySQL о том, будет ли включение вызовов этой хранимой процедуры в журнал репликации привести к различиям между основной базой данных и реплицированными ведомыми устройствами и, следовательно, небезопасно.

При определении того, подходит ли флаг DETERMINISTIC для хранимой процедуры, подумайте об этом следующим образом: если я начну с двух идентичных баз данных, и я выполняю свою подпрограмму в обеих базах данных с одинаковыми входными параметрами, мои базы данных будут идентичны? Если они тогда, моя рутина детерминирована.

Если вы заявляете, что ваша подпрограмма является детерминированной, когда ее нет, то реплики вашей основной базы данных могут быть не идентичны оригиналу, потому что MySQL будет только добавлять вызов процедуры в журнал репликации, а выполнение процедуры на ведомом не дают идентичные результаты.

Если ваша подпрограмма не является детерминированной, тогда MySQL должен включать в нее затронутые строки в журнале репликации. Если вы объявляете свою подпрограмму как недетерминированную, если это не так, это ничего не сломает, но журнал репликации будет содержать все затронутые строки, когда просто вызов процедуры был бы достаточно, и это может повлиять на производительность.

Ответ 4

Вы ничего не пропустили. Эта функция недетерминирована. Объявление детерминированного объявления не приведет к таянию базы данных, но это может повлиять на производительность. Из сайта MySQL: "Объявление недетерминированной процедуры как DETERMINISTIC может привести к неожиданным результатам, заставив оптимизатора сделать неправильные варианты плана выполнения". Но MySQL не применяет или не проверяет, действительно ли ваша заявленная детерминированная процедура фактически детерминирована. MySQL доверяет вам, что вы знаете, что вы делаете.

Ответ 5

Детерминированность важна, если вы включили репликацию или можете использовать ее в один прекрасный день. Недетерминированный вызов функции, который вызывает изменение строки (обновление или вставку), например, должен быть реплицирован с использованием двоичного (основанного на строках), где в качестве детерминированной функции может быть реплицирован оператор на основе. Это становится интересным при просмотре приведенных выше примеров SQL, какие из них будут совпадать (дать тот же результат) при репликации с использованием оператора на основе и который должен быть реплицирован с использованием результата, полученного в master (на основе строки). Если операторы выполняются с соответствующей блокировкой и могут быть гарантированы выполнение в том же порядке в Slave, то они действительно детерминированы. Если порядок блокировки/оператора, который использует ведомый (no concurrency, последовательная обработка операторов в том порядке, в котором они запущены) означает, что ответ может быть другим, тогда функция должна быть недетерминированной.