Why MySQL 8.4 Fails with io_setup() EAGAIN and How to Fix It
When upgrading MySQL 8.0 to 8.4 on a host running multiple instances, some instances fail to start with a series of InnoDB errors caused by io_setup() returning EAGAIN, which can be resolved by increasing the system's aio‑max‑nr limit and adjusting InnoDB I/O thread settings.
Problem
A host running several MySQL instances upgraded from 8.0 to 8.4 began showing startup failures. The error log contains repeated warnings and errors such as io_setup() failed with EAGAIN, Cannot initialize AIO sub-system, and a cascade of InnoDB initialization abort messages.
Root‑Cause Analysis
Searching the source tree reveals the messages originate from storage/innobase/os/os0file.cc where the function AIO::linux_create_io_ctx calls the Linux system call io_setup. The code retries the call up to OS_AIO_IO_SETUP_RETRY_ATTEMPTS (default 5) and finally logs an error if io_setup still returns -EAGAIN.
# grep "io_setup() failed" -r /usr/src/mysql-8.4.0
/usr/src/mysql-8.4.0/storage/innobase/os/os0file.cc: ib::warn(ER_IB_MSG_757) << "io_setup() failed with EAGAIN."
/usr/src/mysql-8.4.0/storage/innobase/os/os0file.cc: << "io_setup() failed with EAGAIN after "The io_setup system call creates an asynchronous I/O (AIO) context. It fails with EAGAIN when the requested max_events exceeds the kernel‑wide limit defined in /proc/sys/fs/aio-max-nr (default 65536 on many systems).
Understanding the AIO Limits
The kernel parameter /proc/sys/fs/aio-max-nr controls the maximum number of AIO events that can be allocated system‑wide. MySQL calculates the number of events it needs during startup based on the number of read and write I/O threads:
(1 + innodb_read_io_threads + innodb_write_io_threads) * 256 + 1Here, 256 is the per‑segment event count ( OS_AIO_N_PENDING_IOS_PER_THREAD * 8), and the final +1 accounts for the AIO support check.
Solution
Increase the kernel limit to accommodate the required events. For a temporary change: # echo 1048576 > /proc/sys/fs/aio-max-nr For a permanent change, add the line to /etc/sysctl.conf and reload:
# vim /etc/sysctl.conf
fs.aio-max-nr=1048576
# sysctl -pWhy MySQL 8.4 Triggers the Error
In MySQL 8.4 the default value of innodb_read_io_threads changed: it now defaults to half the logical CPU count (minimum 4, maximum 64). On a server with 128 logical CPUs, the default becomes 64, dramatically increasing the required AIO events. With the default aio‑max‑nr of 65536, only three such instances can start (65536 / 17665 ≈ 3).
Explicitly setting the thread variables in the startup command, e.g. --innodb-read-io-threads=64 --innodb-write-io-threads=4, reproduces the calculation and confirms the required increase in aio‑max‑nr matches the observed difference in /proc/sys/fs/aio-nr before and after startup.
Conclusion
If MySQL reports io_setup() failed with EAGAIN, raise /proc/sys/fs/aio-max-nr to a value that covers
(1 + innodb_read_io_threads + innodb_write_io_threads) * 256 + 1.
The number of asynchronous I/O requests MySQL needs at startup equals
(1 + innodb_read_io_threads + innodb_write_io_threads) * 256 + 1.
Because innodb_read_io_threads defaults changed in MySQL 8.4, it is advisable to set this variable explicitly in my.cnf to avoid unexpected AIO limit exhaustion.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
ITPUB
Official ITPUB account sharing technical insights, community news, and exciting events.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
