【问题标题】:Good idea to use NOLOCK to work around a query/update scenario?使用 NOLOCK 解决查询/更新方案的好主意?
【发布时间】:2011-03-21 22:47:17
【问题描述】:

我正在从数据库中提取记录,将其内容发布到事务性 MSMQ 队列,然后更新该行以表明它已发布。 Enqueing-and-Updating 发生在 TransactionScope 中,它本身位于遍历所有记录的 DataReader 读取循环内。即:读取发生在TransactionScope 的外部。像这样的:

SqlConnection conn = new SqlConnection(ConnectionString);
conn.Open();

SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = "GetUnpublishedEvents";
cmd.CommandType = System.Data.CommandType.StoredProcedure;

SqlDataReader reader = cmd.ExecuteReader(System.Data.CommandBehavior.CloseConnection
                                       | System.Data.CommandBehavior.SingleResult);

while (reader.Read())
   using (TransactionScope scope = new TransactionScope())
   {
      string ID = reader.GetString(0);
      string data = reader.GetString(1);

      SqlConnection updateConn = new SqlConnection(ConnectionString);
      updateConn.Open();
      SqlCommand updateCommand = updateConn.CreateCommand();
      updateCommand.CommandText = "SetEventAsPublished";
      updateCommand.CommandType = System.Data.CommandType.StoredProcedure;
      updateCommand.Parameters.Add(new SqlParameter("@ID", ID));

      updateCommand.ExecuteNonQuery();
      updateConn.Close();

      Message msg = new Message(data);
      RaiseMessageArrived(msg);
      scope.Complete();
   }

   reader.Close();

在我修改GetUnpublishedEvents 以使用NOLOCK 之前,存储过程SetEventAsPublished 曾经因超时异常而失败。我的问题是:这是个好主意吗?超时异常是否暗示我应该以其他方式执行此操作?

我知道NOLOCK 在 SQL Server 中等同于READUNCOMMITTED。不过,我不太担心在此应用程序中读取未提交的数据(它一开始并没有插入事务中)。

编辑:

存储过程都很简单。 GetUnpublishedEvents 只是:

SELECT id, data
FROM eventsTable WITH (NOLOCK)
WHERE data IS NOT NULL
AND published IS NULL;

SetEventAsPublished 是:

UPDATE eventsTable
SET published = GETDATE()
WHERE ID = @ID;

【问题讨论】:

    标签: .net tsql transactionscope


    【解决方案1】:

    您要查询表中的行,然后在同一个事务中更新它们?只要那是唯一的机会(即使有其他人参加了一个新的未发布活动,它也不应该影响到你)),我认为这样做没有问题。

    基本上,您正在执行与 ReaderWriterLock 等效的 SQL。它针对读取进行了优化,但可以提升以允许在同一范围内进行写入。

    只有一个评论,我认为第二个连接是不必要的。这可能是您超时的原因,因为它正在升级您的事务以使用 DTC(单个事务中的两个连接)。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-11-09
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多