In production systems, the database is rarely serving one statement at a time. Hundreds or thousands of sessions can be reading and writing concurrently. Transactions provide the boundary SQL Server uses to decide when changes become visible to other sessions and whether a multi-step operation should be made permanent or undone.
A transaction begins explicitly (or implicitly), performs work, and then ends with a COMMIT (make changes durable) or a ROLLBACK (undo the work).
This is the practical meaning of ACID in SQL Server:
SQL Server treats a transaction as the boundary for consistency and recovery. Within the boundary, SQL Server may hold locks, maintain row versions, log changes, and enforce constraints. The developer’s job is to keep transactions correct and short: long-running transactions are a common cause of blocking, lock escalation, and deadlocks.
BEGIN TRANSACTION;
-- One unit of work: either everything succeeds, or nothing does.
UPDATE dbo.Account
SET Balance = Balance - 100
WHERE AccountId = 101;
UPDATE dbo.Account
SET Balance = Balance + 100
WHERE AccountId = 202;
COMMIT;
The module will also emphasize safe rollback patterns using TRY...CATCH and transaction state checks so that failures do not leave sessions in an
unusable transaction state.
Concurrency control answers a simple question: how can many sessions read and write the same tables at the same time without producing incorrect results? SQL Server uses two primary mechanisms:
You will see how these mechanisms interact with isolation levels. Locking is normal and necessary, but excessive blocking is usually a design or tuning signal: missing indexes, long transactions, poor access patterns, or inappropriate isolation choices.
Isolation controls what anomalies a transaction may observe (dirty reads, non-repeatable reads, phantom rows) and how much contention it can create. SQL Server offers lock-based isolation levels and row-versioning options that can substantially change runtime behavior.
READ UNCOMMITTED allows statements to read rows modified by other transactions that have not yet committed. At this level, SQL Server does not acquire shared locks for reads and is not blocked by exclusive locks in the typical way, which can reduce blocking. The tradeoff is correctness: the session can see changes that later roll back (dirty reads), and the result set can shift during execution (rows can appear, disappear, or change values).
This isolation level is commonly associated with the NOLOCK table hint. It should be treated as an optimization of last resort for non-critical
reporting queries where approximate answers are acceptable and the risks are explicitly understood.
In many systems, a better approach to reducing reader/writer contention while preserving correctness is to use row versioning:
READ_COMMITTED_SNAPSHOT at the database level so readers can use row versions.
Transactions and locking are broader than BEGIN/COMMIT and isolation keywords. This module also introduces related topics that influence
correctness and performance in SQL Server 2025:
By the end of the module, you should be able to reason about the tradeoffs between consistency and concurrency, choose an isolation level intentionally, and implement transactions that remain correct under real-world multi-user load.