Детерминированная функция в 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;

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

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

спасибо.

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

5 ответов


из ссылки MySQL 5.0:

оценка природы рутины основана на" честности " создателя: MySQL не проверяет, что рутина, объявленная детерминированной, свободна от утверждений, которые производят недетерминированные результаты. Однако неправильное объявление процедуры может повлиять на результаты или производительность. Объявление недетерминированной процедуры детерминированной может привести к неожиданным результатам, заставив оптимизатор сделать неверный выбор плана выполнения. Объявление детерминированной процедуры недетерминированной может снизить производительность, вызвав неиспользование доступных оптимизаций. До MySQL 5.0.44 детерминированная характеристика принимается, но не используется оптимизатором.

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


детерминированные результаты не относятся к различным наборам результатов, возвращаемым в разное время (в зависимости от того, какие данные были добавлены в среднее время). Кроме того, это ссылка на результирующие наборы на разных машинах, использующих одни и те же данные. Если, например, у вас есть 2 машины, которые запускают функцию, включая UUID () или ссылающиеся на переменные сервера, то они должны считаться не детерминированными. Это полезно, например, в репликации, поскольку вызовы функций хранятся в двоичный журнал (master), а затем также выполняется ведомым. Подробнее и примеры см. В разделеhttp://dev.mysql.com/doc/refman/5.0/en/stored-programs-logging.html

использование детерминированного, таким образом, (99% времени) правильно, не следует считать неправильным.


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

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

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

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

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

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


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


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