Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 829357
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 15, 20262026-05-15T03:52:13+00:00 2026-05-15T03:52:13+00:00

I know that snapshot isolation would fix this problem, but I’m wondering if NOLOCK

  • 0

I know that snapshot isolation would fix this problem, but I’m wondering if NOLOCK is safe in this specific case so that I can avoid the overhead.

I have a table that looks something like this:

drop table Data

create table Data
(
    Id BIGINT NOT NULL,
    Date BIGINT NOT NULL,
    Value BIGINT,
    constraint Cx primary key (Date, Id)
)

create nonclustered index Ix on Data (Id, Date)

There are no updates to the table, ever. Deletes can occur but they should never contend with the SELECT because they affect the other, older end of the table. Inserts are regular and page splits to the (Id, Date) index are extremely common.

I have a deadlock situation between a standard INSERT and a SELECT that looks like this:

select top 1 Date, Value from Data where Id = @p0 order by Date desc

because the INSERT acquires a lock on Cx (Date, Id; Value) and then Ix (Id, Date), but the SELECT acquires a lock on Ix (Id, Date) and then Cx (Date, Id; Value). This is because the SELECT first seeks on Ix and then joins to a seek on Cx.

Swapping the clustered and non-clustered index would break this cycle, but it is not an acceptable solution because it would introduce cycles with other (more complex) SELECTs.

If I add NOLOCK to the SELECT, can it go wrong in this case? Can it return:

  1. More than one row, even though I asked for TOP 1?
  2. No rows, even though one exists and has been committed?
  3. Worst of all, a row that doesn’t satisfy the WHERE clause?

I’ve done a lot of reading about this online, but the only reproductions of over- or under-count anomalies I’ve seen (one, two) involve a scan. This involves only seeks. Jeff Atwood has a post about using NOLOCK that generated a good discussion. I was particularly interested in a comment by Rick Townsend:

Secondly, if you read dirty data, the
risk you run is of reading the
entirely wrong row. For example, if
your select reads an index to find
your row, then the update changes the
location of the rows (e.g.: due to a
page split or an update to the
clustered index), when your select
goes to read the actual data row, it’s
either no longer there, or a different
row altogether!

Is this possible with inserts only, and no updates? If so, then I guess even my seeks on an insert-only table could be dangerous.


Update:

I’m trying to figure out how snapshot isolation works. It seems to be row-based, where transactions read the table (with no shared lock!), find the row they are interested in, and then see if they need to get an old version of the row from the version store in tempdb.

But in my case, no row will have more than one version, so the version store seems rather pointless. And if the row was found with no shared lock, how is it different to just using NOLOCK?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-15T03:52:14+00:00Added an answer on May 15, 2026 at 3:52 am

    Using NOLOCK or READ UNCOMMITTED means you give up any guarantee of consistency. Period.

    If you need consistency, don’t do dirty reads. Your whole explanation relies on undocumented behavior subject to change in future releases and, far worse, on specific access plans you expect for your query. The Query Optimizer is free to choose any plan it sees fit and any assumption you make it may be broken in production. So is back to square one: don’t do dirty reads if you’re not prepared to face the consequences.

    Not sure if this applies, is not clear what you try to achieve with your query/table, but perhaps this article may help: Using tables as Queues.

    Updated
    Where a NOLOCK read would read an inconsistent state (eg. read a stale non-clustered index key and chase it to a missing row in the clustered index) a snapshot read would find the ‘missing’ row in the version store. For stable data, a snapshot read is identical with a nolock read. The magic of the version store comes into play whenever data is changed (uncommitted updates), because the snapshot read goes into the version store and finds the ‘old’ values (stable and consistent) where the nolock read would go haywire and chase pointers into lala land.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I know that |DataDirectory| will resolve to App_Data in an ASP.NET application but is
I know that IList is the interface and List is the concrete type but
I know that I can do something like $int = (int)99; //(int) has a
I know that default cron's behavior is to send normal and error output to
I know that you can insert multiple rows at once, is there a way
I know that the MsNLB can be configured to user mulitcast with IGMP. However,
I know that .NET is JIT compiled to the architecture you are running on
I know that the following is true int i = 17; //binary 10001 int
I know that just using rand() is predictable, if you know what you're doing,
I know that we shouldn't being using the registry to store Application Data anymore,

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.