SQLTransactionsbeginner
Updated:

SQL Transactions Explained

6 min read

Learn how SQL transactions group statements into all-or-nothing units, what ACID really means, and how COMMIT, ROLLBACK, and isolation levels keep data correct.

TL;DR – Quick Answer

A SQL transaction is a group of statements that the database treats as a single all-or-nothing unit. You start it, run your statements, then COMMIT to make every change permanent or ROLLBACK to undo them all. Transactions follow the ACID properties, which guarantee your data stays correct even during failures or concurrent access.

On This Page

Imagine transferring money from one account to another. You subtract from one balance and add to the other. If the database crashes after the subtraction but before the addition, money vanishes. A transaction is the mechanism that makes those two steps happen together or not at all — the single most important idea for keeping data correct.

We will use the familiar employees and orders tables from the SQL learning hub, plus a small accounts table for the classic transfer example. The commands here work in MySQL, PostgreSQL, and SQL Server with minor keyword differences.

What a transaction is

A transaction is a group of one or more SQL statements that the database executes as a single, indivisible unit. Either every statement succeeds and the changes become permanent, or something fails and the database undoes all of them, as if none had run.

You wrap statements between a start and an end:

START TRANSACTION;

UPDATE accounts SET balance = balance - 5000 WHERE acc_id = 1;
UPDATE accounts SET balance = balance + 5000 WHERE acc_id = 2;

COMMIT;

START TRANSACTION (or BEGIN) opens the transaction. The two UPDATE statements run but are not yet permanent. COMMIT makes them permanent together. If anything had gone wrong before COMMIT, you would run ROLLBACK and both updates would disappear, leaving the balances untouched.

Pro tip: By default, most databases run in autocommit mode — each statement commits instantly on its own. The moment you need two or more statements to succeed or fail together, you must open an explicit transaction. Forgetting this is how half-finished updates end up in production data.

The four ACID guarantees

Transactions are trustworthy because they satisfy four properties, remembered by the acronym ACID.

Atomicity means all-or-nothing. The transfer above either moves the full 5000 or moves nothing. There is no state where the money left one account but never arrived in the other.

Consistency means the database moves from one valid state to another. Constraints like foreign keys, unique keys, and check constraints are enforced; a transaction that would break a rule is rejected. This is where the design work from database normalization pays off, because well-defined constraints define what "valid" even means.

Isolation means concurrent transactions do not step on each other. If a hundred orders are inserted at once, each transaction behaves as though it were running alone, according to the isolation level you choose.

Durability means that once a transaction commits, its changes survive a crash, power loss, or restart. The database writes the change to a durable log before reporting success.

COMMIT and ROLLBACK in practice

Here is a realistic order-processing flow. When an employee finalizes a sale, you insert the order and update inventory together. If the inventory update fails, you must not keep the order.

START TRANSACTION;

INSERT INTO orders (order_id, emp_id, order_date, amount, status)
VALUES (5001, 42, '2026-07-15', 1299.00, 'CONFIRMED');

UPDATE inventory
SET quantity = quantity - 1
WHERE product_id = 88;

-- If quantity is now negative, the sale is invalid:
-- application checks the result, then decides.
COMMIT;   -- or ROLLBACK on failure

If the application detects that the product was out of stock, it issues ROLLBACK instead of COMMIT, and the order insert is erased along with the inventory change. The customer sees a clean "out of stock" message and the data never records a phantom sale.

Many databases also support savepoints, which let you roll back part of a transaction:

START TRANSACTION;
UPDATE employees SET salary = salary * 1.10 WHERE department = 'Sales';
SAVEPOINT sales_raise;
UPDATE employees SET salary = salary * 1.10 WHERE department = 'Support';
ROLLBACK TO sales_raise;   -- undo only the Support raise
COMMIT;                    -- keep the Sales raise

Concurrency problems and isolation levels

The hard part of transactions is not one user — it is thousands at once. When transactions overlap, three classic problems appear.

A dirty read is reading another transaction's uncommitted change, which may later be rolled back. A non-repeatable read is reading the same row twice in one transaction and getting different values because another transaction committed a change in between. A phantom read is running the same query twice and getting different rows because another transaction inserted or deleted matching rows.

SQL defines four isolation levels that trade correctness against concurrency:

-- Set the level for the next transaction
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

START TRANSACTION;
SELECT SUM(amount) FROM orders WHERE emp_id = 42;
-- ... more work ...
COMMIT;

