Вызов хранимой процедуры MySQL из сценария PHP - нет ошибки, но не выполняется?
- ОБНОВЛЕНИЕ В КОНЦЕ
Я следую этому руководству по автоматическому обслуживанию разделов в MySQL, в котором подробно описывается общий метод удаления и добавления разделов таблиц mySQL на основе диапазонов дат.
Идея состоит в том, что вы можете автоматически отбрасывать старые данные таблицы через определенный промежуток времени и создавать новые разделы таблицы для текущих данных по мере необходимости.
Однако, поскольку мой сайт, скорее всего, будет размещен в "общем" пакете провайдера, кажется, что события mySQL будут для меня недоступны.
Итак, я перекрестно использую хранимые процедуры, описанные в первом уроке, с альтернативным методом их вызова с использованием метода, подробно описанного в этом ответе о переполнении стека, с некоторыми изменениями: Сценарий поддержки разделов для Mysql
На моем локальном тестовом компьютере я хочу запустить скрипт PHP как задание CRON от Webmin.
Когда я запускаю хранимые процедуры из Adminer (который имеет схожую функциональность с phpMyAdmin), используя тестовую базу данных mySQL, они выполняются как положено - разделы удаляются, и весь процесс занимает пару минут.
Однако, когда я запускаю свой модифицированный PHP-скрипт из Webmin в качестве задания CRON, кажется, ничего не происходит. Ошибок нет, но скрипт сразу возвращается с "ОК".
Точно так же, когда я запускаю скрипт из оболочки моего компьютера LAMP, он сразу же возвращается с "OK".
Это скрипт PHP:
#!/usr/bin/env php
<?php
$connection = mysqli_connect('localhost', 'my_username', 'my_password', 'employees');
$result = mysqli_query($connection, "CALL perform_partition_maintenance('employees', 'titles', 3, 216, 5)") or die('Query fail: ' . mysqli_error($connection));
if ($result)
echo "OK";
else
echo "FAIL";
mysqli_close($connection);
Буду очень признателен за любые предложения о том, где я могу пойти не так.
ОБНОВИТЬ
В соответствии с предложением Ника, я добавил много отладочных операторов. Я пошел немного другим путем, потому что это было немного легче сделать - много новых заявлений "в файл".
Но то, что я наблюдал, сбило меня с толку. Небольшой сегмент хранимой процедуры ниже:
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO current_partition_name;
IF done THEN
LEAVE read_loop;
END IF;
IF ! @first AND p_seconds_to_sleep > 0 THEN
SELECT CONCAT('Sleeping for ', p_seconds_to_sleep, ' seconds');
SELECT SLEEP(p_seconds_to_sleep);
END IF;
SELECT CONCAT('Dropping partition: ', current_partition_name);
...
SET @first = FALSE;
END LOOP;
CLOSE cur1;
Все это взято, не изменено, из веб-учебника на странице Джеффа Монти, и работает безупречно в других контекстах (т. Е. В Adminer, из консоли sql - только не в сочетании с PHP-скриптом). Тем не менее, когда я закомментирую строку, которая говорит:
SELECT CONCAT('Dropping partition: ', current_partition_name);
Все работает просто отлично, но сценарий задыхается, когда я вставляю эту строку обратно. Я не могу понять этого. Особенно потому, что - при тестировании - я записываю "current_partition_name" в файл на диске для первых трех итераций цикла, и ссылка на строку в этой ситуации не вызывает никаких проблем. Это очень странно.
Этот другой (по-видимому, неразрешенный) вопрос переполнения стека звучит несколько похоже.
1 ответ
С опозданием я узнал, что разделение недоступно, когда в таблице есть внешние ключи. Я не уверен, как я упустил эту фундаментальную деталь, когда впервые изучал разделение как вариант.
Это очень неудачно, потому что делает все упражнение излишним. Мне придется исследовать какое-то решение, включающее обычное удаление таблиц, со всеми связанными головными болями.
Отдельно я не приблизился к пониманию того, почему комментирование этой конкретной строки из хранимой процедуры Джеффа Монти было ключевым в том, чтобы позволить функции успешно работать при вызове из PHP. Я был бы соблазн объяснить это ошибкой интерпретатора (я использую mySQL 5.5.62 в моей тестовой среде), но, как упоминалось ранее, хранимая процедура выполняется без нареканий при запуске из Adminer.