2011-11-01 35 views
5

Tôi muốn:SQL Chọn Rows từ một bảng và cập nhật các hàng cùng

  1. Chọn N hàng từ một bảng để chế biến nơi flag = 0
  2. làm một số công việc trên một bảng thứ hai sử dụng các giá trị từ những N hàng
  3. cập nhật những dòng N và thiết lập flag = 1

tôi có các quy trình song song thực hiện công việc này cùng với nhau, và tôi muốn đảm bảo rằng tất cả bắt đầu làm việc trên các hàng độc đáo. Làm cách nào để tôi đảm bảo điều đó?

Trả lời

5

Tôi cho rằng bạn đang chạy trên SQL Server (vì thẻ), nếu không thì câu trả lời của tôi không áp dụng được. Khóa một mình là không đủ. Nếu bạn sử dụng máy chủ SqL khóa bản ghi cơ sở dữ liệu sẽ chặn các quá trình khác cố gắng truy cập hàng bị khóa và có hiệu lực bạn sẽ chỉ xử lý một hàng tại một thời điểm. Giải pháp cho bạn là kết hợp khóa hàng với gợi ý READPAST để các hàng bị khóa bởi người khác sẽ bị bỏ qua. Đây là những gì mỗi quá trình nên làm:

  1. chọn tiếp theo hàng mở khóa cho việc xử lý và khóa nó
  2. làm việc
  3. cập nhật hàng và kết thúc giao dịch

select top 1 id, ... from TheTable with (updlock, readpast) where flag = 0

//do the work now

update TheTable set flag = 1 where id=<previously retrieved id>

Điều tốt đẹp ở đây là hoạt động chọn hàng được mở khóa tiếp theo và khóa nó là nguyên tử để đảm bảo rằng không ai khác có thể chọn cùng một hàng.

+0

gợi ý READPAST thực hiện thủ thuật, một bài viết hay http://www.mssqltips.com/sqlservertip/1257/processing-data-queues-in-sql-server-with-readpast-and-updlock/ – newbie

+0

Với SQL 2008 , bạn có thể sử dụng mệnh đề OUTPUT với READPAST HINT trong truy vấn để kết hợp hoạt động xếp hàng vào một câu lệnh đơn.http: //www.sqlservercentral.com/articles/Queue+processing/69653/ – newbie

+0

@newbie Có, bạn có thể sử dụng đầu ra để khóa và truy xuất tin nhắn và đánh dấu nó được xử lý trong một truy vấn duy nhất. Nhưng tôi đã so sánh hiệu suất xử lý tin nhắn đơn và không có lợi ích nào so với hai truy vấn (chọn trước và sau đó cập nhật). Trên thực tế, thông lượng đa luồng thấp hơn một chút khi sử dụng truy vấn OUTPUT. Có lẽ trong xử lý hàng loạt các khoản đầu ra sẽ nhanh hơn, nhưng đối với tin nhắn đơn nó không. – nightwatch

0

Một cách là có một chương trình chính phân phát các phân đoạn cho các chuỗi con.

Cách khác là khóa bảng, nhận CEIL(N/#processes) hàng có cờ = 0, cập nhật cờ lên 2, sau đó nhả khóa. Sau đó, quá trình tiếp theo sẽ tiếp tục vì nó có khóa, và vì flag = 2 nó sẽ không nhận được những hàng đó.

Bạn có hai cách để khóa bảng - bạn có thể khóa toàn bộ hoặc thực hiện SELECT ... CẬP NHẬT với giới hạn (để không nhận được quá nhiều hàng). Xem: SELECT FOR UPDATE with SQL Server

Thậm chí tốt hơn việc đặt cờ thành 2 là đặt cờ thành process_id. Sau đó, tất cả những gì bạn phải làm là cập nhật tất cả các hàng để phân phối các số, sau đó để cho quá trình này hoạt động, mỗi lần chỉ kiểm tra các hàng của riêng chúng.

Các vấn đề liên quan