2016-02-29 60 views
5

我相信SQL Server中的每个SELECT语句都会导致放置共享锁或键锁。但是它会在事务中放置相同类型的锁吗?共享锁还是锁可以让其他进程读取相同的记录?在SQL Server事务中为SELECT语句放置了什么样的锁

比如我有以下逻辑

Begin Trans 
-- select data that is needed for the next 2 statements 
SELECT * FROM table1 where id = 1000; -- Assuming this returns 10, 20, 30 

insert data that was read from the first query 
INSERT INTO table2 (a,b,c) VALUES(10, 20, 30); 

-- update table 3 with data found in the first query 
UPDATE table3 
SET d = 10, 
    e = 20, 
    f = 30; 

COMMIT; 

此时将我的select语句仍创建共享或钥匙锁还是会得到升级到排它锁?其他事务是否能够从表1中读取记录,或者是否所有事务都会等到我的事务被提交,然后其他人才能从中进行选择?

在一个应用程序中,它是否会将select语句移到事务之外,并在一个事务中保持插入/更新?

回答

7

一个SELECT将始终将共享锁 - 除非你使用WITH (NOLOCK)提示(当时无锁将被放置),使用READ UNCOMMITTED事务隔离级别(同一件事),或除非您特别与查询提示覆盖它如WITH (XLOCK)WITH (UPDLOCK)

共享锁允许其他读取进程也获取共享锁并读取数据 - 但它们阻止获取独占锁(用于插入,删除和更新操作)。

在这种情况下,只选择三行,将会有锁定升级(只有当单个事务获取5000个锁以上时才会发生)。

根据事务隔离级别,这些共享锁将保留不同的时间量。使用READ COMMITTED(默认级别)时,在读取数据后立即释放锁,而在REPEATABLE READSERIALIZABLE级别,锁将保留到事务提交或回退。

+0

非常感谢您提供这些有价值的信息。所以如果SQL Server对任何select语句默认使用“Read Committed”。之后没有试图将我的SELECT查询分开在事务 –

+0

@MikeA之外:不,没有任何区别 - 共享锁将会被非常短暂地获取,以便实际读取数据(仅用于防止另一个进程在读取它们时更改它们),然后再次发布它们 - 在该事务内部或外部 - 同一过程 –

+0

如果您不知道这一点:READ COMMITTED选择不会始终锁定。锁仅在未提交更改的页面上执行。您可以读取RC下的一个表,该表已由另一个事务处理为XLOCK,TABLOCK。 (我试过。) – usr