When you put NOLOCK in your query, SQL Server will:
- Read rows twice
- Skip rows altogether
- Show you changes that never actually got committed
- Let your query fail with an error
This is not a bug. This is by design. To understand what happens, read these blog posts in order:
- Using NOLOCK? Here’s how you’ll get the wrong query results.
- “But NOLOCK is okay when my data isn’t changing, right?”
- “But surely NOLOCK is okay if no one’s changing data, right?”
After reading those, you’re going to ask, “So what am I supposed to do if I need to avoid blocking problems?” There are 3 solutions:
- Have enough indexes that your queries go fast, but not so many that your deletes/updates/inserts take forever. I cover this in the locking module of my Mastering Index Tuning class.
- Keep your transactions short and sweet, and use batching to avoid lock escalation. I cover this in the deadlocking module and the batching module of my Mastering Query Tuning class.
- Use read committed snapshot isolation (RCSI) or snapshot isolation (SI) so that readers and writers can coexist. I cover this in the isolation levels module of my Mastering Server Tuning class.
I know: NOLOCK sounds so much easier because you can just slap it into a query and it feels like it’s going faster. Just remember the demos in those first 3 blog posts up above: sooner or later, your users are going to see inaccurate query results.
If it’s so bad,
why is NOLOCK an option?
Because in some applications, accuracy really doesn’t matter. I know it sounds like a joke, but I’m being serious.
For example, one of my clients is a high-volume online shopping site. Their admins want to see that data is moving through the shopping cart process, that users have been adding new shopping carts in the database. They use monitoring queries to check for the last 10 carts that were created recently and checked out recently. They don’t really care whether the results are transactionally accurate – they just wanna see that any new orders are moving through the system. NOLOCK works fine there.
Another example is the open source First Responder Kit scripts like sp_BlitzIndex. I don’t need transactional accuracy when I’m checking the usage statistics on an index – we’re just getting rough numbers. If the same index happened to be shown twice, you would simply go, “Well that’s odd,” and you’d rerun it to check.
But if your application involves money, health care, or anything else vitally important, you better think twice before using NOLOCK.