There exist a class of applications in which you never want them to swap. One such class is a database. Databases will use memory as caches and buffers for their disk areas, and it makes absolutely no sense that these are ever put to swap. The particular memory may hold some relevant data that is not needed for a week until one day when a client asks for it. Without the caching/swapping, the database would simply find the relevant record on disk, which would be quite fast; but with swapping, your service might suddenly be taking a long time to respond.
mysqld
includes code to use the OS / system call memlock
. On Linux, since at least 2.6.9, this system call will work for non-root processes that have the CAP_IPC_LOCK
capability[1]. When using memlock()
, the process must still work within the bounds of the LimitMEMLOCK
limit. [2]. One of the (few) good things about systemd
is that you can grant the mysqld
process these capabilities, without requiring a special program. If can also set the rlimits as you'd expect with ulimit
. Here is an override
file for mysqld
that does the requisite steps, including a few others that you might need for a process such as a database:
[Service]
# Prevent mysql from swapping
CapabilityBoundingSet=CAP_IPC_LOCK
# Let mysqld lock all memory to core (don't swap)
LimitMEMLOCK=-1
# do not kills this process if low on memory
OOMScoreAdjust=-900
# Use higher io scheduling
IOSchedulingClass=realtime
Type=simple
ExecStart=
ExecStart=/usr/sbin/mysqld --memlock $MYSQLD_OPTS
Note The standard community mysql currently ships with Type=forking
and adds --daemonize
in the option to the service on the ExecStart
line. This is inherently less stable than the above method.
UPDATE I am not 100% happy with this solution. After several days of runtime, I noticed the process still had enormous amounts of swap! Examining /proc/XXXX/smaps
, I note the following:
- The largest contributor of swap is from a stack segment! 437 MB and fluctuating. This presents obvious performance issues. It also indicates stack-based memory leak.
- There are zero Locked pages. This indicates the
memlock
option in MySQL (or Linux) is broken. In this case, it wouldn't matter much because MySQL can't memlock stack.