Sqlserver
 sql >> Baza danych >  >> RDS >> Sqlserver

Czy w tsql wstawka z instrukcją Select jest bezpieczna pod względem współbieżności?

Jak pisze Paweł:Nie, to nie jest bezpieczne , dla którego chciałbym dodać dowody empiryczne:Utwórz tabelę Table_1 z jednym polem ID i jeden rekord o wartości 0 . Następnie wykonaj następujący kod jednocześnie w dwóch oknach zapytań 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

Następnie wykonaj

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

Na moim serwerze SQL Server 2008 jeden identyfikator (662 ) został utworzony dwukrotnie. Tak więc domyślny poziom izolacji stosowany do pojedynczych instrukcji to nie wystarczy.

EDYCJA:Oczywiście, zawijanie INSERT z BEGIN TRANSACTION i COMMIT nie naprawi tego, ponieważ domyślny poziom izolacji dla transakcji to nadal READ COMMITTED , co nie jest wystarczające. Pamiętaj, że ustawienie poziomu izolacji transakcji na REPEATABLE READ jest również niewystarczający. Jedyny sposób na uczynienie powyższego kodu bezpiecznym jest dodać

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

na górze. To jednak od czasu do czasu powodowało impas w moich testach.

EDYCJA:Jedyne rozwiązanie, które znalazłem, które jest bezpieczne i nie powoduje zakleszczeń (przynajmniej w moich testach) jest jawne zablokowanie wyłącznie tabeli (domyślny poziom izolacji transakcji jest tutaj wystarczający). Uważaj jednak; to rozwiązanie może zabić wydajność:

...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. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Odpowiednik C# typów danych SQL Server

  2. Jak mogę ogólnie posortować kolumnę „Numer wersji” za pomocą zapytania SQL Server?

  3. Jak znaleźć nazwy kolumn dla wszystkich tabel we wszystkich bazach danych w SQL Server

  4. SQL Server i luki w zabezpieczeniach Spectre/Meltdown

  5. Jak ręcznie wstawić wartość w kolumnie tożsamości w tabeli SQL Server — samouczek SQL Server / T-SQL, część 41