MySQL

MySQL User Permissions Best Practices: Least Privilege and Password Policy

Harden MySQL user permissions with host-scoped grants, validate_password plugin, account locking, and privilege auditing. Essential for SOC2 and PCI-DSS compliance.

JusDB Team
April 25, 2025
Updated June 20, 2026
5 min read

MySQL permissions are often granted too broadly, creating unnecessary security risk. Here is how to implement least-privilege access for production MySQL deployments.

Never Use Root for Applications

sql
-- Create application user with only needed privileges
CREATE USER 'app_service'@'10.0.%' IDENTIFIED BY 'str0ng_p@ss';
GRANT SELECT, INSERT, UPDATE, DELETE ON myapp.* TO 'app_service'@'10.0.%';

-- Read-only analytics user
CREATE USER 'analytics'@'10.0.%' IDENTIFIED BY 'read_p@ss';
GRANT SELECT ON myapp.* TO 'analytics'@'10.0.%';

-- Schema migration user (restricted to deploy window)
CREATE USER 'migrator'@'localhost' IDENTIFIED BY 'mig_p@ss';
GRANT ALTER, CREATE, DROP, INDEX ON myapp.* TO 'migrator'@'localhost';

Restrict by Host

sql
-- 'user'@'%' allows connections from anywhere — avoid in production
-- 'user'@'10.0.0.0/255.255.0.0' limits to subnet
-- 'user'@'app.internal' limits to specific host

-- Check current users and hosts
SELECT user, host, plugin, password_expired
FROM mysql.user
ORDER BY user, host;

Password Policy

sql
-- Enable password validation plugin
INSTALL COMPONENT 'file://component_validate_password';

SET GLOBAL validate_password.policy = STRONG;
SET GLOBAL validate_password.length = 12;
SET GLOBAL validate_password.mixed_case_count = 1;
SET GLOBAL validate_password.number_count = 1;
SET GLOBAL validate_password.special_char_count = 1;

Password Expiry and Account Locking

sql
-- Expire password every 90 days for interactive users
CREATE USER 'dba_user'@'localhost'
  IDENTIFIED BY 'p@ssword'
  PASSWORD EXPIRE INTERVAL 90 DAY;

-- Lock account after 5 failed attempts
ALTER USER 'dba_user'@'localhost'
  FAILED_LOGIN_ATTEMPTS 5 PASSWORD_LOCK_TIME 1;

-- Unlock a locked account
ALTER USER 'dba_user'@'localhost' ACCOUNT UNLOCK;

Audit Overprivileged Users

sql
-- Find users with dangerous global privileges
SELECT user, host
FROM information_schema.user_privileges
WHERE privilege_type IN ('SUPER','FILE','PROCESS','REPLICATION SLAVE')
ORDER BY user;

-- Find users with wildcard host access
SELECT user, host FROM mysql.user WHERE host = '%';

Key Takeaways

  • Scope users to specific hosts — never use '%' for production application users
  • Grant only the DML privileges your app needs — avoid DDL grants for running applications
  • Enable the validate_password component with STRONG policy
  • Audit users with SUPER and FILE privileges — these are high-risk grants

JusDB Can Help

MySQL permission audits regularly reveal critical overprivilege issues. JusDB can harden your MySQL user permissions to compliance standards.

Share this article

JusDB Team

Official JusDB content team

Keep reading

MySQL Explained (2026): InnoDB, 8.4 LTS, Replication & Production Patterns

Everything you need to know about MySQL: storage engines, replication topologies, performance tuning, and cloud deployment. From basics to advanced optimization.

MySQL5 minMay 13, 2026
Read

MySQL binlog Retention, Rotation & Purge: Production Guide (2026)

Configure MySQL binlog retention safely: binlog_expire_logs_seconds, manual purging rules, AWS RDS retention, and the disk-exhaustion failure mode you should monitor for.

MySQL10 minMay 9, 2026
Read

MySQL "Communications Link Failure": Fix wait_timeout, HikariCP & All 8 Timeout Variables

MySQL wait_timeout, net_read_timeout, innodb_lock_wait_timeout and max_execution_time — production tuning rules and the HikariCP alignment trick that prevents 'communications link failure' errors.

MySQL6 minMay 9, 2026
Read