The NOLOCK hint in SQL is used to tell the database engine to read data without acquiring shared locks and without waiting for exclusive locks held by other transactions. In simple terms, it allows the query to read uncommitted data, meaning it can access rows that are currently being updated by other transactions — this is why it’s often associated with faster but “dirty” reads.
In practice, when I use WITH (NOLOCK) (or equivalently the READ UNCOMMITTED isolation level), I’m essentially trading accuracy for speed. It’s useful in situations where performance and concurrency are more important than perfectly consistent data.
For example, in one reporting environment, we had a dashboard pulling large volumes of transactional data from an orders table that was continuously updated by an e-commerce system. During peak hours, users complained that reports were timing out because queries were getting blocked by active inserts and updates.
To fix this, we applied WITH (NOLOCK) to non-critical SELECT queries, which allowed reports to read data instantly without waiting for locks to be released. As a result, report performance improved drastically, and there was no user disruption — because minor inconsistencies in the report (like a few orders missing for a few seconds) were acceptable.
However, I’ve also seen challenges with NOLOCK — especially in financial systems. In one case, an accounting report showed negative balances because it read uncommitted data while another transaction was still adjusting ledger entries. After analysis, we realized NOLOCK was the root cause, and we switched to READ COMMITTED SNAPSHOT ISOLATION (RCSI) instead. This maintained high concurrency but guaranteed consistent data using row versioning instead of dirty reads.
Some of the risks of NOLOCK include:
- Dirty reads — reading uncommitted data that may later be rolled back.
- Non-repeatable reads — the same query may return different results if run twice.
- Phantom reads — new rows may appear between executions.
- Missing or duplicate rows — can happen when pages are being moved or updated during the read.
Given those risks, I only use NOLOCK when:
- The query is read-only and not part of a transaction that modifies data.
- The data is not mission-critical, like logs, analytics snapshots, or temporary metrics.
- Slightly stale or inconsistent data is acceptable for the business purpose.
- A safer isolation level like RCSI or READ COMMITTED SNAPSHOT is not available or feasible due to infrastructure constraints.
In summary, NOLOCK can be a valuable performance optimization tool in high-concurrency environments, but it should be used selectively and carefully. My general principle is: use it for performance on non-critical reads, avoid it on financial or transactional data where accuracy matters.
