我有一个api,并且每次请求此API都会保存/更新用户活动。
但问题是,当同一个用户的api有5个并发连接时,我明白了:
违反PRIMARY KEY约束'PK_user_act'。无法在对象'user_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米的连接)
答案 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
语句的检查每次都为其检查获取正确的数据