6

我使用 WITH (ROWLOCK) 更新了表的一行,但是通过执行“sp_lock”,我可以看到整个表都被锁定了。所以,在事务提交之前,其他事务不能更新表的其他行。为什么“WITH(ROWLOCK)”不生效?

我将以下查询与行锁一起使用:

DELETE FROM DefDatabaseSession  WITH (ROWLOCK) WHERE ProcessName='test';

在同一时间从对同一表中的不同行运行相同删除操作的任何其他事务中,我得到了异常

[SQLServer JDBC Driver][SQLServer]Lock request time out period exceeded.; 嵌套异常是 java.sql.SQLException: [newscale][SQLServer JDBC Driver][SQLServer]Lock request time out period exceeded.: com.newscale.bfw.udkernel.kernel.UdKernelException: udconfig.defdbsession.delete; SQL [DELETE FROM DefDatabaseSession WHERE ProcessName = ?] 的未分类 SQLException;SQL状态[HY000];错误代码[1222];[newscale][SQLServer JDBC Driver][SQLServer]Lock request time out period exceeded.; 嵌套异常是 java.sql.SQLException: [newscale][SQLServer JDBC Driver][SQLServer]Lock request time out period exceeded。

4

2 回答 2

2

The reason here is that optimizer is ignoring your row lock hint [WITH (ROWLOCK) provides a query hint to the optimizer]. This will happen in situations where you're hitting a very large number of rows , in such scenarios optimizer find it more feasible to heap scan on your table and hence obtain table lock.

For a detailed discussion you can go to this link: http://social.msdn.microsoft.com/Forums/sqlserver/en-US/60238304-04e8-4f98-84d1-3ddf1ed786a9/why-the-entire-table-is-locked-while-with-rowlock-is-used-in-a-update-statement

于 2013-08-04T13:19:32.230 回答
0

我的猜测是你没有索引ProcessName,所以查询必须进行全表扫描,因此所有行都被读取(并且可能是删除的候选者),所以锁定整个表比锁定每一行更有效.

尝试定义一个索引:

CREATE INDEX DefDatabaseSession_ProcessName ON DefDatabaseSession(ProcessName);

你可以通过解释找出查询计划:

EXPLAIN DELETE FROM DefDatabaseSession  WITH (ROWLOCK) WHERE ProcessName='test';
于 2013-08-04T14:09:40.600 回答