SQL Server锁定机制令人生畏

时间:2015-02-07 03:37:44

标签: sql-server

在连接到2014 DB的SQLServer 2014 Management Studio中打开2个窗口。

在第一个窗口中:

SELECT * FROM categorytypes WHERE id = 12

输出:

ID  DESCRIPTION ORDER
---------------------
12  Electronics 20 

然后:

begin tran 
UPDATE CategoryTypes SET [order] = 20 WHERE id = 12

现在转到其他窗口( Ctrl + N ):

SELECT * FROM CategoryTypes

查询将无限期执行,直到提交第一个窗口tran或roll-backed。这很好,因为ID = 12行被锁定。

SELECT * FROM CategoryTypes WHERE ID <> 12

工作正常。

SELECT * FROM CategoryTypes WHERE Description = 'MEN'

这里有问题,为什么这个查询应该无限期地执行,我们知道ID = 12有描述&#39; Electronics&#39;。

在同一个表上同时进行大量DML处理和选择操作的大型应用程序中,这种锁定机制不允许在不同的记录集上同时执行这两项操作。

在Oracle中,只要锁定(脏行)不是结果集的一部分,这种用例就可以工作。

伙计们,有什么办法可以避免这种,那种Oracle锁定机制?我不想使用NOLOCK,或将我的交易设置为READ UNCOMMITTED

感谢。

1 个答案:

答案 0 :(得分:4)

在SQL Server中,默认行为是在默认的READ_COMMITTED隔离级别中使用锁定。使用此默认锁定行为,拥有有用的索引以便仅触及所需数据尤为重要。例如,如果您1)在Description上有索引,并且2)在查询计划中使用索引来查找所需的行,则不会阻止WHERE子句中具有描述的查询。如果没有描述索引,则会产生全表扫描,并且当查询到达未提交的更改时,查询将被阻止。

如果您想避免锁定以致读者不会阻止编写者,反之亦然,您可以打开READ_COMMITTED_SNAPSHOT数据库选项。然后,SQL Server将使用行版本控制而不是锁定,以确保仅返回已提交的数据。

与使用行版本控制的其他DBMS产品一样,READ_COMMITTED_SNAPSHOT的开销高于内存中锁定。 SQL Server每行增加14个字节的额外存储空间,并且对行版本存储使用更多的tempdb。这些间接成本是否合理取决于您的工作负载所带来的并发效益。