MySQL 8.0+ 不支持 GRANT SELECT ON .,因全局SELECT隐含访问系统表,违反最小权限原则;须按库粒度授权,如GRANT SELECT ON db_app_xxx.* TO 'ro_user'@'%',并用反引号包裹库名防语法错误。

为什么直接 GRANT ALL ON *.* 不行
批量创建只读账号时,有人会想用 GRANT SELECT ON *.* TO 'user'@'%' 一劳永逸。这在 MySQL 8.0+ 会报错:ERROR 3719 (HY000): 'USAGE' is not supported for users with global privileges。根本原因是:MySQL 8.0 起,USAGE 权限(即“无权限”)是默认隐含的,而显式授予全局 SELECT 会被拒绝,因为全局 SELECT 实际上允许读取系统表(如 mysql.user),违反最小权限原则。
正确做法:按库粒度循环授权
只读账号必须限定到具体数据库,不能跨库通配。假设业务库名都以 db_app_ 开头,可用以下步骤批量生成授权语句:
- 先查出所有目标库:
SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME LIKE 'db_app_%'; - 对每个库执行:
GRANT SELECT ON `db_app_xxx`.* TO 'ro_user'@'%'; - 最后统一执行:
FLUSH PRIVILEGES;
注意反引号必须包裹库名,否则库名含短横线(如 db-app-2024)会导致语法错误;SELECT 权限不包含 SHOW VIEW 或 LOCK TABLES,如有视图需额外加授。
用存储过程自动创建多个账号更稳妥
手动拼 SQL 容易漏库或输错 host。推荐用存储过程一次性建 10 个账号(如 ro_app_01 到 ro_app_10),并统一分配相同权限:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
DELIMITER $$
CREATE PROCEDURE create_ro_users()
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i <= 10 DO
SET @user = CONCAT('ro_app_', LPAD(i, 2, '0'));
SET @sql = CONCAT('CREATE USER IF NOT EXISTS ''', @user, '''@''%'' IDENTIFIED BY ''strong_pwd_2024''');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
<pre class='brush:php;toolbar:false;'>SET @sql = CONCAT('GRANT SELECT ON `db_app_%`.* TO ''', @user, '''@''%''');
PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET i = i + 1;END WHILE; FLUSH PRIVILEGES; END$$ DELIMITER ; CALL create_ro_users();
关键点:GRANT SELECT ON `db_app_%`.* 中的 % 是字面量通配符,不是模糊匹配——它只匹配库名**字面等于** db_app_% 的库(MySQL 不支持 GRANT 中的模式匹配)。所以仍需先查库再逐个授权,上面过程仅适合库名固定、数量少的场景。
密码策略和连接限制别漏掉
只读账号也需防暴力破解和长连接堆积。创建时应同步设置:
- 密码过期:
CREATE USER 'ro_app_01'@'%' IDENTIFIED BY 'pwd' PASSWORD EXPIRE INTERVAL 90 DAY; - 连接数限制:
ALTER USER 'ro_app_01'@'%' WITH MAX_CONNECTIONS_PER_HOUR 100; - 避免使用
IDENTIFIED WITH mysql_native_password(5.7 默认),8.0+ 建议用caching_sha2_password,但需确认客户端支持
最易被忽略的是:未显式 REVOKE 其他权限。如果账号之前存在且有其他权限,GRANT SELECT 不会自动清除旧权限,必须先 REVOKE ALL PRIVILEGES ON *.* FROM 'user'@'%' 再重授。

















