Have you encountered frustrating MySQL connection errors recently, even after setting a high max_connections
value? You might be surprised to learn that the culprit isn't necessarily your database configuration. In some cases, a system limitation called TaskMax within Systemd can restrict the number of connections your MySQL server can handle.
Recently we had been bitten by a Systemd limitation at the “Tasks” created per-unit ie., process. This includes both the kernel threads and user-space threads, with each thread counting individually.
Am writing this blog as a reference for someone who might come across this limitation.
We have been actively working on migration DB instances, from one DC to the newly built DC .The instances on the newer DC were provisioned with the latest hardware and latest Debian OS. Below is the detailed spec of the system.
RAM : 244G
Core : 44Core
HardDisk. : SSD
IOPS : 120K
OS : Debian GNU/Linux 9 (stretch)
Kernel. : 4.9.0-8-amd64
MySQL Version : 5.6.43-84.3-log Percona Server (GPL)
We had setup MySQL on this machine, with all optimal configurations to perform the NFR(Non-Functional Requirement) Testing. The test was performed using Jmeter and we monitored the performance of the db server with PMM.
The connection limit (max_connections) was set in the DB servers as 15k . We were doing a series of test by increasing the no.of app boxes, which increases the number of threads connecting to MySQL Server. When the connection reach 6.5k to 7k mark we started to observer a few errors in the application log , mostly related to connections failures.
Previously we had a limitation with open files limit (ulimit) which affects our connection and MySQL performance and blogged it too.
As you can see in the below graph there is some discontinuity at 7K connection, this clearly shows that we are hitting a resource limit.
Error Description:
We started to debug the issue. At first place we had checked the mysql error log, we could see the below error.
The “errno=11” gives us the clue that its a system (kernel) related issue at the first sight.
The task limit hit can be observed in Systemctl status for MySQL service.
What is TaskMax?
Below is the definition from man page:
Specify the maximum number of tasks that may be created in the unit. This ensures that the number of tasks accounted for the unit stays below a specific limit. This either takes an absolute number of tasks or a percentage value that is taken relative to the configured maximum number of tasks on the system. If assigned the special value “infinity”, no tasks limit is applied.
The system default for this setting may be controlled with DefaultTasksMax=N
Analysis
To reproduce the issue we had restarted the DB servers, in order to flush the connections. As expected we had the same limitation at the same level of connections(6.5-7k)
After a few analysis we found that this limitation was imposed by “systemd”, with respect to its release version “v228”, the task limit for all services would be limited to a value of “512”
We checked our systemd version as below and found the version to be greater than V228
Fix:
Now let’s proceed to see how to increase this limit, since this would be a blocker for high concurrent environment.
The Task limit can be increased both at the system level as well as at the service level.
System-level:
Increasing the limit at system level, affects all the process running.
Let us view the Task limit on process at OS level
Increasing the limit at the OS level (systemd) applies to all the process running, setting at system level is online, does not require a restart and applied immediately
Edit the systemd conf file as below, with the required value of Taskmax
Then proceed to reload the system config as below
Now you can see the increased limit with the process of mysql as below
The downside of setting in the system-level is that, it might cause a race situation with other multi-threaded process if its on the same machine as the DB. If its a dedicated DB machine this would be the quickest method to fix the issue online.
Process-level
Now lets see to set the limit at the process level, edit the service script of a process say mysql.service and add the below lines under the service tag as below
Note by increasing the limit at process-level(service) needs a restart/reload of service.
General Guide lines:
- Ensure needed OS limits are set in MySQL system. Do not trust Kernel defaults, they are prone to change.
- Compute your max_connections, based on the no.of.connections per app boxes and also set the TaskMax accordingly.
- Set the time-out values accordingly in DB to close inactive client connections.
- If you don’t have a control over the connections made by application, I would recommend to have proxysql which does connection pooling & multiplexing.
Don't let database management headaches distract you from your core business. Mydbops offers comprehensive MySQL services, including expert configuration and performance optimization. Let us handle the complexities while you focus on growth. Contact Us Today.
{{cta}}
Featured Image Courtesy by Clint Adair on Unsplash