2010-09-06 56 views
1

如何爲表選擇所有行,它們不是尚未提交的任何事務的一部分?如何僅選擇已提交的行 - sql2008

例子: 比方說,

表T有10行。

用戶A與一些疑問做一個交易:

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

// doing other queries 

現在,這裏到了棘手的部分:

如果用戶B,在用戶之間插入的行和交易時間被更新了系統中的一個列表,並在表T上進行了選擇。

我只希望SELECT用戶B正在使用返回的10行(表中的所有行,不能以後回滾)。如果可能,我該如何做到這一點?

我已經嘗試在事務上設置isolationlevel,並在沒有任何運氣的情況下向查詢中添加「WITH(NOLOCK)」「WITH(READUNCOMMITTED)」。

該查詢要麼返回所有11條記錄,要麼等待事務提交,這不是我所需要的。

任何提示都非常appriciated,謝謝。

回答

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 [email protected]@SPID 
    WAITFOR DELAY '00:01'; 
ROLLBACK 

連接2

SELECT i 
FROM test_readpast WITH (readpast) 
+0

READPAST還會跳過與當前正在插入的行位於同一頁面的已提交行嗎? – Andomar 2010-09-06 11:33:12

+0

@Andomar - No實際上「READPAST鎖提示僅適用於在READ COMMITTED隔離操作的事務,並且只讀取過去的行級鎖,僅適用於SELECT語句。」但OP仍然可以被我假設的頁面鎖定阻止。也許快照隔離會更合適。 – 2010-09-06 11:52:45

+0

當我包含WITH(READPAST)時,我終於得到了10行,正如我所要求的。沒有它,只有使用讀提交,我的選擇查詢從未返回。也許我錯了。 – radbyx 2010-09-06 11:56:53

1

其實,read uncommittednolock是一樣的。它們意味着你可以看到尚未提交的行。

如果您在默認隔離級別read committed下運行,您將看不到未提交的新行。這應該默認工作,但如果您想確定,請以set transaction isolation level read committed爲前綴。

2

Snapshot isolation

我或者三個早期回答過的人誤解/曲解了你的問題,所以我給出了一個鏈接,以便你自己判斷。

+0

我認爲我的解釋與你的相似。關於未被阻止等待其他交易提交的部分似乎已被錯過。 – 2010-09-06 11:59:25