MySQL作为世界上最流行的开源关系型数据库,在实际生产环境中,合理的用户管理和权限控制是确保数据安全的重要基石。本文将从零开始,手把手教你掌握MySQL的用户管理和权限控制。
用户管理是指在MySQL数据库中创建、删除、修改用户账户,并为这些账户分配适当权限的过程。就像公司的门禁系统一样,不同的员工需要不同的门卡权限,有些人只能进入普通办公区,有些人可以进入机房,而管理员则拥有所有区域的访问权限。
为什么用户管理如此重要?
MySQL安装后默认创建一个超级管理员账户root
,这个账户拥有最高权限,可以:
-- 查看当前用户
SELECT USER();
-- 查看当前用户的权限
SHOW GRANTS;
-- 以root用户身份查看所有权限
SHOW GRANTS FOR 'root'@'localhost';
MySQL将所有用户信息存储在系统数据库mysql
的user
表中。这个表包含了用户名、主机、密码哈希值以及各种权限信息。
-- 切换到mysql系统数据库
USE mysql;
-- 查看user表的结构
DESC user;
-- 查看user表的主要字段
SELECT Host, User, authentication_string FROM user;
-- 方法1:查看所有用户
SELECT Host, User FROM mysql.user;
-- 方法2:查看当前数据库的所有用户
SELECT DISTINCT User FROM mysql.user;
-- 方法3:查看特定用户的详细信息
SELECT Host, User, authentication_string,
Select_priv, Insert_priv, Update_priv, Delete_priv
FROM mysql.user
WHERE User = 'root';
-- 方法4:使用SHOW命令查看用户权限
SHOW GRANTS FOR 'root'@'localhost';
-- 基本语法
CREATE USER '用户名'@'主机名' IDENTIFIED BY '密码';
-- 完整语法
CREATE USER [IF NOT EXISTS] '用户名'@'主机名'
IDENTIFIED BY '密码'
[PASSWORD EXPIRE [DEFAULT | NEVER | INTERVAL N DAY]]
[ACCOUNT [LOCK | UNLOCK]];
主机名说明:
localhost
:只能从本机连接%
:可以从任意主机连接192.168.1.%
:只能从192.168.1.x网段连接192.168.1.100
:只能从指定IP连接MySQL会自动对密码进行哈希加密,不会以明文形式存储。从MySQL 8.0开始,默认使用caching_sha2_password
插件。
-- 查看默认的密码验证插件
SHOW VARIABLES LIKE 'default_authentication_plugin';
-- 创建用户时指定密码验证插件
CREATE USER 'test_user'@'localhost'
IDENTIFIED WITH mysql_native_password BY 'password123';
-- 示例1:创建只能本机登录的用户
CREATE USER 'local_user'@'localhost' IDENTIFIED BY 'local_pass123';
-- 示例2:创建可从任意主机登录的用户
CREATE USER 'remote_user'@'%' IDENTIFIED BY 'remote_pass123';
-- 示例3:创建只能从特定IP登录的用户
CREATE USER 'office_user'@'192.168.1.100' IDENTIFIED BY 'office_pass123';
-- 示例4:创建只能从特定网段登录的用户
CREATE USER 'dept_user'@'192.168.1.%' IDENTIFIED BY 'dept_pass123';
-- 示例5:创建用户并设置密码永不过期
CREATE USER 'app_user'@'%'
IDENTIFIED BY 'app_pass123'
PASSWORD EXPIRE NEVER;
-- 验证用户创建成功
SELECT Host, User FROM mysql.user WHERE User LIKE '%user%';
-- 错误1:ERROR 1396 (HY000): Operation CREATE USER failed
-- 原因:用户已经存在
-- 解决方法:使用IF NOT EXISTS或先删除用户
CREATE USER IF NOT EXISTS 'existing_user'@'localhost' IDENTIFIED BY 'password';
-- 错误2:ERROR 1045 (28000): Access denied
-- 原因:当前用户没有CREATE USER权限
-- 解决方法:使用有足够权限的用户(如root)登录
-- 错误3:密码策略不符合要求
-- 查看密码策略
SHOW VARIABLES LIKE 'validate_password%';
-- 创建符合密码策略的用户
CREATE USER 'strong_user'@'localhost' IDENTIFIED BY 'StrongPass123!';
-- 基本语法
DROP USER '用户名'@'主机名';
-- 删除多个用户
DROP USER '用户1'@'主机1', '用户2'@'主机2';
-- 安全删除(如果用户不存在不会报错)
DROP USER IF EXISTS '用户名'@'主机名';
-- 示例1:删除单个用户
DROP USER 'test_user'@'localhost';
-- 示例2:删除多个用户
DROP USER 'user1'@'localhost', 'user2'@'%';
-- 示例3:安全删除用户
DROP USER IF EXISTS 'maybe_not_exist'@'localhost';
-- 示例4:删除所有测试用户
-- 先查询要删除的用户
SELECT CONCAT('DROP USER ''', User, '''@''', Host, ''';') AS drop_command
FROM mysql.user
WHERE User LIKE 'test_%';
-- 执行生成的删除命令
DROP USER 'test_user1'@'localhost';
DROP USER 'test_user2'@'%';
-- 验证用户删除成功
SELECT Host, User FROM mysql.user WHERE User LIKE 'test_%';
-- 方法1:使用ALTER USER(推荐,MySQL 5.7+)
ALTER USER '用户名'@'主机名' IDENTIFIED BY '新密码';
-- 方法2:使用SET PASSWORD
SET PASSWORD FOR '用户名'@'主机名' = '新密码';
-- 方法3:修改当前用户密码
ALTER USER USER() IDENTIFIED BY '新密码';
-- 或者
SET PASSWORD = '新密码';
在MySQL 8.0及以上版本中,PASSWORD()
函数已被移除,直接使用明文密码即可,MySQL会自动进行哈希处理。
-- MySQL 5.7及以下版本(已过时,不推荐)
SET PASSWORD FOR 'user'@'host' = PASSWORD('new_password');
-- MySQL 8.0及以上版本(推荐)
ALTER USER 'user'@'host' IDENTIFIED BY 'new_password';
-- 示例1:root用户修改其他用户密码
ALTER USER 'app_user'@'%' IDENTIFIED BY 'new_strong_password123!';
-- 示例2:用户修改自己的密码
ALTER USER USER() IDENTIFIED BY 'my_new_password123!';
-- 示例3:修改密码并设置过期策略
ALTER USER 'temp_user'@'localhost'
IDENTIFIED BY 'temp_password123!'
PASSWORD EXPIRE INTERVAL 30 DAY;
-- 示例4:强制用户下次登录时修改密码
ALTER USER 'new_employee'@'%'
IDENTIFIED BY 'initial_password123!'
PASSWORD EXPIRE;
-- 示例5:批量修改密码(生成SQL语句)
SELECT CONCAT('ALTER USER ''', User, '''@''', Host, ''' IDENTIFIED BY ''new_password_', User, ''';') AS alter_command
FROM mysql.user
WHERE User LIKE 'temp_%';
-- 验证密码修改(通过重新登录测试)
-- mysql -u app_user -p -h localhost
MySQL提供了细粒度的权限控制,可以在不同级别设置权限:全局级别、数据库级别、表级别、列级别。
权限名称 | 权限描述 | 适用范围 | 使用场景 |
---|---|---|---|
ALL PRIVILEGES | 所有权限(除GRANT OPTION外) | 全局、数据库、表 | 管理员用户 |
SELECT | 查询数据 | 数据库、表、列 | 只读用户、报表用户 |
INSERT | 插入数据 | 数据库、表、列 | 数据录入员 |
UPDATE | 更新数据 | 数据库、表、列 | 数据维护员 |
DELETE | 删除数据 | 数据库、表 | 数据管理员 |
CREATE | 创建数据库、表 | 全局、数据库 | 开发人员 |
DROP | 删除数据库、表 | 全局、数据库 | 高级管理员 |
ALTER | 修改表结构 | 数据库、表 | 数据库设计师 |
INDEX | 创建、删除索引 | 数据库、表 | 性能优化人员 |
GRANT OPTION | 授权给其他用户 | 对应权限范围 | 权限管理员 |
CREATE USER | 创建用户 | 全局 | 用户管理员 |
RELOAD | 重新加载权限表 | 全局 | 系统管理员 |
SHUTDOWN | 关闭MySQL服务 | 全局 | 系统管理员 |
PROCESS | 查看所有进程 | 全局 | 监控人员 |
FILE | 读写服务器文件 | 全局 | 数据导入导出人员 |
-- 查看所有可用权限
SHOW PRIVILEGES;
-- 查看当前用户权限
SHOW GRANTS;
-- 查看特定用户权限
SHOW GRANTS FOR 'username'@'hostname';
-- 基本语法
GRANT 权限列表 ON 数据库.表 TO '用户名'@'主机名';
-- 完整语法
GRANT 权限列表 ON 数据库.表 TO '用户名'@'主机名'
[WITH GRANT OPTION]
[WITH MAX_QUERIES_PER_HOUR count]
[WITH MAX_UPDATES_PER_HOUR count]
[WITH MAX_CONNECTIONS_PER_HOUR count];
-- 单个权限
GRANT SELECT ON database.table TO 'user'@'host';
-- 多个权限
GRANT SELECT, INSERT, UPDATE ON database.table TO 'user'@'host';
-- 所有权限
GRANT ALL PRIVILEGES ON database.table TO 'user'@'host';
-- 特定列权限
GRANT SELECT (column1, column2), UPDATE (column1) ON database.table TO 'user'@'host';
-- 创建测试环境
CREATE DATABASE company_db;
USE company_db;
CREATE TABLE employees (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL,
email VARCHAR(100) UNIQUE,
department VARCHAR(50),
salary DECIMAL(10,2)
);
CREATE TABLE departments (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
manager VARCHAR(100)
);
-- 示例1:授予数据库的所有权限
CREATE USER 'db_admin'@'localhost' IDENTIFIED BY 'admin_pass123!';
GRANT ALL PRIVILEGES ON company_db.* TO 'db_admin'@'localhost';
-- 示例2:授予只读权限
CREATE USER 'report_user'@'%' IDENTIFIED BY 'report_pass123!';
GRANT SELECT ON company_db.* TO 'report_user'@'%';
-- 示例3:授予特定表的增删改查权限
CREATE USER 'hr_user'@'192.168.1.%' IDENTIFIED BY 'hr_pass123!';
GRANT SELECT, INSERT, UPDATE, DELETE ON company_db.employees TO 'hr_user'@'192.168.1.%';
-- 示例4:授予列级别权限
CREATE USER 'public_user'@'%' IDENTIFIED BY 'public_pass123!';
GRANT SELECT (id, name, department) ON company_db.employees TO 'public_user'@'%';
-- 示例5:授予创建表权限
CREATE USER 'developer'@'localhost' IDENTIFIED BY 'dev_pass123!';
GRANT CREATE, ALTER, INDEX ON company_db.* TO 'developer'@'localhost';
GRANT SELECT, INSERT, UPDATE, DELETE ON company_db.* TO 'developer'@'localhost';
-- 示例6:授予全局权限
CREATE USER 'backup_user'@'localhost' IDENTIFIED BY 'backup_pass123!';
GRANT SELECT ON *.* TO 'backup_user'@'localhost';
GRANT RELOAD, LOCK TABLES ON *.* TO 'backup_user'@'localhost';
-- 示例7:授予权限并允许转授(WITH GRANT OPTION)
CREATE USER 'team_lead'@'%' IDENTIFIED BY 'lead_pass123!';
GRANT SELECT, INSERT, UPDATE ON company_db.* TO 'team_lead'@'%' WITH GRANT OPTION;
-- 示例8:授予权限并设置资源限制
CREATE USER 'limited_user'@'%' IDENTIFIED BY 'limited_pass123!';
GRANT SELECT ON company_db.* TO 'limited_user'@'%'
WITH MAX_QUERIES_PER_HOUR 1000
WITH MAX_CONNECTIONS_PER_HOUR 10;
-- 刷新权限表(使权限立即生效)
FLUSH PRIVILEGES;
-- 验证权限授予成功
SHOW GRANTS FOR 'db_admin'@'localhost';
SHOW GRANTS FOR 'report_user'@'%';
SHOW GRANTS FOR 'hr_user'@'192.168.1.%';
-- 基本语法
REVOKE 权限列表 ON 数据库.表 FROM '用户名'@'主机名';
-- 回收所有权限
REVOKE ALL PRIVILEGES ON 数据库.表 FROM '用户名'@'主机名';
-- 回收GRANT权限
REVOKE GRANT OPTION ON 数据库.表 FROM '用户名'@'主机名';
-- 示例1:回收特定权限
REVOKE INSERT, UPDATE ON company_db.employees FROM 'hr_user'@'192.168.1.%';
-- 示例2:回收数据库的所有权限
REVOKE ALL PRIVILEGES ON company_db.* FROM 'developer'@'localhost';
-- 示例3:回收全局权限
REVOKE RELOAD ON *.* FROM 'backup_user'@'localhost';
-- 示例4:回收GRANT权限
REVOKE GRANT OPTION ON company_db.* FROM 'team_lead'@'%';
-- 示例5:回收列级别权限
REVOKE SELECT (salary) ON company_db.employees FROM 'public_user'@'%';
-- 示例6:完全移除用户的所有权限
REVOKE ALL PRIVILEGES, GRANT OPTION FROM 'limited_user'@'%';
-- 刷新权限表
FLUSH PRIVILEGES;
-- 验证权限回收成功
SHOW GRANTS FOR 'hr_user'@'192.168.1.%';
SHOW GRANTS FOR 'developer'@'localhost';
-- 查看密码策略
SHOW VARIABLES LIKE 'validate_password%';
-- 创建强密码用户示例
CREATE USER 'secure_user'@'localhost' IDENTIFIED BY 'SecurePass123!@#';
-- ❌ 错误做法:给予过多权限
GRANT ALL PRIVILEGES ON *.* TO 'app_user'@'%';
-- ✅ 正确做法:只给必要权限
GRANT SELECT, INSERT, UPDATE ON specific_db.specific_table TO 'app_user'@'%';
-- 查看所有用户及其基本权限信息
SELECT
User,
Host,
Select_priv,
Insert_priv,
Update_priv,
Delete_priv,
Create_priv,
Drop_priv
FROM mysql.user
WHERE User != '';
-- 查看特定用户的所有权限
SHOW GRANTS FOR 'username'@'hostname';
-- 限制用户连接来源
CREATE USER 'secure_user'@'192.168.1.%' IDENTIFIED BY 'SecurePass123!';
-- 而不是使用 '%' 允许任意IP连接
-- 设置连接限制
ALTER USER 'limited_user'@'%'
WITH MAX_CONNECTIONS_PER_HOUR 10
MAX_QUERIES_PER_HOUR 1000;
MySQL的用户管理和权限控制是数据库安全的基础,掌握这些技能对于数据库管理员和开发人员都至关重要。
用户管理
权限控制
安全实践
日常维护
记住:安全无小事,权限需谨慎。合理的用户管理和权限控制不仅保护了数据安全,也为系统的稳定运行提供了保障。
希望这篇教程能帮助你更好地理解和掌握MySQL的用户管理和权限控制!在实际应用中,请根据具体业务需求和安全要求来设计权限方案。