增加的DB字段

时间:2009-08-13 04:00:10

标签: sql tsql transactions

假设我在网站上有一篇文章,我想跟踪文章的观看次数。在Articles表中,有PK ID - int,Name - nvarchar(50)和ViewCount - int。每次查看页面时,我都会增加ViewCount字段。更新字段时我担心会发生冲突。我可以在sproc中运行它,例如:

CREATE PROCEDURE IncrementView
(
    @ArticleID int
)
as

BEGIN TRANSACTION

UPDATE Article set ViewCount = ViewCount + 1 where ID = @ArticleID

IF @@ERROR <> 0
BEGIN
    -- Rollback the transaction
    ROLLBACK

    -- Raise an error and return
    RAISERROR ('Error Incrementing', 16, 1)
    RETURN
END

COMMIT

我担心的是,我最终会在这个模型中不计算PageViews。另一种可能的解决方案是日志类型的模型,其中我实际上将视图记录到文章中,并使用函数和视图的组合来获取有关文章的视图数量的数据。

4 个答案:

答案 0 :(得分:2)

可能更好的模型是在应用程序中每小时缓存一次视图数量,然后以批处理方式更新它们。

- 编辑:

要详细说明,一个简单的模型可能是:

  1. 对于给定页面,每个页面加载都会增加一个静态哈希映射。同样在每次加载时,检查自“上次更新”后是否已经过了足够的时间,如果是,请执行更新。

  2. 很棘手,并将基值放在asp.net缓存(http://msdn.microsoft.com/en-us/library/aa478965.aspx)中,当它超时时,[实现链接中描述的缓存删除处理程序]执行更新。设置超时一小时。

  3. 在这两种模型中,您都可以对页面的静态地图进行计数;你将更新每个视图,你也将使用它 - 以及缓存的数据库量 - 来获得当前的“实时”计数。

答案 1 :(得分:2)

数据库应该能够原子地处理单个数字增量。在可能存在冲突的情况下,应按顺序处理队列上的查询。更大的问题,如果有足够的卷将处理对同一行的所有写入。每次写入都会阻止其后面的读写操作。如果您担心,我会创建一个简单的程序,连续调用SQL更新并使用几百个并发线程运行它(增加线程直到硬件饱和)。确保尝试=最终结果。

找到一种缓存和/或执行批量更新的机制,如丝般的建议听起来像赢家。

雅各

答案 2 :(得分:0)

您无需担心SQL Server中单个更新语句中的并发性 但如果你担心有2个用户在同一个十分之一秒内敲击一张桌子,请记住,一天中有1064,000秒。对于提供文章的页面来说,听起来不像是一个问题。

答案 3 :(得分:0)

不要害怕!

此更新是单个(原子)事务 - 您无法获得“冲突”。即使对IncrementView的5,000,000次调用都在同一时刻点击数据库,它们也会以串行的方式处理,就像你使用数据库引擎一样 - 一致性。每次调用都会获得对该行的独占更新锁定(至少),因此在当前的行提交之前,后续查询都不能更新该行。

您甚至不需要使用BEGIN TRAN ... COMMIT。如果更新失败,则无论如何都无法回滚。

我没有看到任何应用缓存的需要 - 没有理由为什么此更新需要很长时间,因此应该对您的应用的性能没有影响。 [假设它的设计相对较好!]