簡體   English   中英

更新並發連接上的活動時間

[英]Update activity time on concurrent connections

我有一個api,在對此api的每個請求中,我都保存/更新了用戶活動。

但是問題是,當同一用戶有5個並發連接到api時,我得到了:

違反PRIMARY KEY約束“ PK_user_act”。 無法在對象'us​​er_activity中插入重復的密鑰

重復的鍵值為(2015-06-11,76146,1)。 該語句已終止。*

我有這個SQL:

if not exists (select 1 from user_activity where user_id = @UserNr and stat_date = CAST(GETUTCDATE() AS DATE))
   insert into user_activity(user_id, stat_date, start_date, end_date)
VALUES
(@UserNr, GETUTCDATE(), GETUTCDATE(), GETUTCDATE())
ELSE
   UPDATE user_activity set end_date = GETUTCDATE() where user_id = @UserNr and stat_date = CAST(GETUTCDATE() AS DATE)

我使用ADO.NET和SP來更新用戶活動。 我認為此sql在同一時間運行,並且保存了第一個請求,其他4個收到此錯誤。

我該怎么做才能解決此問題?

更新:為此,我們使用Azure SQL v12。 (我們每天有1-1,5 m連接到此api)

你真幸運! Azure SQL使用支持MERGE SQL Server:

MERGE User_Activity AS target
USING (SELECT @UserNr, GETUTCDATE()) AS source (userNr, rightNow)
      ON (target.userId = source.userNr)
WHEN MATCHED THEN 
     UPDATE SET end_date = source.rightNow
WHEN NOT MATCHED THEN
     INSERT (user_id, stat_date, start_date, end_date)
            VALUES (source.userNr, source.rightNow, source.rightNow, source.rightNow)

(未經測試-沒有樣本數據)


請注意,盡管這解決了此特定問題,但我同意@The Bojan-您的表具有包含多個部分的鍵。 可能應該做的就是將表更改為如下所示:

 CREATE TABLE User_Activity (userId INTEGER, lastSeenAt DATETIME2) 

...只需INSERT它(並且不使用任何事務)。 在每天結束時,您可以輕松地將所有記錄匯總到當前表中,然后將其清除。

考慮在SP中使用事務 ,以避免在並發執行之間混淆SQL指令,並確保IF語句的檢查每次都能獲取正確的數據以進行檢查

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM