CONCEPT Cited by 1 source
Per-thread memory profiling¶
Per-thread memory profiling is the MySQL technique of measuring a running query's memory usage by sampling the thread running that query, because MySQL binds one query to one connection to one thread for the query's lifetime — so per-thread memory is per-query memory for the duration of the query.
(Source: sources/2026-04-21-planetscale-profiling-memory-usage-in-mysql.)
Why it's a substitute, not a first-class feature¶
MySQL's memory instrumentation does not expose a per-query grain (see concepts/memory-profiling-granularity). The five available grains are account / host / thread / user / global. Of these, thread is the only one that uniquely identifies a specific executing query — provided you know which thread the query is running on. The connection↔thread binding property makes this identification reliable for the duration of the query.
The canonical workflow¶
Four steps from the Dicken post:
- Open two connections — one for the query under test, one for monitoring. See patterns/two-connection-profiling-setup.
- On the monitored connection, capture the thread id:
SET @cid = (SELECT CONNECTION_ID());
SET @tid = (SELECT thread_id
FROM performance_schema.threads
WHERE PROCESSLIST_ID=@cid);
SELECT @cid, @tid;
See concepts/mysql-connection-id-vs-thread-id for the cid↔tid distinction. 3. Execute the query on the monitored connection. 4. On the monitoring connection, sample memory every N ms:
SELECT event_name, current_number_of_bytes_used
FROM performance_schema.memory_summary_by_thread_by_event_name
WHERE thread_id = <tid>
ORDER BY current_number_of_bytes_used DESC LIMIT 4;
See patterns/periodic-sampling-memory-profiler.
Sampling vs total¶
Each sample is an instantaneous snapshot of
current_number_of_bytes_used — not a time-integral, not a
peak. Memory usage during query execution is non-monotonic
(allocations + frees happen throughout), so:
- A single sample mid-execution is one data point, not "the" memory cost of the query.
- The post's running example shows the steady-state top
categories (
Filesort_buffer::sort_keysdominating at ~200 KiB for a 100K-rowORDER BY). - Short queries may complete between samples; the technique is practical only for multi-second (or longer) queries.
When it breaks down¶
- Sub-second queries — the sampling loop never catches the query running, or catches it only once. Dicken flags this explicitly.
- Cross-thread allocations — some MySQL subsystems allocate on a thread other than the connection's thread (background purge, replication). Per-thread sampling misses those.
- Shared memory structures — the InnoDB buffer pool is
global; allocations charged to a thread via
memory/innodb/memoryare the delta this thread caused, not the absolute buffer-pool size. - Thread re-use — after the query completes, the thread
may handle other queries; continuing to sample the same
thread_idwill observe unrelated workloads.
Seen in¶
- PlanetScale's Profiling memory usage in MySQL (2024-04-11).
Dicken canonicalises the two-connection setup + cid→tid
mapping + live
matplotlibvisualisation as the operational shape of per-thread memory profiling. (Source: sources/2026-04-21-planetscale-profiling-memory-usage-in-mysql.)