Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

В tsql безопасно ли е вмъкване с оператор Select по отношение на едновременност?

Както пише Павел:Не, не е безопасно , за което бих искал да добавя емпирични доказателства:Създайте таблица Table_1 с едно поле ID и един запис със стойност 0 . След това изпълнете следния код едновременно в два прозореца за заявка на 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

След това изпълнете

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

На моя SQL Server 2008, един идентификатор (662 ) е създаден два пъти. По този начин нивото на изолация по подразбиране, приложено към единични изрази, е не достатъчно.

РЕДАКТИРАНЕ:Ясно е, обвиване на INSERT с BEGIN TRANSACTION и COMMIT няма да го поправи, тъй като нивото на изолация по подразбиране за транзакциите все още е READ COMMITTED , което не е достатъчно. Имайте предвид, че задаване на нивото на изолация на транзакциите на REPEATABLE READ е също не е достатъчно. Единственият начин да направите горния код безопасен е да добавите

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

на върха. Това обаче от време на време предизвикваше безизходица в моите тестове.

РЕДАКТИРАНЕ:Единственото решение, което намерих, което е безопасно и не създава блокиране (поне в моите тестове) е изрично да заключи таблицата изключително (нивото на изолация на транзакциите по подразбиране е достатъчно тук). Внимавайте обаче; това решение може да убие изпълнение:

...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. Как да използвам функцията CONCAT в SQL Server 2008 R2?

  2. DBA - Как да убиете всички процеси на база данни на SQL Server

  3. Вземете началната и крайната дата на седмицата от номера на седмицата

  4. Подгответе нова виртуална машина за SQL Server 2014 CTP1

  5. SQL - Как да съхранявате и навигирате в йерархии?