假设我在网站上有一篇文章,我想跟踪文章的观看次数。在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。另一种可能的解决方案是日志类型的模型,其中我实际上将视图记录到文章中,并使用函数和视图的组合来获取有关文章的视图数量的数据。
答案 0 :(得分:2)
可能更好的模型是在应用程序中每小时缓存一次视图数量,然后以批处理方式更新它们。
- 编辑:
要详细说明,一个简单的模型可能是:
对于给定页面,每个页面加载都会增加一个静态哈希映射。同样在每次加载时,检查自“上次更新”后是否已经过了足够的时间,如果是,请执行更新。
很棘手,并将基值放在asp.net缓存(http://msdn.microsoft.com/en-us/library/aa478965.aspx)中,当它超时时,[实现链接中描述的缓存删除处理程序]执行更新。设置超时一小时。
在这两种模型中,您都可以对页面的静态地图进行计数;你将更新每个视图,你也将使用它 - 以及缓存的数据库量 - 来获得当前的“实时”计数。
答案 1 :(得分:2)
数据库应该能够原子地处理单个数字增量。在可能存在冲突的情况下,应按顺序处理队列上的查询。更大的问题,如果有足够的卷将处理对同一行的所有写入。每次写入都会阻止其后面的读写操作。如果您担心,我会创建一个简单的程序,连续调用SQL更新并使用几百个并发线程运行它(增加线程直到硬件饱和)。确保尝试=最终结果。
找到一种缓存和/或执行批量更新的机制,如丝般的建议听起来像赢家。
雅各
答案 2 :(得分:0)
您无需担心SQL Server中单个更新语句中的并发性 但如果你担心有2个用户在同一个十分之一秒内敲击一张桌子,请记住,一天中有1064,000秒。对于提供文章的页面来说,听起来不像是一个问题。
答案 3 :(得分:0)
不要害怕!
此更新是单个(原子)事务 - 您无法获得“冲突”。即使对IncrementView的5,000,000次调用都在同一时刻点击数据库,它们也会以串行的方式处理,就像你使用数据库引擎一样 - 一致性。每次调用都会获得对该行的独占更新锁定(至少),因此在当前的行提交之前,后续查询都不能更新该行。
您甚至不需要使用BEGIN TRAN ... COMMIT。如果更新失败,则无论如何都无法回滚。
我没有看到任何应用缓存的需要 - 没有理由为什么此更新需要很长时间,因此应该对您的应用的性能没有影响。 [假设它的设计相对较好!]