Khóa TẠO BẢNG


19

Trong một ứng dụng khác, tôi bị tấn công bởi thiết kế xấu: nhiều luồng thực thi EnsureDatabaseSchemaExists()đồng thời một phương thức, trông cơ bản như thế này:

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'MyTable') AND type = N'U') BEGIN

    CREATE TABLE MyTable ( ... );

END

Tuy nhiên, ngay cả khi được thực hiện trong giao dịch SERIALIZABLE, mã này dường như không an toàn cho luồng (tức là mã song song cố gắng tạo bảng nhiều lần). Có bất kỳ cơ hội nào để buộc câu lệnh SELECT thu được một khóa để ngăn chặn một luồng khác thực hiện cùng một câu lệnh SELECT không?

Có một mô hình tốt hơn cho các phương thức đa luồng-SureSchemaExists () không?

Câu trả lời:


18

Tốt nhất bạn nên sử dụng một giao dịch có chứa rõ ràng và có được một khóa độc quyền tùy chỉnh để bảo vệ toàn bộ hoạt động ( SELECTCREATE TABLE) bằng cách sử dụng sp_getapplock . Các đối tượng hệ thống không tôn trọng các yêu cầu mức cô lập và sử dụng các khóa giống như bảng người dùng, theo thiết kế.

Điều kiện chạy đua trong mã gốc là nhiều luồng có thể kết luận bảng không tồn tại trước khi bất kỳ luồng nào đi xa như CREATE TABLEcâu lệnh.


6
+1 chỉ cần đảm bảo rằng applock kết thúc kiểm tra CHỌN . Nếu không, bạn sẽ giới thiệu bế tắc. Lý tưởng nhất là người ta sẽ khóa ứng dụng ở chế độ S, kiểm tra, nâng cấp lên X, nhưng điều đó thật khó khăn (phải nói là ít nhất ...). Tùy chọn an toàn nhất là có được X, sau đó thực hiện toàn bộ triển khai lược đồ DB. Nó phải là một op hiếm (ví dụ: khi khởi động ứng dụng) vì vậy khóa X không quan trọng lắm.
Remus Rusanu

12

Đề nghị của tôi sẽ là cố gắng thử / bắt tốt nhất. Xử lý trường hợp trùng lặp một cách rõ ràng, nếu thích hợp, ví dụ. đừng để ý đến nó...

Câu hỏi thực sự: tại sao DDL chạy theo yêu cầu, từ nhiều hệ số? Thông thường việc nâng cấp và di chuyển là một vấn đề nghiêm trọng, được xử lý trong các cửa sổ thời gian dành riêng ... Bạn không muốn việc di chuyển của mình (mã đầu tiên?) Bất ngờ, một số bước cập nhật có thể mất hàng giờ trên một bảng lớn (kích thước của hoạt động -data ...)


3
Mã này là một số loại DatabaseLogger tạo các bảng theo yêu cầu. Không di cư, không kinh doanh buồn cười. Tuy nhiên, bạn hoàn toàn đúng. Tôi sẽ cấu trúc lại mã một cách thích hợp.
DR

4
Cũng xem xét rằng việc triển khai / thiết lập là hoàn toàn OK để chạy trên bối cảnh đặc quyền nâng cao (ví dụ: bởi quản trị viên), nhưng ops bình thường thì không. Hiện tại bạn đang yêu cầu CREATE TABLEtài trợ cho các op bình thường ...
Remus Rusanu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.