Read Uncommitted allows dirty reads and is rarely used. Read Committed prevents dirty reads and is the sensible default in PostgreSQL and SQL Server. Repeatable Read also prevents non-repeatable reads and is MySQL's default. Serializable prevents all three problems by making transactions behave as if they ran one after another, at the cost of the most locking.

Interview note: A frequent question is "What is MySQL's default isolation level, and what is PostgreSQL's?" The answer — Repeatable Read for MySQL (InnoDB), Read Committed for PostgreSQL — signals you have actually run these databases, not just read about them.

Deadlocks: when transactions wait forever

When two transactions each hold a lock the other needs, neither can proceed. This is a deadlock. Say transaction A locks employee row 1 and wants row 2, while transaction B locks row 2 and wants row 1. Modern databases detect this, pick a victim, and roll it back automatically, returning an error you must handle.

-- Transaction A
START TRANSACTION;
UPDATE employees SET salary = salary + 100 WHERE emp_id = 1;
UPDATE employees SET salary = salary + 100 WHERE emp_id = 2;  -- waits on B
COMMIT;

The practical fix is to have every transaction acquire locks in the same order — for example, always update the lower emp_id first. Consistent lock ordering makes the classic deadlock impossible.

Common mistake: Leaving a transaction open while the application does slow work — waiting on user input, calling an external API, or sleeping. Locks are held for the whole transaction, so long transactions block everyone else. Keep transactions short: open, do the writes, commit.

Common mistakes to avoid

Beginners tend to forget to commit, leaving changes invisible to everyone else and locks held indefinitely. Others wrap far too much in one transaction, hurting concurrency, or catch an error and continue without rolling back, producing exactly the half-finished state transactions are meant to prevent. The rule is simple: keep transactions small, always commit or roll back on every path, and never do slow non-database work inside one.

Where you meet transactions as a developer

You rarely type START TRANSACTION by hand in a real application. Frameworks manage it for you. In Spring, the @Transactional annotation you will study in Spring Data JPA wraps a method so that all its database work commits together or rolls back on any exception. Understanding what the framework is doing underneath — and why it sometimes deadlocks or reads stale data — is what turns a junior developer into someone who can debug production incidents.

Transactions also lean on the indexes you tune: the database locks the rows and index entries a transaction touches, so a poorly indexed query can lock far more than you intended. These topics connect, which is why they come up together in SQL interviews.

Putting it together

A transaction is the database's promise that a group of changes is atomic, consistent, isolated, and durable. You open it, run your statements, and end with COMMIT or ROLLBACK. You pick an isolation level to balance correctness against concurrency, keep transactions short to avoid blocking, and order your locks consistently to dodge deadlocks. Get comfortable reasoning about these guarantees and you will write data-handling code that stays correct under real production load — the skill that backend teams value most.

Frequently Asked Questions

What does ACID stand for?
ACID stands for Atomicity, Consistency, Isolation, and Durability. These four properties guarantee that a transaction either fully completes or fully undoes, keeps the database in a valid state, does not interfere with other transactions, and survives a crash once committed.
What is the difference between COMMIT and ROLLBACK?
COMMIT makes every change in the current transaction permanent and visible to other users. ROLLBACK discards every change since the transaction began, returning the data to how it was before. You use ROLLBACK when an error occurs or a business rule is violated.
What is a dirty read?
A dirty read happens when one transaction reads data that another transaction has changed but not yet committed. If that other transaction rolls back, the first transaction acted on data that never really existed. Higher isolation levels prevent dirty reads.
Are transactions automatic in SQL?
By default many databases run in autocommit mode, so each statement is its own transaction that commits immediately. To group several statements you explicitly start a transaction with BEGIN or START TRANSACTION and end it with COMMIT or ROLLBACK.
What are isolation levels?
Isolation levels control how much one transaction can see the uncommitted work of another. The standard levels from weakest to strongest are Read Uncommitted, Read Committed, Repeatable Read, and Serializable. Stronger isolation means more correctness but less concurrency.

Want to Build Your Career in Java Full Stack with AI?

Join CodeBegun and train with working industry engineers — Explore the Program

Apply for Demo Class →
Siva Prasad Galaba
Founder, CodeBegun · Staff Engineer

Founder of CodeBegun. 15+ years building Java systems at companies like Crunchyroll. Teaches Java, Spring Boot and system design the way the industry actually works, and mentors students through projects, mock interviews and placement preparation.

Technically reviewed by CodeBegun Technical TeamLast reviewed 15 July 2026 LinkedIn
Chat with us