定时器控制的数据库操作死锁

时间:2015-09-02 00:48:34

标签: c# sql-server-2005 timer

我有3个相同的程序(使用topshelf制作),作为3个不同部门的3个独立服务运行。当它们运行时,它们使用定时器继续访问数据库 - 主要是为了继续发送Alive信号或清除旧日志。最近我被要求只为其中一个部门添加额外的计时器

 Random r = new Random();   //to avoid possible deadlock we save the timestamp on random time
        int hourly =  1000 * 60 * 60;     //this is an hour



       Timer TimerItem = new Timer(TimerCallBack, null, 0, r.Next(20000, 25000));  //alive timer
       Timer purgeLogs = new Timer(TimerPurgeLogs, null,0,hourly);    //purge logs timer
       if (selDep == "planners")
       {
           Timer UpdatePlannes = new Timer(TimerUpdatePlanners, null, 0, r.Next(50000,60000));    //planners update
       }



    private static void TimerUpdatePlanners (Object o)
    {
        string conn = System.Configuration.ConfigurationManager.ConnectionStrings["Microsoft.Rtc.Collaboration.Sample.Properties.Settings.lynccallrosterConnectionString"].ToString();
        if (selDep == "planners") //Only for planners - auto turn the forwading on for everyone except the current person
        {
            string updateCommand = "update employees set on_call = 1 where Department ='Planners' and gkey <> (Select gkey from currently_on_call where Department ='Planners')";
            using (SqlConnection updatePlanners = new SqlConnection(conn))
            {
                SqlCommand executeUpdate = new SqlCommand(updateCommand, updatePlanners);
                try
                {
                    updatePlanners.Open();
                    executeUpdate.ExecuteNonQuery();
                    updatePlanners.Close();
                }
                catch { }
            }
        }

不幸的是,在我完成此操作之后,它导致了其他尝试读取同一数据库的程序出现问题,因为它以某种方式使数据库死锁(SQL 2005)。

我无法在这里看到死锁的原因:定时器每50-60秒执行一次,命令执行持续几毫秒,但似乎连接始终保持打开状态 - 在活动监视器中我可以看到十几个更新命令,这些命令会阻塞数据流量。

有趣的是,这个问题只发生在程序作为服务运行时 - topsehlf允许将服务作为控制台应用程序运行,当它在此模式下运行时,我看不到任何死锁或不必要的更新命令在队列中等待。

我做错了什么?

编辑:我已按照建议尝试在try-catch中添加Dispose()方法

  try
                {
                    updatePlanners.Open();
                    executeUpdate.ExecuteNonQuery();
                    updatePlanners.Close();

                }
                catch { }
                finally
                {
                    executeUpdate.Dispose();
                    updatePlanners.Dispose();
                }

但这仍然无法解决死锁问题。

EDIT2:我想通过在计时器启动时添加延迟,使用try-and-error方法解决了它:

Timer UpdatePlanners = new Timer(TimerUpdatePlanners, null, r.Next(10000, 20000), r.Next(10000, 20000));

为什么有这么多的UPDATE产生仍然让我感到困惑,但至少现在它们并没有相互死锁,因为每一个都会在服务启动/计时器滴答的不同时间产生。

0 个答案:

没有答案