I have a percona mysql (5.7) server with 20K QPS (lots of inserts/updates/deletes).
My question is: why issuing a simple, but long, select query (to any table) with trx isolation=READ-UNCOMMITTED makes history list length (undo logs) to grow? (After query has executed the history list is purged right away).
Here's code example:
SET TRANSACTION ISOLATION LEVEL READ-UNCOMMITTED;
SELECT tt.id, tt.name, SLEEP(1) AS delay FROM table tt; # 100 rows, takes 100 to execute
In my understanding, that SELECT query does not need a read view and it does not care about data consistency. It just reads dirty, possibly uncommitted, data. But, during it's execution, history list length starts to grow fast (due to high QPS, other transactions write a lot), it turns mysql unable to purge - but why? My transaction is in READ-UNCOMMITTED mode, it wont ever need old versions of rows, right? (correct me here if I'm wrong).
I just cannot catch mysql's logic here.. and need a help.
P.S. I checked "information_schema.INNODB_TRX". it shows trx isolation=READ-UNCOMMITTED, trx_read_only=1, trx_autocommit_non_blocking=1. I checked other long running transactions, none. I repeated this on 4 different replicas and master - same behaviour. I tried without "SLEEP(1)" on bigger tables - same behaviour. I repeated this on a replica, without any connections but mine and replica's treads only (so no one could affect the test).
UPD 1 (for comment):
I have done a test. Create a table, insert 4 rows.
CREATE TABLE my_table (
id INT(11) NOT NULL AUTO_INCREMENT
, text VARCHAR(255) DEFAULT NULL
, PRIMARY KEY (id)
) ENGINE = INNODB;
INSERT INTO my_table(id, text) VALUES (1, 'hi'), (3, 'hi 2'), (5, 'hi 3'), (7, 'hi 5');
start dirty read, session 2 will be inserting rows after that query has started
# session 1, now 2021-12-22 21:20:00
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT tt.id, tt.text, SLEEP(4) AS delay FROM my_table tt;
start inserting rows here AFTER session 1 has started
# session 2, now 2021-12-22 21:20:22
INSERT INTO my_table(text) VALUES('hi 7');
INSERT INTO my_table(text) VALUES('hi 11'); ....
and so on, we can insert rows forever and query in session 1 never finishes