更新并发连接的活动时间

时间:2015-06-11 08:10:47

标签: c# sql asp.net sql-server azure

我有一个api,并且每次请求此API都会保存/更新用户活动。

但问题是,当同一个用户的api有5个并发连接时,我明白了:

  

违反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。 (这个api /天有1-1.5米的连接)

2 个答案:

答案 0 :(得分:1)

你好运! Azure SQL使用SQL Server which supports MERGE

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到它(并且不使用任何交易)。在每天结束时,您可以轻松地将所有记录汇总到当前表中,然后将其清除。

答案 1 :(得分:0)

请考虑在SP中使用Transactions,以避免在并发执行之间混淆SQL指令,并确保来自IF语句的检查每次都为其检查获取正确的数据