Детерминированная функция в MySQL - PullRequest
28 голосов
/ 30 октября 2011

Я запутался с на первый взгляд простой концепцией.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 ]

14 голосов
/ 30 октября 2011

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

Оценка природы подпрограммы основана на «честности» создателя: MySQL не проверяет, что подпрограмма, объявленная как DETERMINISTIC, не содержит операторов, которые дают недетерминированные результаты. Однако неправильное указание процедуры может повлиять на результаты или производительность. Объявление недетерминированной подпрограммы как DETERMINISTIC может привести к неожиданным результатам, заставляя оптимизатор сделать неправильный выбор плана выполнения. Объявление детерминированной подпрограммы как NONDETERMINISTIC может снизить производительность, из-за чего доступные оптимизации не будут использоваться. До MySQL 5.0.44 признак DETERMINISTIC принимался, но не использовался оптимизатором.

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

12 голосов
/ 18 июня 2012

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

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

8 голосов
/ 16 апреля 2016

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

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

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

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

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

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

2 голосов
/ 30 октября 2011

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

0 голосов
/ 21 августа 2015

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

...