Rufen Sie eine gespeicherte Prozedur über einen Trigger auf

17

Ich habe eine gespeicherte Prozedur in MySQL mit der folgenden Syntax erstellt.

DROP PROCEDURE IF EXISTS `sp-set_comment_count`;

DELIMITER $$

CREATE PROCEDURE `sp_set-comment_count` (IN _id INT)
BEGIN
   -- AC   - AllCount
   DECLARE AC INT DEFAULT 0;

   SELECT COUNT(*) AS ac
     INTO AC
     FROM usergroups AS ug
LEFT JOIN usergroup_comments AS ugm ON ugm.`gid` = ug.`id`
LEFT JOIN mediagallery AS dm ON ugm.mid = dm.`id`
    WHERE dm.`status` NOT IN (200, 201, 202, 203, 204, 205)
      AND ug.`id` = _id;

   UPDATE usergroups
      SET allCount = AC,
    WHERE usergroups.`id` = _id;

END $$
DELIMITER ;

Zu Ihrer Information Ich habe die gespeicherte Prozedur stark vereinfacht, aber ich weiß, dass sie ohne Probleme funktioniert.

Ich möchte in der Lage sein, einen Trigger aus usergroup_comments einzurichten, der wie folgt funktioniert.

DROP TRIGGER IF EXISTS `usergroups_comments_insert` 

CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
    FOR EACH ROW
    BEGIN
       CALL sp-set-comment_count(NEW.`gid`);
    END;

Aber aus irgendeinem Grund wirft mir jedes Mal, wenn ich mit MySQL arbeite, ein Fehler zu, der nicht hilfreich ist und besagt, dass in Zeile 4 ein Syntaxfehler vorliegt.

Ich habe die MySQL-Dokumentation durchgesehen und einige Informationen zu Einschränkungen von Triggern gefunden, aber festgestellt, dass sie ziemlich verworren sind.

http://dev.mysql.com/doc/refman/5.1/en/stored-program-restrictions.html

Irgendwelche Ideen wären hilfreich.

Mark D
quelle
Es stellte sich also heraus, dass das Problem beim Aufrufen der oben genannten gespeicherten Prozedur darin bestand, dass ihr Name einen Bindestrich enthielt. Durch Ändern des Namens der gespeicherten Prozedur in sp_set_comment_count wurde das Problem behoben.
Mark D

Antworten:

24

Es gibt einen guten Grund, warum Sie gespeicherte Prozeduren niemals aus Triggern heraus aufrufen sollten.

Trigger sind von Natur aus gespeicherte Prozeduren. Ihre Aktionen sind praktisch schwer rückgängig zu machen . Selbst wenn alle zugrunde liegenden Tabellen InnoDB sind, werden Sie ein proportionales Volumen an gemeinsam genutzten Zeilensperren und ärgerliche Unterbrechungen durch exklusive Zeilensperren feststellen. Dies wäre der Fall, wenn Trigger Tabellen manipulieren würden, wobei INSERTs und UPDATEs stagnieren, um bei jedem Aufruf eines Triggers eine Hochleistungs- MVCC durchzuführen .

Vergessen Sie nicht, dass Trigger Overhead erfordern. Laut MySQL Stored Procedure Programming lautet die Überschrift "Trigger Overhead" auf Seite 256 wie folgt:

Es ist wichtig, sich daran zu erinnern, dass Trigger der DML-Anweisung, für die sie gelten, notwendigerweise zusätzlichen Aufwand hinzufügen. Der tatsächliche Overhead hängt von der Art des Triggers ab. Da jedoch alle MySQL-Trigger FÜR JEDE REIHE ausgeführt werden, kann sich der Overhead bei Anweisungen, die eine große Anzahl von Zeilen verarbeiten, schnell ansammeln. Sie sollten daher vermeiden, teure SQL-Anweisungen oder Prozedurcode in Triggern zu platzieren.

Eine ausführliche Erläuterung des Trigger-Overheads finden Sie auf den Seiten 529-531. Der Schlusspunkt aus diesem Abschnitt lautet wie folgt:

