Skip to content

CONCEPT Cited by 1 source

MySQL CONNECTION_ID vs thread_id

MySQL exposes two distinct integer identifiers for the same running session: the user-facing CONNECTION_ID() (aka PROCESSLIST_ID) and the instrumentation-layer performance_schema.threads.thread_id. They are not equal. Every per-thread diagnostic workflow starts by mapping one to the other.

(Source: sources/2026-04-21-planetscale-profiling-memory-usage-in-mysql.)

The two identifiers

Identifier Source Visible in
CONNECTION_ID() User-facing SQL function SHOW PROCESSLIST, information_schema.processlist.ID
PROCESSLIST_ID Column alias for CONNECTION_ID() performance_schema.threads.PROCESSLIST_ID
thread_id Instrumentation-layer identifier performance_schema.threads.THREAD_ID, all memory_summary_by_thread_* tables

CONNECTION_ID() == PROCESSLIST_ID for any user connection. thread_id is assigned independently by performance_schema's internal thread registry and is the key used across every *_by_thread_* summary table.

Canonical mapping pattern

From the Dicken post, verbatim:

SET @cid = (SELECT CONNECTION_ID());
SET @tid = (SELECT thread_id
              FROM performance_schema.threads
              WHERE PROCESSLIST_ID=@cid);
SELECT @cid, @tid;
-- +------+------+
-- | @cid | @tid |
-- +------+------+
-- |   49 |   89 |
-- +------+------+

The mapping is not thread_id = cid + constant@cid = 49, @tid = 89 in the post; specific values vary. The lookup must go through performance_schema.threads.

Why two IDs?

  • performance_schema instruments all MySQL threads, including background threads (purge, replication, IO) that have no user connection + no CONNECTION_ID. A separate identifier namespace is required to account for those.
  • thread_id is a dense sequential counter over the server's lifetime across all threads; CONNECTION_ID is a dense sequential counter restricted to user connections. The two spaces drift apart quickly on busy servers.

Direction of lookup

Almost always cid → tid: a user knows their session's CONNECTION_ID() and needs the thread_id to query instrumentation tables. The reverse direction (tid → cid) is useful for attributing an instrumentation finding back to a user session ("which connection is thread 89?"); the join is symmetric through performance_schema.threads.

Caveats

  • Background threads have no PROCESSLIST_ID — the column is NULL for them. Joining on IS NOT NULL scopes to user connections.
  • Thread re-use across connections — after a connection closes, its thread_id may be re-used by a future connection (implementation-defined). Long-running sampling scripts should re-resolve the mapping if the target connection is lost.
  • Tools sometimes conflate the two — external monitoring tools may call either value "thread ID"; read the column source to disambiguate.

Seen in

  • PlanetScale's Profiling memory usage in MySQL (2024-04-11). Dicken's workflow requires the cid→tid mapping as step 1 of per-query memory profiling. Also the second Python script takes --connection-id as user-facing input and internally calls performance_schema.threads to resolve the thread_id. (Source: sources/2026-04-21-planetscale-profiling-memory-usage-in-mysql.)
Last updated · 470 distilled / 1,213 read