sql >> Databasteknik >  >> RDS >> Sqlserver

Välj / Infoga version av en Upsert:finns det ett designmönster för hög samtidighet?

Du kan använda LÅS för att göra saker SERIALISERbara men detta minskar samtidighet. Varför inte prova det vanliga tillståndet först ("för det mesta infoga eller mestadels välj") följt av säker hantering av "avhjälpande" åtgärder? Det vill säga "JFDI"-mönstret...

Mestadels INSERTs förväntas (bollpark 70-80%+):

Försök bara lägga in. Om det misslyckas har raden redan skapats. Du behöver inte oroa dig för samtidighet eftersom TRY/CATCH hanterar dubbletter åt dig.

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

Mestadels SELECT:

Liknande, men försök att få data först. Inga data =INFO behövs. Återigen, om två samtidiga anrop försöker INFOGA eftersom de båda hittade att raden saknade TRY/CATCH-handtagen.

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

Den andra verkar upprepa sig, men den är mycket samtidig. Lås skulle uppnå samma sak men på bekostnad av samtidighet...

Redigera:

Varför inte för att använda MERGE...

Om du använder OUTPUT-satsen kommer den bara att returnera det som är uppdaterat. Så du behöver en dummy UPDATE för att generera INSERTED-tabellen för OUTPUT-satsen. Om du måste göra dummy-uppdateringar med många anrop (som antyds av OP) är det mycket logg som skriver bara för att kunna använda MERGE.



  1. Hur returnerar man flera värden i en kolumn (T-SQL)?

  2. effektivt sätt att implementera personsökning

  3. Hur man byter namn på ett tabellnamn i SQL Server

  4. Fel när QUERY-paketet skickades