Saklanan yordamı bir tetikleyiciden çağırma


17

Aşağıdaki sözdizimini kullanarak mysql saklı bir yordam oluşturduk.

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 ;

FYI Saklı yordamı büyük ölçüde basitleştirdim ama herhangi bir sorun olmadan çalışır biliyorum.

Yapabileceğim şey, usergroup_comments tarafından böyle çalışan bir tetikleyici kurmak.

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;

Ama nedense her zaman mysql bana bir hata atar 4. satırda bir sözdizimi hatası olduğunu belirten daha az yardımcı olur.

MySQL belgeleri ile taranmış ve tetikleyici kısıtlamaları hakkında bazı bilgiler buldum ama oldukça kıvrık bulundu.

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

Herhangi bir fikir yardımcı olacaktır.


Bu nedenle, yukarıdaki saklı yordamın çağrılmasıyla ilgili sorun, adında bir kısa çizgi olmasıydı. Saklı yordam adını sp_set_comment_count olarak değiştirmek sorunu çözdü.
Mark D

Yanıtlar:


24

Saklı yordamları hiçbir zaman tetikleyicilerden çağırmamanız için büyük bir neden vardır.

Tetikleyiciler, doğası gereği, saklı prosedürlerdir. Eylemlerini geri almak neredeyse zor . Altta yatan tüm tablolar InnoDB olsa bile, özel satır kilitlerinden oransal olarak paylaşılan satır kilitleri ve rahatsız edici kesintiler yaşayacaksınız. Tetikleyiciler, INSERT'ler ve UPDATE'ler bir tetikleyiciye yapılan her çağrıda ağır MVCC gerçekleştirmek için durdurulan tabloları manipüle ediyorsa böyle olurdu .

Tetikleyicilerin ek yük gerektirdiğini unutmayın. Aslında, MySQL Saklı Yordam Programlama göre , "256 Tepegöz" başlığının altında 256:

Zorunlu olarak, tetikleyicilerin uygulandıkları DML ifadesine ek yük getirdiğini hatırlamak önemlidir. ek yükün gerçek miktarı tetikleyicinin doğasına bağlı olacaktır, ancak --- tüm MySQL tetikleyicilerinin HER SATIR İÇİN yürüttüğü gibi --- ek yük çok sayıda satır işleyen ifadeler için hızlı bir şekilde birikebilir. Bu nedenle, pahalı SQL deyimlerini veya yordamsal kodları tetikleyicilere yerleştirmekten kaçınmalısınız.

Tetikleyici ek yükünün genişletilmiş açıklaması 529-531. Sayfalarda verilmiştir. Bu bölümdeki sonuç noktası aşağıdakileri belirtir:

Buradaki ders şudur: tetikleme kodu bir DML ifadesinden etkilenen her satır için bir kez çalışacağından, tetikleyici kolayca DML performansında en önemli faktör haline gelebilir. Tetikleyici gövdenin içindeki kodun olabildiğince hafif olması ve özellikle tetikleyicideki SQL ifadelerinin mümkün olduğunca dizinler tarafından desteklenmesi gerekir.

Daha önceki bir yazıda Triggers'ın diğer kötü yönlerini açıkladım.

ÖZET

Ben ediyorum şiddetle Tetikleyici herhangi saklı yordamları çağırmak değil tavsiye MySQL izin veriyorsa bile,. MySQL 5.5 için geçerli kısıtlamaları kontrol etmelisiniz .


İlginç, kafalar için teşekkürler. Ortamımızda işlem sorgularının bulunmaması, işlem sorununu azaltır. Ancak havai biriktirme fikrini takdir ediyorum. Sanırım bu değişikliğin sonucunu görmek için bir süre db'yi izleyeceğim.
Mark D

Tetikleyicileri saklı yordamlarla birleştirmenin doğru olduğunu düşünmüyorum. En azından, bir işlemi saklı yordamda başlatmak ve uygulamak geçerlidir. Bir tetikleyicide aynısını yapmaya çalışırsanız MySQL şikayet ediyor. Bu saçmadır, çünkü bazı değişikliklere yanıt olarak bir veya daha fazla tabloyu işlemsel olarak güncellemesi gereken bir tetikleyiciye sahip olmak, basit bir şekilde desteklenmesi gereken tamamen geçerli bir kullanım durumudur.
Ocak'ta aroth

Bu tetikleyicim var, bu gerçekten büyük. Hem ekleme hem de güncelleme üzerine masamda çeşitli hesaplamalar yapar. Mysql'deki tetikleyiciler karmaşık olduklarında gerçekten acı verebilir. Tetiği prosedürlere ayırmak çok daha kolay olurdu.
Lamar

8

Bu yüzden, birkaç saatliğine inandığım ya da inanmadığım bir sorun var.

Sp_set-comment_count adlı bir yordamı kolayca tanımlayabilirim. Ancak, söz konusu prosedürü çağırırken, aynı şekilde çalışmaz.

CALL sp_set-comment_count (Bunun yalnızca sunucunun - eksi olarak yorumlaması nedeniyle olduğunu varsayabilirim).

O zamandan beri sadece alt çizgi kullanmak için saklı yordam adını değiştirdim ve her şeyi çözmüş gibi görünüyor.


Partiye geç ama: CALL `sp-set-comment_count`(NEW.`gid`);
SP'nizi

5

Sözdizimi hatası hakkında yazıyorsa, büyük olasılıkla sınırlayıcıyı değiştirmeyi unuttunuz (saklı yordamda yaptığınız gibi). Yani ihtiyacın var

DELIMITER $$
CREATE TRIGGER `usergroups_comments_insert` AFTER INSERT ON `usergroups_comment`
FOR EACH ROW
BEGIN
   CALL sp_set_count(NEW.`gid`);
END;
$$

Teşekkür ederim bu aslında doğru yolda düşünmemi sağladı. Aslında sp'm sp-set_comment_count olarak adlandırıldı. Bir tetikleyici tarafından çağrıldığında, sorun tetikleyiciden SP çağrıldığında - hata atmaya devam etti.
Mark D

1

Görünüşe göre virgül sonra ACbir sözdizimi hatası:

UPDATE usergroups
   SET allCount = AC,
 WHERE ........

Geçerli nokta, ama bu durumda hatanın gerçek nedeni değil sadece ben bu sorgudan bazı ekstra setleri kesilmiş ve kaldırmayı unuttum,
Mark D
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.