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

Je v tsql vložka s příkazem Select bezpečná z hlediska souběžnosti?

Jak píše Paul:Ne, není to bezpečné , pro který bych rád přidal empirický důkaz:Vytvořte tabulku Table_1 s jedním polem ID a jeden záznam s hodnotou 0 . Poté spusťte následující kód současně ve dvou oknech dotazu Management Studio :

declare @counter int
set @counter = 0
while @counter < 1000
begin
  set @counter = @counter + 1

  INSERT INTO Table_1
    SELECT MAX(ID) + 1 FROM Table_1 

end

Poté proveďte

SELECT ID, COUNT(*) FROM Table_1 GROUP BY ID HAVING COUNT(*) > 1

Na mém serveru SQL Server 2008 je jedno ID (662 ) byl vytvořen dvakrát. Výchozí úroveň izolace aplikovaná na jednotlivé příkazy je tedy ne dostačující.

EDIT:Jasně, zalomení INSERT s BEGIN TRANSACTION a COMMIT neopraví to, protože výchozí úroveň izolace pro transakce je stále READ COMMITTED , což není dostatečné. Pamatujte, že nastavení úrovně izolace transakcí na REPEATABLE READ je také nedostatečný. Jediný způsob, jak učinit výše uvedený kód bezpečným je přidat

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

Nahoře. To však v mých testech tu a tam způsobovalo uváznutí.

EDIT:Jediné řešení, které jsem našel, je bezpečné a nevytváří uváznutí (alespoň v mých testech) je explicitně zamknout výhradně tabulku (výchozí úroveň izolace transakcí je zde dostatečná). Dejte si však pozor; toto řešení může zabíjet výkon:

...loop stuff...
    BEGIN TRANSACTION

    SELECT * FROM Table_1 WITH (TABLOCKX, HOLDLOCK) WHERE 1=0

    INSERT INTO Table_1
      SELECT MAX(ID) + 1 FROM Table_1 

    COMMIT
...loop end...


  1. Funkce LOWER() v Oracle

  2. Jak přejmenovat název sloupce nebo název tabulky v SQL Server - SQL Server / Kurz T-SQL, část 36

  3. Oracle datum mezi dotazem

  4. Jak nainstalovat SQL Server na Mac