2011-01-14 43 views
6

Tôi đang sử dụng SQL Server 2008 R2 làm cơ chế xếp hàng. Tôi thêm các mục vào bảng và dịch vụ bên ngoài đọc và xử lý các mục này. Điều này làm việc tuyệt vời, nhưng thiếu một điều - tôi cần cơ chế theo đó tôi có thể cố gắng chọn một hàng duy nhất từ ​​bảng và, nếu không có một, chặn cho đến khi có (tốt nhất là trong một khoảng thời gian cụ thể).Máy chủ SQL, sử dụng bảng dưới dạng hàng đợi

Có ai có thể tư vấn về cách tôi có thể đạt được điều này không?

+0

câu hỏi đã được hỏi nhiều lần về SO; vui lòng tìm kiếm SO –

+4

Liên kết tốt trên khu vực chung. http://rusanu.com/2010/03/26/using-tables-as-queues/ Chỉnh sửa: Không chắc chắn rằng nó trả lời câu hỏi cụ thể của bạn về việc chặn cho đến khi các mục được thêm vào hàng đợi. Ngoài ra tôi không chắc chắn tôi đã nhìn thấy câu hỏi cụ thể trước khi trên SO. –

+2

Bạn biết rằng SQL Server có * hàng đợi * thực tế, phải không? http://msdn.microsoft.com/en-us/library/ms345108(v=sql.90).aspx –

Trả lời

2

tôi cần cơ chế theo đó tôi có thể cố gắng để chọn một hàng duy nhất từ ​​bảng , và nếu không có một, cho đến khi khối có (tốt nhất là trong một thời gian cụ thể thời gian).

Bạn có thể lặp và kiểm tra hàng mới mỗi giây:

while not exists (select * from QueueTable) 
    begin 
    wait for delay '00:01' 
    end 

Disclaimer: đây không phải là mã tôi sẽ sử dụng cho một hệ thống sản xuất, nhưng nó làm những gì bạn yêu cầu.

+0

Cảm ơn. Đây là bản chất của giải pháp mà tôi đang sử dụng tại thời điểm này nhưng khi bạn đề xuất nó không thực sự là giải pháp tốt nhất. Cụ thể, tôi muốn một cái gì đó mà không liên quan đến looping - một số loại hoạt động chờ đợi mà một trong hai lần ra, hoặc là đá vào hành động của một hàng mới thêm vào bảng (thông qua một kích hoạt?) – Barguast

1

Người nhận xét trước đã đề xuất sử dụng Nhà môi giới dịch vụ có thể có câu trả lời hay nhất. Dịch vụ môi giới cho phép bạn về cơ bản chặn trong khi chờ đợi thêm đầu vào.

Nếu môi giới dịch vụ quá mức cần thiết, bạn nên xem xét một cách tiếp cận khác cho vấn đề của mình. Bạn có thể cung cấp thêm chi tiết về những gì bạn đang cố gắng làm không?

+0

Về cơ bản, tôi đang tìm kiếm cho cách tốt nhất để truyền các mục công việc giữa các dịch vụ phân tán (hiện tại trên cùng một máy nhưng, trong tương lai, chúng có thể nằm trên các máy khác nhau trên cùng một mạng LAN). Trong một số trường hợp, tôi cần cùng một mục công việc để gửi đến hai hàng đợi khác nhau, do đó lý do tôi ban đầu đã chọn để thực hiện triển khai của riêng tôi. Lời khuyên nào sẽ được hoan nghênh. Tại thời điểm này tôi đang xem xét một sự kết hợp của nhà môi giới dịch vụ, cùng với một tập hợp các thủ tục lưu trữ sẽ xử lý việc phân phối cho nhiều hàng đợi. – Barguast

+0

Nếu bản chất của các mục công việc này là không đồng bộ, bạn nên xem xét một cái gì đó như MSMQ. MSMQ có thể cung cấp thông điệp tin nhắn đáng tin cậy trên các giới hạn dịch vụ/máy, bao gồm cả những thứ như truyền lại. Nhưng nếu bạn muốn nói "bên trong" SQL Server, dịch vụ môi giới là chính xác những gì bạn đang tìm kiếm. Mỗi dịch vụ/máy sẽ lưu trữ một bản sao của SQL Server Express (hoặc tốt hơn) mà sẽ hoạt động như hàng đợi địa phương. Sau đó nó sẽ quản lý quá trình truyền tin nhắn của bạn đến các dịch vụ từ xa. Nó thậm chí quản lý các thông báo vào cuối của bạn nhận được tin nhắn. Nó hỗ trợ multicasting quá. – RMD

8

Cách duy nhất để đạt được một dequeue chặn không gộp là WAITFOR (RECEIVE). Điều này ngụ ý hàng đợi Service Broker, với tất cả các chi phí bổ sung.

Nếu bạn đang sử dụng thông thường tables as queues, bạn sẽ không thể đạt được chặn không bỏ phiếu. Bạn phải thăm dò hàng đợi bằng cách yêu cầu một hoạt động dequeue, và nếu nó không trả về gì cả, hãy ngủ và thử lại sau.

Tôi sợ rằng tôi sẽ không đồng ý với Andomar ở đây: trong khi câu trả lời của anh ấy hoạt động như một câu hỏi chung 'có bất kỳ hàng nào trong bảng không?' khi nói đến xếp hàng, do tính chất bận rộn của việc enqueue chồng lên nhau/dequeue, kiểm tra các hàng như thế này là một (gần như) đảm bảo bế tắc dưới tải. Khi nói đến việc sử dụng các bảng như hàng đợi, người ta phải luôn luôn dính vào các hoạt động enqueue/dequeue cơ bản và không thử các công cụ ưa thích.

