sql >> Databáze >  >> RDS >> Sqlserver

Vybrat / vložit verzi Upsert:existuje návrhový vzor pro vysokou souběžnost?

Můžete použít ZÁMKY, aby se věci staly SERIALIZAČNÍMI, ale to snižuje souběžnost. Proč nezkusit nejprve běžnou podmínku („většinou vložit nebo většinou vybrat“) a poté bezpečně provést „nápravnou“ akci? Tedy vzor "JFDI"...

Očekávané většinou INSERTy (ball park 70-80 %+):

Jen zkuste vložit. Pokud selže, řádek již byl vytvořen. Není třeba se obávat souběžnosti, protože TRY/CATCH řeší duplikáty za vás.

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

Většinou SELECT:

Podobné, ale zkuste nejprve získat data. Žádná data =potřeba INSERT. Znovu, pokud se 2 souběžná volání pokusí o INSERT, protože oba nalezli v řádku chybějící úchyty 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

Zdá se, že druhý se opakuje, ale je vysoce souběžný. Zámky by dosáhly stejného, ​​ale na úkor souběžnosti...

Upravit:

Proč ne použít MERGE...

Pokud použijete klauzuli OUTPUT, vrátí pouze to, co je aktualizováno. K vygenerování tabulky INSERTED pro klauzuli OUTPUT tedy potřebujete fiktivní UPDATE. Pokud musíte provádět fiktivní aktualizace s mnoha hovory (jak předpokládá OP), znamená to, že se do protokolu zapisuje mnoho jen abyste mohli používat MERGE.



  1. Jak vrátit seznam podporovaných jazyků v Oracle

  2. Exportujte sadu výsledků uložených procedur do Excelu v SSMS

  3. Otázky, které je třeba si položit před spuštěním databáze

  4. Vysvětlení velikosti úložiště „datetimeoffset“ na serveru SQL