Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Trong tsql, một câu lệnh Chèn với một câu lệnh Chọn có an toàn về mặt đồng thời không?

Như Paul viết: Không, nó không an toàn , mà tôi muốn thêm bằng chứng thực nghiệm:Tạo bảng Table_1 với một trường ID và một bản ghi có giá trị 0 . Sau đó, thực thi mã sau đồng thời trong hai cửa sổ truy vấn của 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

Sau đó thực thi

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

Trên SQL Server 2008 của tôi, một ID (662 ) đã được tạo hai lần. Do đó, mức cách ly mặc định được áp dụng cho các câu lệnh đơn lẻ là không đủ.

CHỈNH SỬA:Rõ ràng, gói INSERT với BEGIN TRANSACTIONCOMMIT sẽ không sửa được, vì mức cô lập mặc định cho các giao dịch vẫn là READ COMMITTED , mà là không đủ. Lưu ý rằng đặt mức cô lập giao dịch thành REPEATABLE READ cũng không đủ. Cách duy nhất để làm cho mã trên an toàn là thêm

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

ở trên cùng. Tuy nhiên, điều này đã gây ra bế tắc thỉnh thoảng trong các thử nghiệm của tôi.

CHỈNH SỬA:Giải pháp duy nhất tôi tìm thấy là an toàn không tạo ra deadlock (ít nhất là trong các thử nghiệm của tôi) là để khóa bảng một cách rõ ràng (mức cách ly giao dịch mặc định là đủ ở đây). Hãy cẩn thận mặc dù; giải pháp này có thể giết chết hiệu suất:

...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. Sử dụng cột thứ tự sắp xếp trong bảng cơ sở dữ liệu

  2. Cài đặt SQL Server 2016

  3. MSDTC trên máy chủ 'máy chủ không khả dụng'

  4. SQL Server 2008 - sắp xếp theo chuỗi với số

  5. Hiệu suất của hàm COUNT SQL