Databases 13 min read

Understanding MySQL Auto‑Increment IDs, InnoDB row_id, Xid, trx_id, and thread_id Limits

This article explains how MySQL auto‑increment primary keys, InnoDB hidden row_id, transaction Xid, InnoDB trx_id, and the server thread_id behave when they reach their numeric limits, the consequences for data integrity, and recommended mitigation strategies.

Architect's Guide
Architect's Guide
Architect's Guide
Understanding MySQL Auto‑Increment IDs, InnoDB row_id, Xid, trx_id, and thread_id Limits

Table Auto‑Increment ID

MySQL defines an initial value and step for an AUTO_INCREMENT column, but the underlying unsigned integer type has a fixed byte size (e.g., INT UNSIGNED is 4 bytes, max 2^32‑1). When the limit is reached, further INSERTs return the same maximum value, causing duplicate‑key errors.

mysql> create table t(id int unsigned auto_increment primary key) auto_increment=4294967295;
Query OK, 0 rows affected

mysql> insert into t values (null);
Query OK, 1 row affected

mysql> insert into t values (null);
ERROR 1062 (23000): Duplicate entry '4294967295' for key 't.PRIMARY'

Therefore, tables that may exhaust INT UNSIGNED should use BIGINT UNSIGNED (8 bytes).

InnoDB System Auto‑Increment row_id

If an InnoDB table lacks an explicit primary key, InnoDB creates an invisible 6‑byte row_id . The global dict_sys->row_id is a 8‑byte unsigned integer, but only the lower 6 bytes are stored, giving a range 0 – 2^48‑1. When the limit is hit, the next value wraps to 0, causing later rows to overwrite earlier rows with the same row_id.

Verification using GDB to set dict_sys.row_id = 2^48 shows that subsequent inserts reuse row_id 0 and 1, overwriting previous rows.

Xid

Both the redo log and binlog contain an Xid that links a transaction to its log records. MySQL maintains a global global_query_id (8‑byte) that is assigned to query_id for each statement and, for the first statement of a transaction, also to the transaction’s Xid. The counter resets on server restart, so Xids are unique only within a single binlog file; theoretically they could repeat after 2^64 statements, but this is practically impossible.

InnoDB trx_id

InnoDB has its own transaction identifier ( trx_id) maintained by a global max_trx_id. Each new transaction receives the current max_trx_id value, then the counter is incremented. Read‑only transactions do not allocate a trx_id, reducing overhead and the size of the active‑transaction array.

When a row is updated, its stored trx_id is used together with the transaction’s consistency view to decide visibility.

Data Visibility Core Idea

Every row stores the trx_id of the transaction that created it. A reading transaction compares this value with its own view; if the row’s trx_id is less than the transaction’s low‑water‑mark, the row is visible.

Read‑only transactions skip trx_id allocation, so their low‑water‑mark can be much larger than the IDs of read‑write transactions, improving concurrency.

thread_id

MySQL assigns each new connection a thread_id from a global 4‑byte counter ( thread_id_counter). When the counter reaches 2^32‑1 it wraps to 0, but the server ensures uniqueness in the process list by using an internal array.

Summary

Different auto‑increment mechanisms have distinct behaviours at their limits:

Table primary‑key AUTO_INCREMENT stops increasing at its maximum and then raises duplicate‑key errors.

InnoDB hidden row_id wraps to 0, causing later rows to overwrite earlier ones with the same row_id. Xid only needs to be unique within a binlog file; collisions across restarts are theoretically possible but negligible. max_trx_id persists across restarts; if it ever reaches 2^48‑1 and wraps, a specific dirty‑read bug can appear, though it would require many years of continuous operation. thread_id also wraps at 2^32‑1 but remains unique in the active connection list.

Understanding these limits helps design schemas (e.g., using BIGINT UNSIGNED for primary keys) and avoid data loss or availability issues.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

InnoDBmysqlauto_incrementDatabase Internalstransaction IDs
Architect's Guide
Written by

Architect's Guide

Dedicated to sharing programmer-architect skills—Java backend, system, microservice, and distributed architectures—to help you become a senior architect.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.