【问题标题】:xml Column update and Locking in Sql ServerSql Server 中的 xml 列更新和锁定
【发布时间】:2009-11-09 17:44:09
【问题描述】:

我有一些windwos 服务。他们从 Sql server 获取 xml 列并对其进行操作和更新。

服务 A- 获取 XML
服务 B- 获取 XML
服务 A - 更新 XML(它将丢失)
服务 B - 更新 XML

我必须锁定行并使用下一个代码:

SqlCommand cmdUpdate = new SqlCommand();
            cmdUpdate.CommandText = "select MyXML from MyTable with(holdlock,rowlock) where id=@id";
            cmdUpdate.Parameters.AddWithValue("@id", id);

        using (SqlConnection conn = Helper.GetConnection())
        {
            cmdUpdate.Connection = conn;
            SqlTransaction ts = conn.BeginTransaction();
            cmdUpdate.Transaction = ts;
            XElement elem = XElement.Parse(cmdUpdate.ExecuteScalar().ToString());
            UpdateXElement(elem);
            cmdUpdate.Parameters.Clear();
            cmdUpdate.CommandText = "update MyTable set MyXML=@xml where id=@id";
            cmdUpdate.Parameters.AddWithValue("@id", id);
            cmdUpdate.Parameters.AddWithValue("@xml", elem.ToString());

            cmdUpdate.ExecuteNonQuery();
            ts.Commit();
        }
    }`

然后发生死锁。

你有更好的主意来解决这个问题吗?

谢谢

【问题讨论】:

    标签: sql-server xml locking deadlock


    【解决方案1】:

    您描述的场景不是死锁。这是一个锁争用,换句话说,就是锁的用途:

    1. 服务 A- 获取 XML - Service A locks XML
    2. 服务 B- 获取 XML - Services B places lock request which waits for service A to release the lock
    3. 服务 A - 更新 XML(它将丢失)- Service A should commit or rollback the transaction to release the lock.
    4. 服务 B - 更新 XML - Service B acquires the lock on the XML and updates it

    Service B 将在步骤23 之间冻结。

    这意味着您应该尽快执行这些步骤。

    更新:

    您使用HOLDLOCK 锁定事务中的行。

    HOLDLOCK 放置的共享锁与另一个共享锁兼容,但与UPDATE 放置的更新锁不兼容。

    会发生什么:

    1. Service Arow 1 上放置共享锁
      • Service Brow 1 上放置一个共享锁
      • Service A 尝试在row 1 上放置更新锁,这与Service B 在步骤2 上放置的共享锁不兼容。 Service A 进入等待状态(同时仍持有放置在步骤 1 上的共享锁)。
      • Service B 尝试在row 1 上放置更新锁,这与Service A 在步骤1 上放置的共享锁不兼容。 Service B 进入等待状态。 死锁

    这里没有必要在SELECT 子句中放置共享锁。您应该将UPDLOCK 放在SELECT 子句中。这将使事务锁完全不兼容,任何一个事务都必须等待其他事务完成才能获取任何锁。

    在这种情况下,死锁是不可能的。

    【讨论】:

    • 是的,但有时我会收到“事务(进程 ID 108)在锁定资源上与另一个进程死锁,并已被选为死锁受害者。重新运行事务。”例外。我的代码是负责任的(因为锁)吗?在这种情况下如何防止死锁?谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多