Aus irgendeinem Grund feuert ein Trigger, der eine Zeile aus einer zweiten Tabelle löscht, nicht mehr den Löschtrigger für die zweite Tabelle auf einer MySQL 5.5.30-Maschine.MySQL 5.5.30 kaskadierte Trigger funktionieren nicht
Das funktioniert perfekt auf unsere lokalen MySQL Version 5.5.25
Ich habe keine Dokumentation finden, die dieses Verhalten erklären würde, vielleicht hat jemand das gleiche Problem?
Dies ist entweder ein Fehler in der MySQL-Version größer als 5.5.25 oder ein "Feature", das versehentlich aktiviert wird.
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 hier meine Schritte reproduzieren:
Datenbank
CREATE DATABASE "triggerTest" DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;
Tabellen
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;
Trigger
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 ;
F: Warum zitieren Sie Bezeichner doppelte Anführungszeichen verwenden? (Anstelle von Backticks)
Weil Ich mag "Nische Syntax" nicht
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)
Testfall 1: Erwartetes Verhalten (Datenbankversion 5.2.20)
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.5.20 |
+-----------+
1 row in set (0.00 sec)
mysql> SET GLOBAL general_log := ON;
Testeinsatz Trigger
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"
erwartet Tabelleninhalt:
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)
Testaktualisierungstrigger, aktiv gesetzt
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"
erwartet Tabelleninhalt:
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)
Testaktualisierungstrigger,
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"
erwartet Tabelleninhalte inaktiv gesetzt:
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: unerwartetes Verhalten (MySQL Version 5.5.30)
Heilige löst grml - Weißt du was? Schade, dass ich nicht den zweiten Fall zuerst prüfen hat - leider war ich nicht in der Lage, den Fehler zu reproduzieren .. der Test auf 5.5.30 wie gut funktioniert, halten Sie auf dem Laufenden :)
EDIT Auslöser tat nicht Kaskade wegen eines unbekannten Definierers, der in der für die Produktion gemachten Sqldumps verblieb. Entfernen von DEFINER = in den Trigger-Dumps (alternative Lösung wäre, den Benutzer zu erstellen oder DEFINER = zu einem vorhandenen zu ändern) löste das Problem, löste einen Teil des Problems.
Der unbekannte definer keine Protokolldateiausgabe
* zeigen Sie bitte das tatsächliche Stück Code *. – Sebas
Alles von Interesse in den Protokollen? Können Sie auch ein kleines Beispiel für eine brandneue Datenbank erstellen, um das Problem zu veranschaulichen? (Wenn es replizierbar ist, ist es einfacher zu verstehen, imo). – halfer
Hey Michel, ja, als Halber sagten Sie könnten uns ein Beispiel für das Design Ihres Tisches geben. – medina