sql >> Database >  >> RDS >> Sqlserver

Selecteer / voeg een versie van een Upsert in:is er een ontwerppatroon voor hoge gelijktijdigheid?

U kunt LOCKs gebruiken om dingen SERIALISABLE te maken, maar dit vermindert gelijktijdigheid. Waarom probeert u niet eerst de algemene voorwaarde ("meestal invoegen of meestal selecteren"), gevolgd door een veilige afhandeling van de "herstelactie"? Dat wil zeggen, het "JFDI"-patroon...

Meestal INSERT's verwacht (ballenpark 70-80%+):

Probeer maar eens in te voegen. Als het mislukt, is de rij al gemaakt. U hoeft zich geen zorgen te maken over gelijktijdigheid, want de TRY/CATCH behandelt duplicaten voor u.

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

Meestal SELECTEERT:

Vergelijkbaar, maar probeer eerst gegevens te krijgen. Geen gegevens =INSERT nodig. Nogmaals, als 2 gelijktijdige oproepen proberen te INSERT omdat ze allebei ontdekten dat de rij de TRY/CATCH-handles mist.

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

De 2e lijkt zich te herhalen, maar is zeer gelijktijdig. Sloten zouden hetzelfde bereiken, maar ten koste van gelijktijdigheid...

Bewerken:

Waarom niet om SAMENVOEGEN te gebruiken...

Als u de OUTPUT-clausule gebruikt, wordt alleen geretourneerd wat is bijgewerkt. U hebt dus een dummy-UPDATE nodig om de INSERTED-tabel voor de OUTPUT-component te genereren. Als je dummy-updates moet doen met veel oproepen (zoals geïmpliceerd door OP), zijn dat veel log-schrijfacties slechts om MERGE te kunnen gebruiken.



  1. Java JDBC:dateert consequent twee vrije dagen

  2. MySQL-fout 1264:waarde buiten bereik voor kolom

  3. Optimistische gelijktijdigheid:IsConcurrencyToken en RowVersion

  4. Hoe zie ik welke tekenset een MySQL-database / tabel / kolom is?