Динамический SQL в хранимых подпрограммах MySQL

13

В соответствии с ограничениями на хранимые подпрограммы и триггеры , нельзя использовать динамический sql (ограничение снято для хранимых процедур в версии 5.0.13 и более поздних). Почему это ограничение на месте? И зачем поднимать его для процедур, а не для функций или триггеров?

Дерек Дауни
источник

Ответы:

8

Просто слушая вопрос, я думаю о двух аспектах:

АСПЕКТ № 1: Функции должны быть ДЕТЕРМИНИСТИЧЕСКИМИ

Если это так, это означает, что функция должна последовательно представлять одни и те же возвращаемые данные для заданного набора параметров, НИКАКОГО МАТЕРИИ, КОГДА ВЫ ВЫЗЫВАЕТЕ ФУНКЦИЮ.

Теперь представьте себе функцию, которая выдает другой ответ из-за сбора данных в разное время дня на основе статического SQL в функции. В некотором смысле это все еще можно считать ДЕТЕРМИНИСТИЧЕСКИМ, если вы каждый раз запрашиваете один и тот же набор таблиц и столбцов, учитывая один и тот же набор параметров.

Что если бы вы могли изменить базовые таблицы функции через динамический SQL? Вы нарушаете определение ДЕТЕРМИНИСТИЧЕСКОЙ функции.

Обратите внимание, что MySQL добавил эту опцию в /etc/my.cnf

log-bin-trust-function-creators

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

АСПЕКТ № 2: Триггеры должны иметь возможность отката

  • Можете ли вы представить триггер с тем же поведением, что и функцию, а затем ввести динамический SQL в смесь?
  • Можете ли вы представить себе попытку применить MVCC (Multiversion Concurrecy Control) к Dynamic SQL после применения MVCC к базовой таблице, для которой предназначался триггер?

По сути, у вас есть данные, которые растут квадратично (даже экспоненциально) только в одной только MVCC. Процесс управления откатом SQL с помощью триггеров, которые могут быть недетерминированными, был бы, по меньшей мере, ужасно сложным.

В свете этих двух аспектов, я уверен, что разработчики MySQL подумали об этих вещах и быстро отклонили их, введя ограничения.

Итак, зачем снимать ограничение на процедуры? Проще говоря, это не касается ДЕТЕРМИНИСТИЧЕСКИХ свойств или отката.

RolandoMySQLDBA
источник
3
Не может быть настолько "безбожно сложным", если другие СУБД могут очень хорошо поддерживать MVCC и динамический SQL в триггерах.
a_horse_with_no_name
1
На самом деле, @a_horse_with_no_name, вы правы. Для Oracle и PostgreSQL был написан безбожный комплекс. +1 за ваш комментарий. MySQL имеет недостаток в работе с несколькими механизмами хранения, поэтому откат и детерминизм могут потребовать перекрытия операций механизма хранения. Это немного страшно. Может быть, у кого-то хватит смелости толкнуть «безбожный комплекс» в InnoDB в полном объеме. Еще более желательно было бы создать реализацию триггера, специфичную для механизма хранения, таким образом, чтобы она не позволяла смешивать механизмы хранения в одном и том же запросе.
RolandoMySQLDBA
5

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

Для начала я вижу это:

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

Что заставляет меня думать, что это как-то связано с этим. Он не будет перекомпилировать SQL, даже если он не отслеживает метаданные. Что означает, что это проблема двигателя.

К тому же, когда я читаю этот блок, я думаю о том же (двигатель):

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

В общем, я не совсем уверен, почему они этого не позволяют, но я могу догадаться. Извините, что я не могу помочь вам больше, я открыт, чтобы обсудить это еще немного. Лучше всего надеяться на некоторых активных разработчиков MySQL, как только мы выйдем из приватной бета-версии;)

Jcolebrand
источник
1

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

Помимо этого, вы можете поднять уродливые вопросы о том, что может случиться, если это допустимо.

dba4life
источник