August 27, 2025

MySQL Session Memory Leak Experiments Revealed

This article investigates MySQL memory growth in sessions through controlled experiments, showing large variable assignments cause significant leaks. Essential for database optimization.

1. Background
On a client site, we encountered a session occupying dozens of GBs of memory, with consumption continuously increasing. Investigation revealed that a variable was being assigned increasingly larger values in a loop, causing session memory to grow. To address this, we designed experiments to confirm two key questions:

  • Does repeatedly assigning different values to a variable increase session memory?
  • Does assigning large values to a variable increase session memory?

2. Preparation Environment

DROP DATABASE IF EXISTS test_db;  
CREATE DATABASE test_db;  
USE test_db;  
CREATE TABLE a (i INT, j VARCHAR(2000));  
INSERT INTO a VALUES (1, 'a'), (2, 'b'), (3, 'c'), (4, 'd');  

2.1 Experiment 1: Does repeatedly assigning different values increase session memory?​​​

2.1.1 Create a function that continuously assigns values in a loop

DROP FUNCTION IF EXISTS test_db.fun_test;  
DELIMITER //  
CREATE FUNCTION test_db.fun_test(_id VARCHAR(32))  
RETURNS VARCHAR(4000) DETERMINISTIC  
BEGIN  
    DECLARE _tb_i VARCHAR(32) DEFAULT _id;  
    IF _tb_i IS NULL THEN  
        RETURN NULL;  
    END IF;  
    WHILE _tb_i IS NOT NULL DO  
        SELECT i INTO @var_i FROM test_db.a WHERE i = _tb_i;  
    END WHILE;  
    RETURN 1;  
END //  
DELIMITER ;  

2.1.2 Call the function

SELECT test_db.fun_test("1");  

2.1.3 Check the processlist ID

SELECT * FROM information_schema.processlist;  

Output:

+----+----------+-----------------+---------+---------+------+--------------+---------------------------------------------------------------------------------------------------------------+  
| ID | USER     | HOST            | DB      | COMMAND | TIME | STATE        | INFO                                                                                                          |  
+----+----------+-----------------+---------+---------+------+--------------+---------------------------------------------------------------------------------------------------------------+  
|  3 | mgr_user | 127.0.0.1:48704 | test_db | Query   |   24 | Sending data | SELECT i INTO @var_i FROM test_db.a WHERE i = NAME_CONST('_tb_i', _utf8mb4'1' COLLATE 'utf8mb4_general_ci') |  
|  2 | mgr_user | 127.0.0.1:47104 | NULL    | Query   |    0 | executing    | SELECT * FROM information_schema.processlist                                                                  |  
+----+----------+-----------------+---------+---------+------+--------------+---------------------------------------------------------------------------------------------------------------+  
2 rows in set (0.00 sec)  

2.1.4 Find the thread ID using the processlist ID

SELECT PROCESSLIST_ID, thread_id, name FROM performance_schema.threads WHERE PROCESSLIST_ID=3;  

Output:

+----------------+-----------+---------------------------+  
| PROCESSLIST_ID | thread_id | name                      |  
+----------------+-----------+---------------------------+  
|              3 |        29 | thread/sql/one_connection |  
+----------------+-----------+---------------------------+  
1 row in set (0.00 sec)  

2.1.5 Monitor session memory usage by thread ID (observe multiple times)​

SELECT * FROM sys.memory_by_thread_by_current_bytes WHERE thread_id=29;  

Output examples:

+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
| thread_id | user               | current_count_used | current_allocated | current_avg_alloc | current_max_alloc | total_allocated |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
|        29 | mgr_user@127.0.0.1 |                 82 | 194.02 KiB        | 2.37 KiB          | 71.80 KiB         | 60.37 GiB       |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
1 row in set (0.03 sec)  

+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
| thread_id | user               | current_count_used | current_allocated | current_avg_alloc | current_max_alloc | total_allocated |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
|        29 | mgr_user@127.0.0.1 |                 82 | 194.02 KiB        | 2.37 KiB          | 71.80 KiB         | 61.97 GiB       |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
1 row in set (0.03 sec)  

After multiple refreshes, total_allocated increases steadily, but current_allocated remains stable. This indicates that repeatedly assigning different values does not increase session memory.

