在進行一些如發送短信、郵件的業務時,我們經常會使用一個表來存儲待發送的資料,由背景多個線程不斷的從表中讀取待發送的資料進行發送,發送完成後再将資料轉移到曆史表中,這樣保證待發送表的資料一般情況下不會太多。如待發送表結構為:
Create Table SMS(ID int not null identity(1,1),Content varchar(1024),Status int not null,CreateTime datetime);
Status 取值:0未讀取 1已讀取
這樣設計的好處是,不會因為後端有時發送過慢導緻前端接收發送消息的請求出現問題,如發送短信的業務,有時由于營運商的網關原因發送太慢,這樣前端可以先将使用者的發送請求全部放在待發送表中,由後端進行慢慢發送。
在後端發送程序一般使用
Select top 100 * From SMS Where Status=0;這樣的SQL取出未被讀取的資料。
為了提高後端發送能力,需要部署多個程序同時從待發送表中取出資料進行發送,這樣有時就會造成同一個記錄被多個程序同時取出來,并發送的情況。
今天查了一下SQL Server 的MSDN,發現可以通過先更新同時通過deleted表(就像是在觸發器中使用一樣)取出的方式,來保證每條記錄隻會被讀取一次。
declare @Rowid table(rowid int);
BEGIN
set rowcount 100; --一次讀取的行數
--先将要讀取的記錄狀态更新
update Sms set [status]= 1 output deleted.ID into @Rowid Where [status] = 0;
--讀取剛更新狀态的記錄
select * from Sms where ID in (select Rowid from @Rowid);
END