我如何只选择已提交的行 - sql 2008

时间:2010-09-06 11:14:34

标签: sql sql-server-2008 transactions

如何选择表的所有行,它们不属于尚未提交的任何事务?

实施例: 让我们说,

表T有10行。

用户A正在使用某些查询进行交易:

INSERT INTO T (...)
SELECT ...
FROM T

// doing other queries 

现在,这里有一个棘手的部分:

如果用户A在用户A插入行并且提交了事务之间的时间内,用户B正在使用表T上的select更新系统中的列表。

我只希望SELECT用户B正在使用返回10行(表中的所有行,以后不能回滚)。如果可能的话,我该怎么做呢?

我已尝试在事务上设置isolationlevel并在查询中添加“WITH(NOLOCK)”“WITH(READUNCOMMITTED)”而没有任何运气。

查询要么返回所有11条记录,要么等待事务提交,这不是我需要的。

任何提示都很受欢迎,谢谢。

3 个答案:

答案 0 :(得分:2)

您需要使用(默认)read committed隔离级别和READPAST提示来跳过因未提交而被锁定的行(而不是被阻止等待锁被释放)

这确实依赖于INSERT取出行锁。如果它取消了页面锁定,您将回到被阻止状态。示例如下

连接1

IF OBJECT_ID('test_readpast') IS NULL
BEGIN
   CREATE TABLE test_readpast(i INT PRIMARY KEY CLUSTERED)
   INSERT INTO test_readpast VALUES (1)
END

BEGIN TRAN
      INSERT INTO test_readpast 
      WITH(ROWLOCK) 
      --WITH(PAGLOCK)
      VALUES (2)
   SELECT * FROM sys.dm_tran_locks WHERE request_session_id=@@SPID
   WAITFOR DELAY '00:01';
ROLLBACK

连接2

SELECT i
FROM test_readpast WITH (readpast)

答案 1 :(得分:2)

Snapshot isolation

无论是我还是早期回答的三个人都误读/误解了你的问题,所以我给出了一个链接,以便你自己确定。

答案 2 :(得分:1)

实际上,read uncommittednolock是相同的。它们意味着你可以看到尚未提交的行。

如果以默认隔离级别read committed运行,则不会看到尚未提交的新行。这应该在默认情况下有效,但如果您想确定,请在选择前添加set transaction isolation level read committed