2013-04-11 3 views
11

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

Это прекрасно работает на нашем локальном MySQL версии 5.5.25

Я не нашел никаких документов, которые бы объяснить такое поведение, знает ли кто, возможно, имеют одинаковую проблему?

Это либо ошибка, которая возникает в версии MySQL более 5.5.25, либо «функция», которая включена случайно.

UPDATE table1 => fires BEFORE UPDATE trigger ON table1 
     table1 BEFORE UPDATE TRIGGER executes: DELETE FROM table2 => should fire BEFORE DELETE trigger on table2 (but doesn't) 
      table 2 BEFORE DELETE TRIGGER executes: DELETE FROM table3 (never happens) 

OK вот мои шаги: воспроизвести

База данных

CREATE DATABASE "triggerTest" DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci; 

Столы

CREATE TABLE "table1" (
    "id" int(11) NOT NULL AUTO_INCREMENT, 
    "active" tinyint(1) NOT NULL DEFAULT '0', 
    "sampleData" varchar(100) COLLATE utf8_unicode_ci NOT NULL DEFAULT '', 
    PRIMARY KEY ("id") 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC; 


CREATE TABLE "table2" (
    "id" int(11) NOT NULL AUTO_INCREMENT, 
    "table1_id" int(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY ("id"), 
    CONSTRAINT "test2_fk_table1_id" FOREIGN KEY ("table1_id") REFERENCES "table1" ("id") ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC; 


CREATE TABLE "table3" (
    "id" int(11) NOT NULL AUTO_INCREMENT, 
    "table1_id" int(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY ("id"), 
    CONSTRAINT "test3_fk_table1_id" FOREIGN KEY ("table1_id") REFERENCES "table1" ("id") ON DELETE CASCADE ON UPDATE CASCADE 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci ROW_FORMAT=DYNAMIC; 

Триггеры

DELIMITER $$ 

CREATE TRIGGER "table1_rtrg_AI" AFTER INSERT ON "table1" FOR EACH ROW 
BEGIN 
    IF NEW."active" THEN 
     INSERT INTO "table2" ("table1_id") SELECT NEW."id"; 
    END IF; 
END$$ 

CREATE TRIGGER "table1_rtrg_BU" BEFORE UPDATE ON "table1" FOR EACH ROW 
BEGIN 
    IF NOT NEW."active" AND OLD."active" THEN 
     DELETE FROM "table2" WHERE "table1_id" = OLD."id"; 
    END IF; 

    IF NEW."active" AND NOT OLD."active" THEN 
     INSERT INTO "table2" ("table1_id") SELECT NEW."id"; 
    END IF; 
END$$ 

CREATE TRIGGER "table2_rtrg_AI" AFTER INSERT ON "table2" FOR EACH ROW 
BEGIN 
    INSERT INTO "table3" ("table1_id") SELECT NEW."table1_id"; 
END$$ 

CREATE TRIGGER "table2_rtrg_BD" BEFORE DELETE ON "table2" FOR EACH ROW 
BEGIN 
    DELETE FROM "table3" WHERE "table1_id" = OLD."table1_id"; 
END$$ 

DELIMITER ; 

Q: Почему вы цитируете идентификаторы, используя двойные кавычки? (Вместо обратных кавычек)

Потому что мне не нравится "ниша" синтаксис

mysql> show variables LIKE 'sql_mode'; 
+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| Variable_name | Value                                    | 
+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 
| sql_mode  | PIPES_AS_CONCAT,**ANSI_QUOTES**,IGNORE_SPACE,NO_UNSIGNED_SUBTRACTION,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION | 
+---------------+------------------------------------------------------------------------------------------------------------------------------------------------------+ 
1 row in set (0.00 sec) 

TestCase 1: Ожидаемое поведение (база данных версия 5.2.20)

mysql> SELECT VERSION(); 
+-----------+ 
| VERSION() | 
+-----------+ 
| 5.5.20 | 
+-----------+ 
1 row in set (0.00 sec) 

mysql> SET GLOBAL general_log := ON; 

тестирование вставки триггером

mysql> INSERT INTO "table1" ("active", "sampleData") SELECT 0, 'sample data row 1'; 
Query OK, 1 row affected (0.00 sec) 
Records: 1 Duplicates: 0 Warnings: 0 

general_log: 
130423 12:51:27 78010 Query  INSERT INTO "table1" ("active", "sampleData") SELECT 0, 'sample data row 1' 


mysql> INSERT INTO "table1" ("active", "sampleData") SELECT 1, 'sample data row 2'; 
Query OK, 1 row affected (0.00 sec) 
Records: 1 Duplicates: 0 Warnings: 0 

general_log: 
130423 12:51:33 78010 Query  INSERT INTO "table1" ("active", "sampleData") SELECT 1, 'sample data row 2' 
       78010 Query  INSERT INTO "table2" ("table1_id") SELECT NEW."id" 
       78010 Query  INSERT INTO "table3" ("table1_id") SELECT NEW."table1_id" 

ожидается содержимое таблицы:

mysql> SELECT * FROM "table1"; 
+----+--------+-------------------+ 
| id | active | sampleData  | 
+----+--------+-------------------+ 
| 1 |  0 | sample data row 1 | 
| 2 |  1 | sample data row 2 | 
+----+--------+-------------------+ 
2 rows in set (0.00 sec) 

mysql> SELECT * FROM "table2"; 
+----+-----------+ 
| id | table1_id | 
+----+-----------+ 
| 1 |   2 | 
+----+-----------+ 
1 row in set (0.00 sec) 

mysql> SELECT * FROM "table3"; 
+----+-----------+ 
| id | table1_id | 
+----+-----------+ 
| 1 |   2 | 
+----+-----------+ 
1 row in set (0.00 sec) 

тестирования триггер обновления, установите активный

mysql> UPDATE "table1" SET "active" = 1 WHERE "id" = 1; 
Query OK, 1 row affected (0.00 sec) 
Rows matched: 1 Changed: 1 Warnings: 0 

query_log: 
130423 12:52:15 78010 Query  UPDATE "table1" SET "active" = 1 WHERE "id" = 1 
       78010 Query  INSERT INTO "table2" ("table1_id") SELECT NEW."id" 
       78010 Query  INSERT INTO "table3" ("table1_id") SELECT NEW."table1_id" 

ожидается содержимое таблицы:

mysql> SELECT * FROM "table1"; 
+----+--------+-------------------+ 
| id | active | sampleData  | 
+----+--------+-------------------+ 
| 1 |  1 | sample data row 1 | 
| 2 |  1 | sample data row 2 | 
+----+--------+-------------------+ 
2 rows in set (0.00 sec) 

mysql> SELECT * FROM "table2"; 
+----+-----------+ 
| id | table1_id | 
+----+-----------+ 
| 2 |   1 | 
| 1 |   2 | 
+----+-----------+ 
2 rows in set (0.00 sec) 

mysql> SELECT * FROM "table3"; 
+----+-----------+ 
| id | table1_id | 
+----+-----------+ 
| 2 |   1 | 
| 1 |   2 | 
+----+-----------+ 
2 rows in set (0.00 sec) 

тестирования триггер обновления, установите неактивным

mysql> UPDATE "table1" SET "active" = 0 WHERE "id" = 2; 
Query OK, 1 row affected (0.01 sec) 
Rows matched: 1 Changed: 1 Warnings: 0 

query_log: 

130423 12:52:49 78010 Query  UPDATE "table1" SET "active" = 0 WHERE "id" = 2 
       78010 Query  DELETE FROM "table2" WHERE "table1_id" = NEW."id" 
       78010 Query  DELETE FROM "table3" WHERE "table1_id" = OLD."table1_id" 

ожидается таблица содержания:

mysql> SELECT * FROM "table1"; 
+----+--------+-------------------+ 
| id | active | sampleData  | 
+----+--------+-------------------+ 
| 1 |  1 | sample data row 1 | 
| 2 |  0 | sample data row 2 | 
+----+--------+-------------------+ 
2 rows in set (0.00 sec) 

mysql> SELECT * FROM "table2"; 
+----+-----------+ 
| id | table1_id | 
+----+-----------+ 
| 2 |   1 | 
+----+-----------+ 
1 row in set (0.00 sec) 

mysql> SELECT * FROM "table3"; 
+----+-----------+ 
| id | table1_id | 
+----+-----------+ 
| 2 |   1 | 
+----+-----------+ 
1 row in set (0.00 sec) 

Testcase2: неожиданное поведение (MySQL версии 5.5.30)

Holy вызывает GRML - Вы знаете, что? Стыдно, что я не проверял второй случай первый - к сожалению, я не был в состоянии воспроизвести ошибку .. тест работал на 5.5.30, а также, будет держать вас в курсе :)

EDIT Trigger не каскадом из-за неизвестного определителя, который оставался в свалке sql, сделанном для производства. Удаление DEFINER = в дампах запуска (альтернативным решением было бы создать пользователя или изменить DEFINER = на существующий) решил проблему, решил часть проблемы.

Неизвестное Определитель не вызывает каких-либо выходной файл журнала

+4

* отображается фактический кусок кода *, пожалуйста. – Sebas

+0

Что-нибудь интересное в журналах? Кроме того, можете ли вы создать небольшой пример в новой базе данных, чтобы проиллюстрировать проблему? (Если он воспроизводимый, его легче понять, imo). – halfer

+0

Эй, Мишель, да, как сказал халфер, вы могли бы привести нам пример дизайна вашего стола. – medina

ответ

8

Окончательный вывод: MySQL 5.5.30 не глючит в этом случае также не было расконфигурация самого сервера.

Несколько самодельных ошибок возникла проблема:

Ошибка I: пользователь DEFINER не существует

Вместо того, чтобы просто генерирующую базу данных на рабочей машине, я был ленивым и сбрасывали базу данных тестирования к производственной машине. Если вы не указали явно DEFINER в своем заявлении CREATE TRIGGER, оно установлено на CURRENT_USER. К сожалению, этот точный CURRENT_USER на моей тестовой машине не существует на производственном сервере.

Ошибка II: бездельничать

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

mysqldump --triggers --routines -h test -p database | gzip -3 | ssh production "gunzip -c | mysql -h production_database_host -p production_database" 

Это выглядит здорово (OMG выродок) и экономит много файла дампа толкающей, но surpresses предупреждения вы можете увидеть при загрузке дампа в консоли

MySQL пишет Ниже о триггерном определителе:

Если указать положение DEFINER, эти правила определяют допустимые значения пользователя DEFINER:

Если у вас нет привилегии SUPER, единственным законным значением пользователя является ваша собственная учетная запись, указанная буквально или с использованием CURRENT_USER. Вы не можете установить определитель для какой-либо другой учетной записи.

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

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

Источник: http://dev.mysql.com/doc/refman/5.5/en/create-trigger.html

Ошибка III: бездельничать

У меня есть очень крутой туздЫшпр обертку, которая способна генерировать чистые, многоразовые файлы дампа. При перезаписывании триггеров без DEFINER у меня была консольная транзакция (блокировка table2), открытая на рабочем сервере, поэтому триггеры на таблице2 вообще не обновлялись, но опять же, из-за моего конвейера sql-данных на 5 серверах я не видел таймаут ошибка.

Вывод:

Там не было ошибка, только триггеры не были созданы правильно ..

Иногда вы должны перестать быть ленивым, давая важные вещи в немного больше времени и внимание может сэкономить вам много времени !!

1

Триггеры в MySQL (в отличие от хранимых процедур) всегда запускаются в контексте DEFINER. Возможно, триггеры не работают, потому что у DEFINER нет разрешений на выполнение какого-либо или всего триггера. В частности, в MySQL 5.1 и более поздних версиях DEFINER должна иметь привилегию TRIGGER, а также соответствующие права SELECT и/или UPDATE.

Если триггеры не работают, проверьте привилегии.

 Смежные вопросы

  • Нет связанных вопросов^_^