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

Отладка MySQL-триггеров

Я люблю триггеры по одной причине - они просто работают. Я ненавижу триггеры по одной причине - когда они не работают, забудьте про попытку отладки. О сладкое разочарование.

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

Я пытаюсь отлаживать запрос на обновление с несколькими объединениями, а что нет. Мои запросы намного сложнее, но для краткости здесь приведен пример.

DELIMITER |
CREATE TRIGGER ireallyhateyourightnow AFTER UPDATE ON watch_this_table
FOR EACH ROW BEGIN
 IF (OLD.my_value != NEW.my_value) THEN
  update 
   my_table
  set 
   my_column = NEW.my_value;
 END IF;
END|
DELIMITER ;

Вот еще один дополнительный контекст, который может повлиять на предложение или ответ. Опять же, меня меньше интересует семантика/синтаксис и больше интересует, как MySQL запускает запрос, но, во что бы то ни стало, я открыт для чего-либо на этом этапе.

  • Strace не работает/показывает запрос.
  • Не реплицированная среда, но если журналы bin отображают триггерные инструкции, я обязательно установлю это.
  • Выполняется ли "show full processlist" выполнение триггера выполнения и/или выполняемые инструкции (я никогда не вижу их после запуска полного списка процессов, так как Perl может запускать его, но я могу просто его не заметить)?
  • Общий журнал запросов не отображает эти запросы (конечно, не журнал ошибок).
  • Я не использую псевдонимы (больше).
  • При создании триггера отсутствуют синтаксические ошибки.
  • Оператор IF работает.
  • Когда я вставляю НОВЫЕ значения в таблицу "test/temp" и вручную запускаю запрос на обновление, он работает (я даже зашел так далеко, что фактически ввел весь запрос на обновление).
  • Я не могу показать вам запрос, но, как я только что упомянул, он работает, когда я запускаю вручную, если это помогает.
  • Я удалил все ошибочные символы, вкладки, возврат каретки, новые строки и т.д.
  • Я думаю, что сокет MySQL будет показывать только локальное соединение/данные, но не внутреннюю работу MySQL.
  • MyISAM, поэтому журналы INNODB не являются опцией
  • lsof, похоже, не показывал ничего полезного.
  • Я использую MySQL 5.0.77 на CentOS 5.5.
4b9b3361

Ответ 1

Вы можете отлаживать триггеры с помощью dbForge Studio for MySQL, Попробуйте пробную версию.

Подробное описание процесса отладки триггера в документации: Отладка\Отладка хранимых процедур \How To: запуск отладки триггеров.

Ответ 2

Там альтернативный способ тестирования с помощью временной таблицы debug. В этом примере они создают его в собственной базе данных debug.

Шаг 1: Создать таблицу

DROP TABLE IF EXISTS debug;
CREATE TABLE debug (
  proc_id varchar(100) default NULL,
  debug_output text,
  line_id int(11) NOT NULL auto_increment,
  PRIMARY KEY  (line_id)
)

Шаг 2: Создайте отладочные SP для заполнения таблицы отладки

DELIMITER $$

DROP PROCEDURE IF EXISTS `debug_insert` $$
CREATE PROCEDURE `debug_insert`(in p_proc_id varchar(100),in p_debug_info text)
begin
  insert into debug (proc_id,debug_output)
  values (p_proc_id,p_debug_info);
end $$

DROP PROCEDURE IF EXISTS `debug_on` $$
CREATE PROCEDURE `debug_on`(in p_proc_id varchar(100))
begin
  call debug_insert(p_proc_id,concat('Debug Started :',now()));
end $$

DROP PROCEDURE IF EXISTS `debug_off` $$
CREATE PROCEDURE `debug_off`(in p_proc_id varchar(100))
begin
  call debug_insert(p_proc_id,concat('Debug Ended :',now()));
  select debug_output from debug where proc_id = p_proc_id order by line_id;
  delete from debug where proc_id = p_proc_id;
end $$

Шаг 3: Вызовите отладочные SP в триггере

Как это,

CREATE PROCEDURE test_debug()
begin
declare l_proc_id varchar(100) default 'test_debug';
  call debug_on(l_proc_id);
  call debug_insert(l_proc_id,'Testing Debug');
  call debug_off(l_proc_id);
end $$

В результате таблица отладки будет заполнена следующим образом,

+------------------------------------+
| debug_output                       |
+------------------------------------+
| Debug Started :2006-03-24 16:10:33 |
| Testing Debug                      |
| Debug Ended :2006-03-24 16:10:33   |
+------------------------------------+

Ответ 3

ПРОЦЕДУРА MYSQL = > incron = > tail -f 'mysql_dynamic.log'

Сохраненная процедура может быть вызвана внутри триггера, но не должна возвращать ничего

CREATE PROCEDURE `DYN_LOG` (IN s VARCHAR(500))
BEGIN
SELECT s into outfile '/var/spool/incron/mysql_dynamic_spool/foo_file';
DO SLEEP(.1);   // create a gap beetween multiple shuts
END

Теперь в любом месте триггера вы можете вызвать

CREATE TRIGGER `trig_name` BEFORE UPDATE ON `tb_name` 
FOR EACH ROW
BEGIN
CALL DYN_LOG(concat_ws('\t',NEW.col1,NEW.col2));
... 
// rest of the code
END

для Linux-машин apt-get install incron (учебник по debian incron)

Создайте папку, в которой mysql будет вводить foo_file

mkdir -m 777 /var/spool/incron/mysql_dynamic_spool
incrontab -e

и добавьте следующее задание в подземелье

/var/spool/incron/mysql_dynamic_spool IN_CREATE /path/foo_file_procesor [email protected]/$#

Создать исполняемый файл script "/path/foo_file_procesor"

#!/bin/sh
# // $1 is the foo_file absolute addres
body="$( cat $1 )" // read file content
rm  $1
log=/var/log/mysql_dynamic.log    // message collector
echo "`date "+%y%m%d %H:%M:%S"`\t== dyn_log ==\t$body">>$log
exit 0

Теперь смотрите файл коллектора

tail -f /var/log/mysql_dynamic.log