LVE caps PHP, SSH, and cron, but it doesn't touch MySQL. On a shared cPanel server, that leaves the single most common cause of "the whole server is slow" tickets — one customer's bad query, holding open every MySQL connection, blocking everyone else's page loads — completely uncovered.
CloudLinux MySQL Governor (dbctl) is the fix. It caps CPU and IO per database user, runs
in one of four modes, and is included free with every CloudLinux license.
This guide is the practical walkthrough — which mode to pick, what limits to set, and the
two cron-runaway scenarios that catch operators out.
The four modes, ranked by usefulness
MySQL Governor has four modes. Almost everyone running shared hosting wants the same one.
| Mode | What it does | When to use it |
|---|---|---|
abusers | Restricts only users currently violating limits | The default for shared hosting. |
all | Applies limits to every user, all the time | Only when you sell strict tiers and want predictable per-user caps |
single | Restricts one abuser at a time, releases when next abuser appears | Testing only — not for production |
off | Collects stats but enforces nothing | First week after install, while you build a baseline |
The recommended path is two weeks in off — to see who your heavy users actually are with
dbtop and dbctl list — followed by a switch to abusers for production. Skip single
unless you're explicitly debugging Governor itself; it leaves obvious holes during testing.
Step 1 — Install and start in off
If you're already on CloudLinux with dbctl available, skip to step 2. Otherwise:
yum install governor-mysql
service db_governor start
chkconfig db_governor on
Confirm the daemon is running and statistics are being collected:
dbtop
dbtop is the top equivalent for MySQL users — live CPU, IO, queries, and connection
counts per database user. In off mode you still see the data, you just don't restrict
anything yet.
Leave it for a week. You're looking for:
- Which users routinely sit above 30% of one core
- Which users spike to 100% CPU for >30 seconds at a time
- Any user with a sustained IO read rate above 4 MB/s
These are the accounts that will trip your limits later. Note their usernames — you'll either tune them up or have a polite conversation about query optimisation.
Step 2 — Set sensible defaults and switch to abusers
For a general-purpose shared-cPanel server running WordPress, WooCommerce, and the usual PHP CMSs, these defaults are the right starting point:
dbctl set --mode=abusers
dbctl set default \
--cpu=30 \
--read=4096 \
--write=2048 \
--max_user_connections=30
What each value buys you:
- CPU 30 — 30% of one core, averaged over the period. Bursts above are fine; sustained
pegs aren't. This is generous for WordPress and tight enough to catch a
SELECT *on a multi-million-row WooCommerce orders table. - read 4096 / write 2048 — 4 MB/s read, 2 MB/s write throughput per user. Plenty for
legitimate WP-Admin work and backups; not enough for one user to saturate the disk
during an
ALTER TABLEon a large table. - max_user_connections 30 — caps the number of simultaneous MySQL connections per
user. Set this lower than your global
max_connectionsdivided by user count, or one user can still exhaust the connection pool.
Apply, then watch dbctl list-restricted over the next 24 hours. If the same two or three
users keep appearing, you have specific accounts to tune — not a default to change.
Step 3 — Per-user overrides
Once you know your heavy hitters, override their limits individually rather than raising
defaults for everyone. Database usernames in cPanel follow the <user>_<db> convention,
but dbctl operates on the cPanel user prefix, not individual databases:
# Give the cPanel user "acmewp" more headroom
dbctl set acmewp \
--cpu=80 \
--read=8192 \
--write=4096 \
--max_user_connections=60
Revert a user to defaults:
dbctl delete acmewp
List all per-user overrides:
dbctl list
If a customer legitimately needs higher MySQL limits to run their business — a busy forum,
a large WooCommerce store — the standard hosting move is a paid add-on. Create a "Database
Boost" WHM package, and trigger dbctl set from your billing system's post-purchase hook.
Step 4 — Tune the restriction window
Out of the box, Governor restricts a user as soon as they cross a limit and releases them 60 seconds after they drop back under. That's right for most servers; for noisy WordPress traffic patterns you may want to be less twitchy.
Edit /etc/container/mysql-governor.xml:
<limit name="cpu">
<default period='1'>30</default>
<default period='5'>20</default>
<default period='15'>15</default>
</limit>
The three period values are 1-, 5-, and 15-minute moving averages. A user is restricted if they exceed any of them. Setting the 1-minute value higher than the 5- and 15-minute values gives short bursts room to breathe while still catching sustained abusers — which matches how WordPress actually generates load.
After editing:
service db_governor restart
Step 5 — The two cron scenarios that bypass Governor
Governor restricts the MySQL user. Two scenarios sidestep that protection — both are worth knowing about before they wake you up.
Root cron with mysqldump. A backup script running as root, dumping every database,
shows up as the root MySQL user. Governor by default does not restrict root. If your
nightly backups are saturating disk IO, the fix is to run dumps as the cPanel user
(su - cpaneluser -c "mysqldump ...") or schedule them through JetBackup,
not to relax Governor.
Persistent connection pools (e.g. PHP-FPM with mysqlnd_ms). If a connection lives long
enough to span multiple Governor restriction windows, the user can effectively pre-allocate
their full IO budget at the start of each window. This is rare on cPanel (the default
PHP-FPM lifetime is short), but if you've tuned pm.max_requests to 0 for performance,
you've also slightly weakened Governor enforcement.
Common mistakes
- Running in
offforever. "We collect stats but never enforce" is a half-finished install. The whole point of Governor is the throttling — stats without enforcement is just expensive logging. - Restricting root. Some operators add
rootto the restricted list "for fairness". This breaks WHM, cPanel, and your backup scripts. Leave root alone. - Setting
max_user_connectionshigher than the global pool. If your globalmax_connectionsis 300 and you set per-user to 500, the per-user limit is meaningless — the global will hit first and take down everyone. - Forgetting to whitelist your monitoring user. If you use Percona Monitoring,
Datadog's MySQL integration, or any external observer, that user runs frequent
SHOW STATUSqueries that can trip CPU limits. Either give the monitoring user its own high-limit override or whitelist via the XML config.
FAQ
What is the difference between abusers and all mode in MySQL Governor?+
Does MySQL Governor work without CloudLinux OS?+
How do I see which MySQL user is currently being throttled?+
Will MySQL Governor restrict the root user?+
What CPU limit should I set per MySQL user on shared hosting?+
How does MySQL Governor interact with LVE limits?+
Next steps
- The other half of CloudLinux resource control is LVE tuning for shared cPanel servers
- If you haven't yet, the CloudLinux activation and cPanel integration guide covers the install side
- For volume operators evaluating Governor across many servers, see pricing tiers and per-server CloudLinux licensing or contact sales for volume discounts