Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Version Select/Insert d'un Upsert :existe-t-il un modèle de conception pour une concurrence élevée ?

Vous pouvez utiliser des LOCK pour rendre les choses SERIALIZABLE mais cela réduit la simultanéité. Pourquoi ne pas essayer d'abord la condition commune ("la plupart du temps insérer ou sélectionner la plupart du temps") suivie d'une gestion sûre de l'action "corrective" ? C'est-à-dire le modèle "JFDI"...

Principalement des INSERTS attendus (ball park 70-80 % +) :

Essayez simplement d'insérer. En cas d'échec, la ligne a déjà été créée. Pas besoin de vous soucier de la simultanéité car le TRY/CATCH traite les doublons pour vous.

BEGIN TRY
   INSERT Table VALUES (@Value)
   SELECT @id = SCOPE_IDENTITY()
END TRY
BEGIN CATCH
    IF ERROR_NUMBER() <> 2627
      RAISERROR etc
    ELSE -- only error was a dupe insert so must already have a row to select
      SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH

Principalement des SELECT :

Similaire, mais essayez d'abord d'obtenir des données. Aucune donnée =INSERT nécessaire. Encore une fois, si 2 appels simultanés tentent d'INSERER car ils ont tous deux trouvé la ligne manquant les poignées TRY/CATCH.

BEGIN TRY
   SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
   IF @@ROWCOUNT = 0
   BEGIN
       INSERT Table VALUES (@Value)
       SELECT @id = SCOPE_IDENTITY()
   END
END TRY
BEGIN CATCH
    IF ERROR_NUMBER() <> 2627
      RAISERROR etc
    ELSE
      SELECT @id = RowID FROM Table WHERE RowValue = @VALUE
END CATCH

Le 2e semble se répéter, mais il est très concurrent. Les verrous permettraient d'obtenir le même résultat, mais au détriment de la concurrence...

Modifier :

Pourquoi pas utiliser FUSIONNER...

Si vous utilisez la clause OUTPUT, elle ne renverra que ce qui est mis à jour. Vous avez donc besoin d'un UPDATE factice pour générer la table INSERTED pour la clause OUTPUT. Si vous devez effectuer des mises à jour factices avec de nombreux appels (comme l'implique OP), il y a beaucoup d'écritures dans le journal juste pouvoir utiliser MERGE.