2.2 Experiment 2: Does assigning large values increase session memory?​
2.2.1 Create a function assigning large values in a loop (appending content each iteration)​

DELIMITER //  
CREATE FUNCTION test_db.fun_test_var(_id VARCHAR(32))  
RETURNS VARCHAR(4000) DETERMINISTIC  
BEGIN  
    DECLARE _tb_i VARCHAR(32) DEFAULT _id;  
    DECLARE _abc VARCHAR(4000) DEFAULT NULL;  
    IF _tb_i IS NULL THEN  
        RETURN NULL;  
    END IF;  
    WHILE _tb_i IS NOT NULL DO  
        SELECT i INTO @var_i FROM test_db.a WHERE i = _tb_i;  
        IF @var_i IS NOT NULL THEN  
            SET _abc = CONCAT(@var_i, '>', _abc);  
        END IF;  
    END WHILE;  
    RETURN 1;  
END //  
DELIMITER ;  

2.2.2 Call the function

SELECT test_db.fun_test_var("1");  

2.2.3 Check the processlist ID

SELECT * FROM information_schema.processlist;  

Output:

+----+----------+-----------------+---------+---------+------+--------------+---------------------------------------------------------------------------------------------------------------+  
| ID | USER     | HOST            | DB      | COMMAND | TIME | STATE        | INFO                                                                                                          |  
+----+----------+-----------------+---------+---------+------+--------------+---------------------------------------------------------------------------------------------------------------+  
|  6 | mgr_user | 127.0.0.1:59548 | test_db | Query   |   49 | Sending data | SELECT i INTO @var_i FROM test_db.a WHERE i = NAME_CONST('_tb_i', _utf8mb4'1' COLLATE 'utf8mb4_general_ci') |  
|  2 | mgr_user | 127.0.0.1:47104 | NULL    | Query   |    0 | executing    | SELECT * FROM information_schema.processlist                                                                  |  
+----+----------+-----------------+---------+---------+------+--------------+---------------------------------------------------------------------------------------------------------------+  
2 rows in set (0.00 sec)  

2.2.4 Find the thread ID using the processlist ID

SELECT PROCESSLIST_ID, thread_id, name FROM performance_schema.threads WHERE PROCESSLIST_ID=6;  

Output:

+----------------+-----------+---------------------------+  
| PROCESSLIST_ID | thread_id | name                      |  
+----------------+-----------+---------------------------+  
|              6 |        32 | thread/sql/one_connection |  
+----------------+-----------+---------------------------+  
1 row in set (0.00 sec)  

2.2.5 Monitor session memory usage by thread ID (observe multiple times)​

SELECT * FROM sys.memory_by_thread_by_current_bytes WHERE thread_id=32;  

Output examples:

+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
| thread_id | user               | current_count_used | current_allocated | current_avg_alloc | current_max_alloc | total_allocated |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
|        32 | mgr_user@127.0.0.1 |                825 | 693.13 MiB        | 860.32 KiB        | 564.82 MiB        | 248.01 GiB      |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
1 row in set (0.03 sec)  

+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
| thread_id | user               | current_count_used | current_allocated | current_avg_alloc | current_max_alloc | total_allocated |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
|        32 | mgr_user@127.0.0.1 |                834 | 705.05 MiB        | 865.67 KiB        | 576.75 MiB        | 249.93 GiB      |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
1 row in set (0.03 sec)  

+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
| thread_id | user               | current_count_used | current_allocated | current_avg_alloc | current_max_alloc | total_allocated |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
|        32 | mgr_user@127.0.0.1 |                848 | 727.74 MiB        | 878.78 KiB        | 599.44 MiB        | 253.84 GiB      |  
+-----------+--------------------+--------------------+-------------------+-------------------+-------------------+-----------------+  
1 row in set (0.03 sec)  

Multiple refreshes show both total_allocated and current_allocated increasing, indicating that assigning large values significantly increases session memory.

3. Summary

  • Repeatedly assigning different values to a session variable does not cause continuous memory growth.
  • Assigning large values to a session variable can lead to substantial memory increases.
    Keywords:​​ #MySQL #FunctionCall #MemoryManagement

You will get best features of ChatDBA