Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

InnoDB’s multi-version concurrency control (MVCC) lets ordinary reads see a consistent snapshot while other transactions change rows. In MySQL 8.4, the snapshot timing depends on isolation level: the default REPEATABLE READ reuses the snapshot from a transaction’s first consistent read, while READ COMMITTED takes a fresh snapshot for each consistent read. MVCC supports nonlocking reads; it does not make every query lock-free.

How does MVCC work in MySQL?

MVCC is InnoDB’s way of managing visibility across concurrent transactions. The MySQL 8.4 Reference Manual describes InnoDB as “a multi-version storage engine.” Instead of keeping a complete extra copy of every table, InnoDB stores undo information for changed rows. Each row includes transaction metadata and a pointer into undo information; when a consistent read needs an earlier version, InnoDB can follow that history to reconstruct it.

Undo information also supports rollback. Insert undo can be discarded after a committed insert, but update undo may remain necessary while an active snapshot could still need an earlier row version. MVCC therefore handles both transaction recovery and consistent reads.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What is a consistent read in InnoDB?

The manual defines a consistent read as a query for which “InnoDB uses multi-versioning to present to a query a snapshot of the database at a point in time.” An ordinary SELECT is generally a consistent, nonlocking read. It sees changes committed before its snapshot was established, not changes committed afterward or uncommitted changes from other transactions.

There is an important exception: a transaction sees its own earlier writes. If it updates a row and then selects it, the SELECT can show that update even while other rows remain visible as they were in the transaction’s older snapshot. The resulting view may not match a single state that ever existed globally.

In REPEATABLE READ, the snapshot is established by the first consistent read, not necessarily when the transaction begins. Committing ends that transaction; a subsequent query in a new transaction can use a later snapshot.

What is the difference between REPEATABLE READ and READ COMMITTED?

REPEATABLE READ is InnoDB’s default isolation level. READ COMMITTED changes when an ordinary consistent read gets its view of committed data.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Behavior REPEATABLE READ READ COMMITTED
InnoDB default Yes No
Snapshot timing for ordinary consistent reads The first consistent read establishes the snapshot; later consistent reads in the transaction reuse it. Each consistent read obtains a fresh snapshot.
Practical effect Repeated plain SELECTs in one transaction continue to use the same snapshot, apart from the transaction’s own writes. A later plain SELECT can see a commit that was not visible to an earlier SELECT in the same transaction.
Locking behavior Range and locking operations can use gap or next-key locks in documented cases. Gap locking for searches and index scans is disabled, except for foreign-key and duplicate-key checks. UPDATE can use a semi-consistent read in the documented case.

A timeline example

  1. Transaction A starts and performs a plain SELECT. That consistent read establishes its snapshot.
  2. Transaction B updates a row and commits.
  3. Transaction A performs another plain SELECT. Under REPEATABLE READ, it continues to use its earlier snapshot; under READ COMMITTED, it gets a fresh snapshot and can see B’s committed change.

These differences concern consistent reads, not a promise that all statements in a transaction use one identical view. Locking reads and data-changing statements have behavior that differs from ordinary consistent SELECTs. The other InnoDB isolation levels are READ UNCOMMITTED, which can expose uncommitted data (a dirty read), and SERIALIZABLE, which changes plain SELECT behavior when autocommit is disabled.

Why does MySQL show an older value inside a transaction?

Under REPEATABLE READ, a plain SELECT after another transaction commits can still show the value visible when the first consistent read established the snapshot. That is expected snapshot behavior, not necessarily stale storage or a failed update. A new transaction, or a consistent read under READ COMMITTED, can use a newer snapshot.

Also distinguish the statement type. Ordinary consistent reads, locking reads, and data-changing statements do not all necessarily see data the same way. In particular, mixing consistent nonlocking reads with locking statements in a REPEATABLE READ transaction can expose different views.

Does MVCC mean MySQL queries never lock?

No. Ordinary consistent reads in REPEATABLE READ and READ COMMITTED do not set locks on the tables they access, so other sessions can modify those tables while the reads run. Explicit locking reads are different:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • SELECT ... FOR SHARE takes shared locks on rows read.
  • SELECT ... FOR UPDATE locks encountered index records and associated entries similarly to an UPDATE.

These locks are released at commit or rollback. For example, if an application must check that a parent row exists before inserting a related child row, a plain SELECT leaves an opportunity for another transaction to delete the parent before the insert. A FOR SHARE read protects the row while the transaction continues. Actual lock scope depends on the search and indexes.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Can a long-running transaction cause undo history to grow?

Yes. If an active snapshot could still need earlier row versions, InnoDB cannot discard the corresponding update undo records. A long-running transaction—including a read-only transaction that performs consistent reads—can delay purge and contribute to a growing InnoDB History list length.

MySQL’s 8.4 Reference Manual says the History list length is typically “usually less than a few thousand.” This is a general observation, not a target, limit, or guarantee. To investigate purge lag, inspect the TRANSACTIONS section of SHOW ENGINE INNODB STATUS for History list length, and consider transaction age as well; the value alone does not diagnose the cause. Commit or roll back transactions regularly, including read-only transactions.

Version scope and official documentation

The behavior described here is documented for InnoDB in MySQL 8.4. Implementation and isolation details can vary by version, so check the manual for the MySQL release you deploy. Relevant sections are InnoDB Multi-Versioning, Consistent Nonlocking Reads, Transaction Isolation Levels, Undo Logs, Purge Configuration, and Locking Reads.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.