Sql server Sql Server中的xml列更新和锁定
我有一些windwos服务。他们从SQLServer获取xml列,并对其进行操作和更新 服务A-获取XMLSql server Sql Server中的xml列更新和锁定,sql-server,xml,locking,deadlock,Sql Server,Xml,Locking,Deadlock,我有一些windwos服务。他们从SQLServer获取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";
服务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();
}
}`
然后出现死锁
你有更好的办法来解决这个问题吗
谢谢您描述的场景不是死锁。这是一个锁争用,换句话说,锁的确切用途是:
-服务A锁定XML
-服务B放置锁请求,等待服务A释放锁
-服务A应提交或回滚事务以释放锁。
-服务B获取XML上的锁并更新它
服务B
将在步骤2
和3
之间冻结
这意味着您应该尽可能快地执行这些步骤
更新:
使用HOLDLOCK
锁定事务中的行
HOLDLOCK
放置的共享锁与另一个共享锁兼容,但与update
放置的更新锁不兼容
下面是发生的情况:
服务A
将共享锁放置在第1行
将共享锁放置在服务B
第1行
尝试在服务A
上放置更新锁,该锁与行1
在步骤服务B
上放置的共享锁不兼容<代码>服务A进入等待状态(同时仍持有步骤2
1上的共享锁)
尝试在服务B
上放置更新锁,该锁与行1
在步骤服务A
上放置的共享锁不兼容<代码>服务B进入等待状态死锁1
SELECT
子句中放置共享锁。您应该将UPDLOCK
放在SELECT
子句中。这将使事务锁完全不兼容,任何一个事务在获取任何锁之前都必须等待其他事务的完成
在这个场景中,死锁是不可能的。您描述的场景不是死锁。这是一个锁争用,换句话说,锁的确切用途是:
-服务A锁定XML
-服务B放置锁请求,等待服务A释放锁
-服务A应提交或回滚事务以释放锁。
-服务B获取XML上的锁并更新它
服务B
将在步骤2
和3
之间冻结
这意味着您应该尽可能快地执行这些步骤
更新:
使用HOLDLOCK
锁定事务中的行
HOLDLOCK
放置的共享锁与另一个共享锁兼容,但与update
放置的更新锁不兼容
下面是发生的情况:
服务A
将共享锁放置在第1行
将共享锁放置在服务B
第1行
尝试在服务A
上放置更新锁,该锁与行1
在步骤服务B
上放置的共享锁不兼容<代码>服务A进入等待状态(同时仍持有步骤2
1上的共享锁)
尝试在服务B
上放置更新锁,该锁与行1
在步骤服务A
上放置的共享锁不兼容<代码>服务B进入等待状态死锁1
SELECT
子句中放置共享锁。您应该将UPDLOCK
放在SELECT
子句中。这将使事务锁完全不兼容,任何一个事务在获取任何锁之前都必须等待其他事务的完成
在这种情况下,死锁是不可能的。是的,但我有时会看到“事务(进程ID 108)在另一个进程的锁资源上被死锁,并被选为死锁受害者。请重新运行该事务。”异常。我的代码是否负责(因为锁)?在这种情况下如何防止死锁?谢谢,但我有时会看到“事务(进程ID 108)在另一个进程的锁资源上被死锁,并被选为死锁受害者。请重新运行该事务。”异常。我的代码是否负责(因为锁)?在这种情况下如何防止死锁?谢谢