How to create, modify, and drop MySQL users: CREATE USER syntax, privilege levels, GRANT and REVOKE, roles in MySQL 8.4, and least-privilege best practices.
Use this file to discover all available pages before exploring further.
VillageSQL is a drop-in replacement for MySQL with extensions.
All examples in this guide work on VillageSQL. Install Now →
MySQL’s access control model separates authentication (who you are) from authorization (what you can do). You create a user account, then grant privileges to it separately.
-- Read-only access to one databaseGRANT SELECT ON myapp.* TO 'alice'@'localhost';-- Full access to one databaseGRANT ALL PRIVILEGES ON myapp.* TO 'alice'@'localhost';-- Specific privileges on one tableGRANT SELECT, INSERT, UPDATE ON myapp.orders TO 'alice'@'localhost';-- Global privilege (all databases)GRANT PROCESS ON *.* TO 'alice'@'localhost';
The privilege object uses database.table notation:
REVOKE INSERT ON myapp.* FROM 'alice'@'localhost';REVOKE ALL PRIVILEGES ON myapp.* FROM 'alice'@'localhost';
Revoking a privilege that was never granted returns ERROR 1141: There is no such grant defined for user. The user retains any privileges granted at other levels — revoking SELECT ON myapp.* does not remove SELECT ON myapp.orders if that was granted separately.
Roles are named collections of privileges. Instead of granting individual privileges to each user, grant a role.
-- Create a roleCREATE ROLE 'app_reader', 'app_writer';-- Grant privileges to the roleGRANT SELECT ON myapp.* TO 'app_reader';GRANT SELECT, INSERT, UPDATE, DELETE ON myapp.* TO 'app_writer';-- Grant the role to a userGRANT 'app_reader' TO 'alice'@'localhost';GRANT 'app_writer' TO 'bob'@'%';
Users must activate a role to use its privileges (or set it as a default):
-- Activate in sessionSET ROLE 'app_reader';-- Set default role so it activates automatically on loginSET DEFAULT ROLE 'app_reader' TO 'alice'@'localhost';
Dropping a user automatically revokes all their privileges and removes them from all roles. If the user is currently connected, the session continues until it ends.
In MySQL 8.0, all changes via CREATE USER, GRANT, REVOKE, and ALTER USER take effect immediately — no FLUSH PRIVILEGES needed. FLUSH PRIVILEGES is only necessary if you modify the grant tables directly with INSERT/UPDATE (which you shouldn’t do).
What’s the difference between localhost and 127.0.0.1?
localhost in MySQL refers to the Unix socket connection (local file socket), not the network loopback. 127.0.0.1 is the TCP loopback. If your client connects via TCP even on the same machine, use 127.0.0.1 as the host restriction.