简单的选择查询是否获取锁?


14

我是SQL Server的新手,并且想了解以下非常简单的select语句是否需要任何锁。

Select * from Student;

请考虑该语句不在begin tran块内运行的情况。


1
这个问题比您想象的要复杂得多。答案取决于很多事情(会话事务隔离级别是什么?读取提交快照隔离是否已打开?扫描索引是否设置了选项来防止行锁或页面锁?)甚至在语句运行期间可能会更改(有多少个)表中是否有行?表是否已分区?)。是开始阅读的好时机。
乔恩·塞格尔

Answers:


5

是的,它的确在默认情况下读取了行上的共享锁(在要读取的聚集索引的所有页面上也都使用了意图共享锁),这样做是为了防止脏读。但是,有一些方法可以绕过此方法(SQL Server具有nolock提示)。如果该语句不在BEGIN TRAN中,则在SELECT语句运行后释放锁。

更多信息可以在这里找到:

http://msdn.microsoft.com/zh-cn/library/ms184286(v=sql.105).aspx http://www.sqlteam.com/article/introduction-to-locking-in-sql-server


此外,您还可以将事务隔离级别设置为未提交。
Zane 2013年

1
因此,如果SELECT读取十行,那么是否会保留十个共享锁,直到读取完所有十行或每行都获取并释放它们为止?
伊恩·沃伯顿

26

我想了解以下非常简单的select语句是否需要任何锁

一个常见的误解SELECT,以默认READ COMMITTED事务隔离级别运行的查询将始终使用共享锁来防止脏读。

当没有没有它们的情况下读取未提交的数据的危险时,SQL Server可以避免使用共享的行级锁(尽管仍使用较高级别的意图共享(IS)锁)。

即使共享行锁采取了(可能是因为其它并发事务已经修改了页面的行上),它们可以长期被释放之前,SELECT语句完成。

在大多数情况下,在服务器处理下一行之前,该行是“解锁的”。在某些情况下,以默认隔离级别获取的共享锁将保留在当前语句的末尾,而不是事务的末尾。

NOLOCK表提示覆盖当前隔离级别几乎总是一个坏主意

锁定是一个实现细节。SQL Server 在必要时采取锁定措施,以确保它满足当前隔离级别提供的语义保证。当然,有时需要了解为什么要使用锁,这很有用,但是尝试预测锁通常会适得其反。

SQL Server提供了多种隔离级别。选择一种可以提供您的数据使用者所需的保证和行为的方法。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.