sql - 使TSQL插入/更新即使在多线程的情况下也能正常工作

标签 sql multithreading tsql

我有一个表,用于跟踪客户使用情况。我跟踪用户每天的点击次数,因此我有一个如下表:

CustID (uniqueidentifier, not null)

UseDate (smalldatetime, not null)

NumHits (smallint, not null)

我在存储的proc中使用此SQL来为今天(如果需要)插入一行,或为今天增加计数器:
declare @today datetime
set @today = getdate()

/* Try to bump it by one if an entry for today exists */
if (
    select count(*) from CustomerUsage
    where CustID = @cust_guid and year(UseDate) = year(@today) and month(UseDate) = month(@today) and day(UseDate) = day(@today)
    ) = 0

    insert into CustomerUsage (CustID, UseDate, NumHits) values (@cust_guid, getdate(), 1)

else
    update CustomerUsage set NumHits = NumHits + 1 
    where CustID = @cust_guid and year(UseDate) = year(@today) and month(UseDate) = month(@today) and day(UseDate) = day(@today)

有一个更好的方法吗?

另外,我想移至多个Web服务器可以为同一客户调用存储的proc的环境。我认为这段代码可能容易受到多线程问题的影响。

谢谢!

最佳答案

你可以这样

declare @Today smalldatetime = dateadd(d, datediff(d, 0, getdate()), 0)
declare @Tomorrow smalldatetime = dateadd(d, 1, @Today)

insert into CustomerUsage(CustId, UseDate, NumHits )
select Data.CustID, Data.UseDate, Data.NumHits
from (select
        @cust_guid as CustID,
        getdate() as UseDate,
        0 as NumHits) as Data
where not exists (select *
                  from CustomerUsage with (updlock, serializable)
                  where
                    CustID = @cust_guid and
                    UseDate >= @Today and
                    UseDate < @Tomorrow)        


update CustomerUsage 
set NumHits = NumHits + 1 
where
  CustID = @cust_guid and
  UseDate >= @Today and
  UseDate < @Tomorrow

首先使用NumHits = 0插入一行。插入检查该CustID上是否已经存在该UseDate的行,并且仅在必要时插入。

插入之后,请始终将NumHits递增1。

这基本上与托马斯非合并答案相同,但是我在更新之前进行了插入。

编辑1 向插入语句where not exists部分添加了表提示。需要serializable来防止违反主键约束,并且需要updlock来避免死锁。

关于sql - 使TSQL插入/更新即使在多线程的情况下也能正常工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5059826/

相关文章:

sql - 查询以获取每个数据库的日期时间

sql-server - 如何在 SQL 中计算 IPv6 CIDR 路由前缀?

mysql - 我如何决定何时使用右连接/左连接或内连接或者如何确定哪个表在哪一侧?

sql - 按空格和 '-' SQL Server 拆分字符串

php - SQL Join 语句收集用户的 friend 和用户的消息

java - SQL中如何判断一个表是否包含一个值?

multithreading - 如何在 Rust 中同时运行不同的线程?

c# - 如何在线程工作时停止服务(不使用 Thread.Abort)

c++ - 如何在不使用mutex、semorphore、spinLock、futex的情况下实现线程同步?

sql-server - 使用 TSQL 的按位操作,如旋转、选择性位反转