Die Lehre hier ist folgende: Da der Triggercode einmal für jede Zeile ausgeführt wird, die von einer DML-Anweisung betroffen ist, kann der Trigger leicht zum wichtigsten Faktor für die DML-Leistung werden. Der Code im Trigger-Body muss so leicht wie möglich sein. Insbesondere sollten alle SQL-Anweisungen im Trigger nach Möglichkeit durch Indizes unterstützt werden.

Ich habe in einem früheren Beitrag andere unangenehme Aspekte von Triggern erklärt.

ZUSAMMENFASSUNG

Ich würde dringend empfehlen, keine gespeicherten Prozeduren von einem Trigger aufzurufen , auch wenn MySQL dies zulässt. Sie sollten sich die aktuellen Einschränkungen für MySQL 5.5 ansehen .

RolandoMySQLDBA
quelle
Interessant, danke für die Köpfe hoch. Das Fehlen von Transaktionsabfragen in unserer Umgebung verringert das Transaktionsproblem. Ich kann jedoch die Idee der Anhäufung von Overhead schätzen. Ich schätze, ich werde die Datenbank eine Weile beobachten, um zu sehen, was das Ergebnis dieser Änderung ist.
Mark D
Ich denke nicht, dass es richtig ist, Trigger mit gespeicherten Prozeduren zu kombinieren. Das Starten und Festschreiben einer Transaktion in einer gespeicherten Prozedur ist mindestens gültig. MySQL beschwert sich, wenn Sie versuchen, dasselbe in einem Trigger zu tun. Das ist albern, weil ein Trigger, der eine oder mehrere Tabellen als Reaktion auf eine Änderung transaktional aktualisieren muss, ein völlig gültiger Anwendungsfall ist, der auf einfache Weise unterstützt werden sollte.
Aroth
Ich habe also diesen Auslöser, der wirklich groß ist. Es führt mehrere Berechnungen für meine Tabelle durch, sowohl beim Einfügen als auch beim Aktualisieren. Trigger in MySQL können wirklich schmerzhaft werden, wenn sie komplex sind. Es wäre viel einfacher, den Trigger in Prozeduren aufzuteilen.
Lamar
8

Es stellt sich also heraus, dass dies das Problem ist, das mich ein paar Stunden lang geplagt hat, ob Sie es glauben oder nicht.

Ich kann leicht eine Prozedur mit dem Namen sp_set-comment_count definieren. Wenn Sie diese Prozedur aufrufen, funktioniert dies jedoch nicht auf die gleiche Weise.

CALL sp_set-comment_count (das kann ich nur vermuten, weil der Server das - als Minus interpretiert).

Ich habe seitdem den Namen der gespeicherten Prozedur geändert, um nur Unterstriche zu verwenden, und es scheint, alles gelöst zu haben.

Mark D
quelle
Verspätet zur Party, aber: Sie haben Ihren SP mit einer in Anführungszeichen gesetzten Kennung erstellt, die Sonderzeichen im Namen CALL `sp-set-comment_count`(NEW.`gid`);
zulässt. Daher
5

Wenn es sich um einen Syntaxfehler handelt, haben Sie wahrscheinlich vergessen, das Trennzeichen zu ändern (wie bei der gespeicherten Prozedur). Also brauchst du

DELIMITER $$
CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
FOR EACH ROW
BEGIN
   CALL sp_set_count(NEW.`gid`);
END;
$$
a1ex07
quelle
Danke, das hat mich tatsächlich dazu gebracht, auf dem richtigen Weg zu denken. Tatsächlich hieß mein sp sp-set_comment_count. Beim Aufrufen durch einen Trigger scheint das Problem zu bestehen, dass beim Aufrufen des SP durch den Trigger der Fehler immer wieder ausgelöst wurde.
Mark D
1

Das nachfolgende Komma ACist ein Syntaxfehler:

UPDATE usergroups
   SET allCount = AC,
 WHERE ........
user22800
quelle
Gültiger Punkt, aber nicht die eigentliche Fehlerursache in diesem Fall. Ich habe einfach einige zusätzliche Sätze aus dieser Abfrage entfernt und vergessen, den,
Mark D