【问题标题】:How long does it take for sqlserver.exe to remove the lock local database file?sqlserver.exe 需要多长时间才能删除锁定本地数据库文件?
【发布时间】:2016-11-17 06:48:15
【问题描述】:

我有一个应用程序,它会进行几次选择,然后进行一些插入。可能会这样做大约 200 次,然后断开连接并关闭所有内容(据我所知)。代码如下:

using (TransactionScope scope = new TransactionScope())
{
  using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["FrameBudgetDB"].ToString()))
  {
    conn.Open();
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = conn;
    cmd.CommandText = string.Format("SELECT TOP 1 category_id FROM businesses WHERE '{0}' LIKE CONCAT('%',description,'%')", transDescription.Replace("'", "''"));
    SqlDataReader reader = cmd.ExecuteReader();

    try
    {
      if (reader.HasRows)
      {
        while (reader.Read())
        {
          categoryId = (int)reader[0];
        }
      }
      else
      {
        categoryId = 11; // Extgra Expenses
      }
    }
    finally
    {
      reader.Close();                      
      cmd.Dispose();  
    }


    // Get Transaction Type
    int transTypeId = 0;
    cmd = new SqlCommand();
    cmd.Connection = conn;
    cmd.CommandText = string.Format("SELECT trans_type_id FROM transaction_types WHERE description = '{0}'", transType);
    reader = cmd.ExecuteReader();
    try
    {
      if (reader.HasRows)
      {
        while (reader.Read())
        {
          transTypeId = (int)reader[0];
        }
      }
    }
    finally
    {
      reader.Close();
      cmd.Dispose();
    }

    try
    {
      cmd = new SqlCommand();
      cmd.Connection = conn;
      cmd.CommandText = string.Format(
        "BEGIN " +
          "IF NOT EXISTS(SELECT * FROM transactions " +
                   "WHERE transaction_date = @TransDate " +
                   "AND trans_type_id = @TransTypeId " +
                   "AND amount = @Amount " +
                   "AND ((from_bank = 1 AND description = @TransDesc) " +
                    "OR (from_bank = 0)) " +
                   "AND(category_id = @CategoryId OR previous_category_id = @CategoryId )) " +
           "BEGIN " +
             "INSERT INTO transactions(transaction_date, description, trans_type_id, import_date, category_id, amount, from_bank) " +
             "VALUES(@TransDate, @TransDesc, @TransTypeId, @ImportDate, @CategoryId, @Amount, 1) " +
           "END " +
        "END");
      cmd.Parameters.AddWithValue("@TransDate", transDate);
      cmd.Parameters.AddWithValue("@TransDesc", transDescription);
      cmd.Parameters.AddWithValue("@TransTypeId", transTypeId);
      cmd.Parameters.AddWithValue("@Amount", amount);
      cmd.Parameters.AddWithValue("@CategoryId", categoryId);
      cmd.Parameters.AddWithValue("@ImportDate", DateTime.Now);
      rowsInserted = rowsInserted + cmd.ExecuteNonQuery();
      cmd.Dispose();
    }
    catch (Exception e)
    {
      Console.WriteLine(e.Message);
    }
    conn.Close();
    conn.Dispose();                 
  }
  scope.Complete();
  scope.Dispose();
}
}

在所有插入之后,我想通过复制并将其移动到其他地方来备份数据库,但是 sqlserver.exe 会长时间锁定文件。我试过让应用程序等待,但它似乎持有锁很长时间。

我已经构建了一个锁检查 while 循环,但如果知道它实际需要多长时间会很高兴?

【问题讨论】:

  • 为什么不使用实际的 SQL Server 备份方法进行备份?
  • 你能用 SQL Lite 做到这一点吗?

标签: c# sql-server visual-studio visual-studio-2015


【解决方案1】:

执行插入的最后一部分代码似乎有问题。

因为 SqlCommand 被放置在 try..catch 中的最后一行,如果发生异常,它可能根本不会执行。

最好在 usings 中使用单独的 SqlCommands 以确保正确处理所有内容。 这可能是连接保持打开状态的原因。 你的代码:

try
{
  cmd = new SqlCommand();
  cmd.Connection = conn;
  ...
  rowsInserted = rowsInserted + cmd.ExecuteNonQuery();
  cmd.Dispose(); // <- This line might not be executed if exception occurs in previous line
}

建议更正:

try
{
  using (SqlCommand cmd = new SqlCommand())
  {
       cmd.Connection = conn;
       ...
       rowsInserted = rowsInserted + cmd.ExecuteNonQuery();
       // Call dispose is not needed
  }
}

【讨论】:

  • 我在 catch 中添加了一个额外的 cmd.dispose。我尝试了这种方法,但它并没有更快地释放锁。我在两种配置中都对其进行了多次计时,似乎需要大约 2m 才能释放文件上的锁。所以在这一点上,我只是让代码在执行前等待几分钟。
  • 对不起,我错过了您要复制文件而不是备份的信息。然后实际上文件可能会“使用”更长的时间。在这种情况下,我建议在使用即 net stop 复制文件之前停止 sqlserver 服务,然后在复制后重新启动它。
  • 有点犹豫是否强制停止服务,以防它在我停止服务时搞砸了连接的数据库。
  • 事实上,停止服务应该导致将所有内容提交到文件中。但是为什么你不考虑进行备份 - 这是移动/备份数据库的更干净的方式。
  • 我可能会尝试停止服务。将来我会研究一些更好的备份解决方案,但目前我仍在开发和定期更改数据库结构,我一直在将数据复制回 DEV,进行更改并将更改回滚数据库中的数据仍然完好无损。基本上,只是懒惰,不想在 SQL 更新脚本中更改结构。可能我应该研究一下。
猜你喜欢
  • 1970-01-01
  • 2011-12-11
  • 1970-01-01
  • 1970-01-01
  • 2017-08-09
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 2016-01-17
相关资源
最近更新 更多