使用 MySQL、ASP.NET 和 Entityframework 实现原子计数器



我正在使用MySQL和Entity Framework开发 ASP.NET/C#的Web应用程序。我想使用一些计数器列,这些列会通过增加其值 +1 来经常更新。 我有一个计数器列所在的产品表。我有两个问题:

1) 我应该使用第二张桌子作为柜台吗?- 主产品表将被频繁读取,如果我非常频繁地更新该行,这可能会损害性能,因为每次更新计数器时该行都会被锁定(我使用 InnoDB)

2)使用MySQL和实体框架在行上增加+1的最佳方法是什么。 我不介意计数器将是 100% 准确的,所以如果有一些更新冲突,我可以捕获它们,但我可以在没有更新的情况下通过。我假设大多数更新将快速完成并包含在更新中。

正在添加一些代码,我正在使用这些代码来实现这一点,通过使用静态变量来防止频繁写入数据库。

法典:

if (Global.DataCounters != null)
    {
        if (Global.DataCounters.ContainsKey(id))
        {
            int new_value = ++Global.DataCounters[id];
            Global.DataCounters.Remove(id);
            Global.DataCounters.Add(id, new_value);
            // check datatime
            if ((DateTime.Now - Global.LastFlushed).Minutes > 10)
            {
                // update counter in db and reset data
                Global.LastFlushed = DateTime.Now;
            }
        }
        else
        {
            // first time view of a device, set to zero views
            Global.DataCounters.Add(id, 1);
        }
    }
    else
    {
        Global.DataCounters = new Dictionary<int, int>();
    }

Global.asax:

public static Dictionary<int, int> DataCounters = new Dictionary<int,int>();
public static DateTime LastFlushed;
void Application_Start(object sender, EventArgs e)
{
    LastFlushed = DateTime.Now;
    RegisterRoutes(System.Web.Routing.RouteTable.Routes);
}

你认为这是一个很好的实现吗?

谢谢

计数器的第二个表仅在重要产品表读取(例如 50%)不需要计数器信息时有用>。否则,您将始终连接两个表,从而使读取成本高昂。

基于 MySQL 文档:对于更新计数器,如果您的 WHERE 条件使用唯一索引来搜索唯一行(要更新),则只会采用行级锁定(并且不会采用间隙锁定)。这将是适合您的案例的最佳方案(假设产品 ID 可以用作唯一索引)。我建议使用实体 SQL 来触发 Update 语句(或调用会执行相同操作的 SP)。

如果您只想使用实体术语(没有 EntitySQL 或 SP),则不要为此特定操作使用事务范围 - 这样,选择获取产品实体不会锁定,SaveChanges将是单个更新语句递增计数器。当然,在事务之外使用两个语句意味着更新可能会失败(假设您有一些可用于乐观并发检查的时间戳列),但您已指示它是可以接受的。

最后,如果在增加计数器时事务是不可避免的,请尝试缩短它们并尝试使用较低的隔离级别,例如 Read Committed

相关内容

  • 没有找到相关文章

最新更新