views:

91

answers:

3

How do I select all rows for a table, their isn't part of any transaction that hasn't committed yet?

Example: Let's say,

Table T has 10 rows.

User A is doing a transaction with some queries:

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

// doing other queries 

Now, here comes the tricky part:

What if User B, in the time between User A inserted the row and the transaction was committed, was updating a list in the system with a select on Table T.

I only want that the SELECT User B is using returned the 10 rows(all rows from the table, that can't later be rolled back). How do I do this, if it's even possible?

I have tried setting the isolationlevel on the transaction and adding "WITH(NOLOCK)" "WITH(READUNCOMMITTED)" to the query without any luck.

The query either return all 11 records or it's waiting for the transaction to commit, and that's not what I need.

Any tips is much appriciated, thanks.

+1  A: 

Actually, read uncommitted and nolock are the same. They mean you get to see rows that have not been committed yet.

If you run at the default isolation level, read committed, you will not see new rows that have not been committed. This should work by default, but if you want to be sure, prefix your select with set transaction isolation level read committed.

Andomar
+2  A: 

You need to use (default) read committed isolation level and the READPAST hint to skip rows locked as they are not committed (rather than being blocked waiting for the locks to be released)

This does rely on the INSERT taking out rowlocks though. If it takes out page locks you will be back to being blocked. Example follows

Connection 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

Connection 2

SELECT i
FROM test_readpast WITH (readpast)
Martin Smith
READPAST would also skip committed rows that are on the same page as rows currently being inserted?
Andomar
@Andomar - No Actually "READPAST lock hint applies only to transactions operating at READ COMMITTED isolation and will read only past row-level locks. Applies only to the SELECT statement." but the OP could still be blocked by page locks I assume. Maybe snapshot isolation would be more appropriate.
Martin Smith
When I included WITH(READPAST) i finally got the 10 rows as I asked for. Without it, and only using read committed, my select query never returned. Maybe I test it wrong.
radbyx
@Martin Smith: I think snapshot would solve this problem, but snapshot can have a big impact (heavy tempdb usage, possibility of exceptions during an update)
Andomar
@radbyx I just tested `WITH(READPAST)` and it worked fine for me as well. I think it might rely on the insert only taking out row locks though I'd need to do a bit more testing.
Martin Smith
The SELECT User B is using in my solution, is either implemented with sql command or LINQ(or it's maybe LinQ2Entity), and I just sadly experince that LINQ maybe not even support "WITH(READPAST)" (Sql Hints). I was relying on that. So if I can't find a workaround, I don't know what to do hehe. I don't think i'm the first person stranded here ;)
radbyx
@radbyx - Have you looked into snapshot isolation?
Martin Smith
A bit, but it is begining to be a bit overwhelming for me to be honest. But I'll strongly keep it in my memory for a furture solution/option. I think now I must look at the big picture first :/ But I would like to thanks you and all the others for all the answers.
radbyx
Given the title of this question (and hence the possibility that someone in the future will read the question title and jump to the accepted answer), I think you should point out that readpast will not return any rows that are being editing (and hence locked) by another transaction.
sgmoore
+1  A: 

Snapshot isolation ?

Either I or else the three people who have answered early have misread/ misinterpreted your question, so I have given a link so you can determine for yourself.

sgmoore
I think my interpretation was similar to yours. The part about not being blocked waiting for the other transaction to commit seems to have been missed.
Martin Smith