2008-10-23 7 views
2

Dans notre base de données en direct/production, j'essaie d'ajouter un déclencheur à une table, mais cela a échoué. J'ai essayé plusieurs fois, mais il a fallu plus de 30 minutes pour que l'instruction create trigger se termine et je l'ai annulée.CREATE TRIGGER prend plus de 30 minutes sur SQL Server 2005

La table est une table qui est souvent lue/écrite par plusieurs processus différents. J'ai désactivé les tâches planifiées qui mettent à jour la table et j'ai essayé à des moments où il y a moins d'activité sur la table, mais je ne suis pas capable d'arrêter tout ce qui accède à la table.

Je ne crois pas qu'il y ait un problème avec l'instruction create trigger elle-même. L'instruction create trigger a été réussie et rapide dans un environnement de test, et le déclencheur fonctionne correctement lorsque des lignes sont insérées/mises à jour dans la table. Bien que lorsque j'ai créé le déclencheur sur la base de données de test, il n'y avait pas de charge sur la table et il y avait beaucoup moins de lignes, ce qui est différent de la base de données live/production (100 vs 13,000,000+).

Voici la create déclencheur que je suis en train de courir

CREATE TRIGGER [OnItem_Updated] 
    ON [Item] 
    AFTER UPDATE 
AS 
BEGIN 
    SET NOCOUNT ON; 

    IF update(State) 
    BEGIN 
     /* do some stuff including for each row updated call a stored 
      procedure that increments a value in table based on the 
      UserId of the updated row */ 
    END 
END 

Peut-il y avoir des problèmes avec la création d'un déclencheur sur une table tandis que les lignes sont mises à jour ou si elle a plusieurs lignes?

Dans SQL Server, les déclencheurs sont créés activés par défaut. Est-il possible de créer le déclencheur désactivé par défaut?

D'autres idées?

Répondre

6

Le problème peut ne pas se trouver dans la table elle-même, mais dans les tables système qui doivent être mises à jour pour créer le déclencheur. Si vous faites un autre type de DDL dans le cadre de vos processus normaux, ils pourraient le retarder.

Utilisez sp_who pour savoir d'où provient le bloc, puis analysez à partir de là.

+1

L'exécution de la fonction sp_who pendant l'exécution de l'instruction de création de trigger m'a aidé à résoudre le problème. Il y avait une ancienne session d'un autre serveur qui était suspendu alors qu'il avait un verrou de stabilité de schéma sur la table, ce qui explique pourquoi je ne pouvais pas créer le déclencheur. –

2

C'est bizarre. Un déclencheur AFTER UPDATE ne devrait pas avoir besoin de vérifier les lignes existantes dans la table. Je suppose qu'il est possible que vous ne soyez pas en mesure d'obtenir un verrou sur la table pour ajouter le déclencheur.

Vous pouvez essayer de créer un déclencheur qui ne fait rien. Si vous ne pouvez pas créer cela, c'est un problème de verrouillage. Si vous le pouvez, vous pouvez désactiver ce déclencheur, ajouter le code voulu au corps et l'activer. (Je ne crois pas que vous pouvez désactiver un déclencheur pendant la création.)

3

Je crois que le déclencheur de CREATE essayera de mettre un verrou sur la table entière.

Si vous avez beaucoup d'activité sur cette table, il se peut que vous deviez attendre longtemps avant de créer un interblocage.

Pour tout changement de schéma, vous devriez vraiment avoir tout le monde dans la base de données. Cela dit, il est tentant de mettre en "petites" modifications avec des connexions actives. Vous devriez jeter un coup d'oeil aux verrous/connexions pour voir où est la contention de verrous.

2

Une partie du problème peut également être le déclencheur lui-même. Votre déclencheur pourrait-il accidentellement mettre à jour toutes les lignes de la table? Il y a une grande différence entre 100 lignes dans une base de données de test et 13 000 000. C'est une très mauvaise idée de développer du code contre un si petit ensemble quand vous avez un ensemble de données si important que vous ne pouvez pas prévoir les performances. SQL qui fonctionne bien pour 100 enregistrements peut complètement verrouiller un système avec des millions pendant des heures.Vous voulez vraiment savoir cela en dev, pas quand vous promouvez à prod.

L'appel d'un proc stocké dans un trigger est généralement un très mauvais choix. Cela signifie également que vous devez parcourir les enregistrements, ce qui est un choix encore pire dans un déclencheur. Les déclencheurs doivent tenir compte de plusieurs insertions/mises à jour ou suppressions d'enregistrements. Si quelqu'un insère 100 000 lignes (ce qui n'est pas improbable si vous avez 13 000 000 enregistrements), alors boucler un proc stocké basé sur un enregistrement peut prendre des heures, verrouiller toute la table et provoquer la recherche du développeur et tuer (ou au moins mutiler) lui parce qu'ils ne peuvent pas faire leur travail.

Je n'envisagerais même pas de mettre ce déclencheur sur prod jusqu'à ce que vous testiez sur un ensemble d'enregistrements de taille similaire à prod.

Mon ami Dennis a écrit cet article qui illustre pourquoi tester une petite volumn d'informations lorsque vous avez un grand volumn d'information peut créer des difficultés sur prd que vous ne remarquez pas le dev: http://blogs.lessthandot.com/index.php/DataMgmt/?blog=3&title=your-testbed-has-to-have-the-same-volume&disp=single&more=1&c=1&tb=1&pb=1#c1210

+0

bon conseil imho – DForck42

0

Run DISABLE TRIGGER triggername ON tablename avant modification du déclencheur, puis réactivation avec ENABLE TRIGGER triggername ON tablename

Questions connexes