+0

Chúng tôi sử dụng các bảng SQL thông thường làm hàng đợi, dưới tải nặng (200K +/giờ) và chưa bao giờ gặp phải bế tắc. Bản chất của cấu trúc hàng đợi hỗ trợ điều này, bạn chèn vào một đầu (tức là cuối bảng) và dequeue từ cái kia (tức là đỉnh của bảng thông qua SELECT TOP 1). Trong thực tế sử dụng thế giới, nó phức tạp hơn khi mọi thứ được giao dịch, nhưng đây là ý chính của nó – Didaxis

7

"vì SQL Server 2005 đã đưa ra mệnh đề OUTPUT, sử dụng các bảng làm hàng đợi không còn là vấn đề khó". Một bài đăng tuyệt vời về cách thực hiện điều này.

http://rusanu.com/2010/03/26/using-tables-as-queues/

+3

Đó là một bài viết tuyệt vời, mặc dù theo http://stackoverflow.com/a/940001/8479 các gợi ý khóa không phải là khá chính xác - ví dụ cần UPDLOCK – Rory

0

Hãy để tôi chia sẻ kinh nghiệm của tôi với bạn trong lĩnh vực này, bạn có thể tìm thấy nó hữu ích.

Nhóm của tôi trước tiên đã sử dụng hàng đợi giao dịch MSMQ để cung cấp các dịch vụ không đồng bộ của chúng tôi (có thể là IIS được lưu trữ hoặc WS). Vấn đề lớn nhất chúng tôi gặp phải là vấn đề MS DTC dưới tải nặng, như 100 tin nhắn/giây tải; tất cả những gì cần làm là một hoạt động cơ sở dữ liệu chậm ở đâu đó để bắt đầu gây ra ngoại lệ thời gian chờ và MS DTC sẽ đưa ngôi nhà xuống để nói (giao dịch thực sự sẽ bị mất nếu mọi thứ trở nên tồi tệ) và mặc dù chúng tôi không chắc chắn 100% gốc gây ra cho đến ngày nay, chúng tôi nghi ngờ MS DTC trong một môi trường nhóm có một số vấn đề nghiêm trọng.

Vì lý do này, chúng tôi bắt đầu xem xét các giải pháp khác nhau. Dịch vụ xe buýt cho Windows Server (phiên bản tại chỗ của Azure Service Bus) trông đầy hứa hẹn, nhưng nó không giao dịch nên không phù hợp với yêu cầu của chúng tôi.

Cuối cùng, chúng tôi đã quyết định phương pháp tiếp cận theo cách riêng của bạn, một phương pháp được chúng tôi đề xuất cho những người đã tạo Xe buýt dịch vụ Azure, vì các yêu cầu giao dịch của chúng tôi. Về cơ bản, chúng tôi đã làm theo mô hình Vai trò Công nhân Azure cho vai trò công nhân sẽ được cung cấp thông qua một số hàng đợi; một mô hình chặn bỏ phiếu.

Thành thật mà nói, điều này tốt hơn nhiều so với bất kỳ điều gì khác mà chúng tôi đã sử dụng. Mã giả cho một dịch vụ như vậy là:

hasMsg = true 

while(true) 

    if(!hasMsg) 
     sleep 

    msg = GetNextMessage 

    if(msg == null) 
     hasMsg = false 
    else 
     hasMsg = true 

    Process(msg); 

Chúng tôi thấy rằng việc sử dụng CPU thấp hơn đáng kể theo cách này (thấp hơn các dịch vụ WCF truyền thống).

Phần khó khăn của khóa học là xử lý giao dịch. Nếu bạn muốn có nhiều phiên bản dịch vụ của bạn đọc từ hàng đợi, bạn sẽ cần sử dụng read-past/updlock trong sql của bạn, và cũng có dịch vụ .net của bạn tham gia vào các giao dịch theo cách sẽ cuộn trở lại nên dịch vụ không thành công. trong trường hợp này, bạn sẽ muốn đi với hàng đợi thử lại/độc như bảng ngoài hàng đợi thông thường của bạn.

+0

Đây có phải là mã giả cho lớp ứng dụng của bạn không? Làm thế nào để bạn thực hiện GetNextMessage để nhiều tác phẩm có thể hoạt động trên các thư riêng biệt cùng một lúc? Sử dụng khóa hàng?Mọi chi tiết khác sẽ được đánh giá cao. –

+0

@David, đoạn cuối cùng trong ví dụ của tôi giải thích cách thực hiện điều này. Tuy nhiên, nó có liên quan nhiều hơn một chút, vì các hoạt động xếp hàng thực tế cần phải được xử lý đặc biệt (tức là, nếu giao dịch cần được khôi phục, chúng ta vẫn cần thông báo chuyển đến hàng đợi thử lại/độc). GetNextMessage là tầm thường, công việc đang nhận được SQL để làm những gì chúng ta muốn ở đây. Tóm lại, một lớp khách hàng xếp hàng đã được sử dụng để xử lý việc tham gia vào giao dịch và một CLR SQL đã được sử dụng ở phía SQL cho phép tranh thủ trong giao dịch .NET. – Didaxis

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