【Day 35】Linux-Mysql错误总结
(一)MySQL 基础操作与服务故障类
连接层错误(客户端与服务器的连接建立失败)
解决 socket 路径、文件存在性及服务可用性问题。
1、MySQL 客户端连接失败(报错 “Can't connect to local MySQL server throgh socket...”)
- ①确认mysql启动②查找实际socket路径(在mysql配置文件中)
- grep 'socket' /etc/mysql/my.cnf /etc/my.cnf /etc/mysql/mysql.conf.d/mysqld.cnf
- ③ 如果 socket 文件位置与客户端默认查找的位置不一致则手动指定
- mysql -u 用户名 -p --socket=/实际的socket路径
- ④确保 MySQL 进程,客户端有权限创建和访问 socket 文件。msyql:mysql
- ls -ld /var/run/mysqld/
- ls -l /var/run/mysqld/mysqld.sock
2、多路径存在 mysql.sock 的情况确认
①搜索系统中所有名为 mysql.sock 的文件
- sudo find / -name "mysql.sock" 2>/dev/null //
②方法一:确认当前 MySQL 实例实际使用的 socket 路径
- grep -r "socket" /etc/mysql/ /etc/my.cnf /etc/mysql/mysql.conf.d/ 2>/dev/null
方法二:登录 MySQL 实例查询
- SHOW VARIABLES LIKE 'socket';
③ 多 socket 文件的原因
- 多个 MySQL 实例共存:系统中可能运行着多个 MySQL 服务(如官方版与第三方包、不同版本),每个实例生成独立的 socket 文件。
- 历史残留文件:旧版本 MySQL 卸载不彻底,遗留了未删除的
mysql.sock
。 - 配置修改后未清理:修改 socket 路径后,旧路径的 socket 文件未删除。
- 权限问题导致的残留:MySQL 服务异常退出时,可能未自动清理 socket 文件。
④ 停止多余的服务(假设服务名为 mysql2) 删除对应的 socket 文件
- sudo systemctl stop mysql2
- sudo rm -f /path/to/unused/mysql.sock
⑤ 统一客户端与服务端的 socket 路径(在客户端配置文件)
[client] socket = /var/run/mysqld/mysqld.sock # 与服务端配置一致
⑥ 重启 MySQL 服务确保 socket 正确生成
sudo systemctl restart mysql # 验证 socket 文件是否存在 ls -l /var/run/mysqld/mysqld.sock
服务层错误(MySQL 服务自身启动 / 运行失败)
聚焦服务启动 / 重启失败,核心是权限和配置正确性。
1、MySQL 服务启动失败(报错 “权限不够(Error: 13)”)
①找到权限不足的具体文件或目录(在错误日志中)
- sudo tail -f /var/log/mysql/error.log
Can't create/write to file '/path/to/file' (Errcode: 13 - Permission denied)
②查看数据目录权限 # 正确的权限应为:属主和属组都是 mysql,权限至少为 700
- ls -ld /var/lib/mysql/
③排查 SELinux/AppArmor 等安全机制的限制、检查 MySQL 运行用户
2、MySQL 停服改配置后重启卡住的处理
- sudo tail -f /var/log/mysql/error.log //查看 MySQL 错误日志
配置修改不当(如参数冲突、权限错误)导致服务重启时进程阻塞。
3、MySQL 首次启动自动初始化规则及目录修改触发条件
首次启动时自动初始化数据目录、系统表等,目录修改可能触发重新初始化逻辑。
4、其他触发 MySQL 初始化的操作(删关键文件 /--initialize 参数)
删除数据目录关键文件或使用初始化参数,会触发服务重新初始化,可能影响服务启动。
权限验证错误(连接已建立,但权限校验失败)
围绕账号、密码、主机匹配及权限授予展开。
1、MySQL 登录被拒(报错 “Access denied for user 'root'@'localhost'”)
① 密码是否正确 ② 检查登录主机是否匹配 ③重置 root 密码(忘记密码或密码错误)
停止 MySQL 服务步骤--跳过权限验证启动 MySQL--无密码登录并修改密码--重启 MySQL 服务
④MySQL 8.0 默认使用 caching_sha2_password
认证插件,而部分旧客户端(如 Navicat 旧版本)不支持,会导致登录失败。可修改为旧插件
⑤检查用户是否被锁定
- SELECT user, host, account_locked FROM mysql.user WHERE user='root'; # 若 account_locked 为 Y,执行解锁
- ALTER USER 'root'@'localhost' ACCOUNT UNLOCK; FLUSH PRIVILEGES;
2、从库复制权限不足(ERROR 1227: Access denied,普通用户执行 STOP SLAVE)
① 使用 REPLICATION SLAVE ADMIN 权限
- mysql -u root -p
- GRANT REPLICATION SLAVE ADMIN ON *.* TO 'username'@'%';
- FLUSH PRIVILEGES;
//授权时尽量指定具体主机(如 'username'@'192.168.1.100'
),避免使用 %
允许所有主机访问。
3、主从复制时出现 ERROR 1045 (28000): Access denied for user 'repl'@'slave_ip' (using password: YES) 错误
① 检查主库复制账号是否存在及密码是否正确
- SELECT user, host, authentication_string FROM mysql.user WHERE user = 'repl';
② 在从库测试连接主库 (登录失败,说明密码错误或账号不存在,需在主库重新配置)
- mysql -h 主库IP -u repl -p
③检查从库复制配置中的账号密码
- STOP SLAVE;
- CHANGE MASTER TO MASTER_HOST = '主库IP', MASTER_USER = 'repl', MASTER_PASSWORD = '正确的密码', MASTER_LOG_FILE = '主库当前binlog文件',MASTER_LOG_POS = 主库当前binlog位置;
- START SLAVE;
- SHOW SLAVE STATUS\G
④ DNS 反向解析,
- SET GLOBAL skip_name_resolve = ON; //主库执行:临时关闭 DNS 反向解析
- 在从库重新执行
START SLAVE
,若错误消失,说明是反向解析问题 - 修改主库配置文件
- [mysqld] skip_name_resolve = ON # 添加此行,禁用 DNS 反向解析
⑤确保网络和防火墙允许从库访问主库 3306 端口
4、健康检查用户连接错误(monitor 用户连接后端库被拒)
- 原因:monitor 账号不存在、密码错误、主机权限未开放,或网络 / 防火墙限制。
配置层错误(参数配置不当导致功能异常)
服务已启动且连接正常,但因配置参数错误导致功能失效
关注参数生效规则、版本兼容性及系统变量特性。
1、GTID 配置不生效(gtid_mode=OFF,改配置未重启)
- 原因:修改 GTID 模式后未重启服务,导致参数未生效。
validate_password 变量含义 / 配置解读(MEDIUM 策略)
说明:密码验证插件的参数配置,控制密码强度要求(如长度、复杂度)。
validate_password 变量格式区别(. 与_,版本兼容性)
说明:不同 MySQL 版本中密码验证变量的命名格式差异,影响配置生效。
带_的 validate_password 变量能否删除(系统兼容项,不可删)
(二)MySQL 数据备份与恢复类
1、备份 SQL 文件导入无效果(文件空 / 损坏 / 路径错 / SQL 语法错)
①文件为空或损坏
- ls -lh backup.sql
- head -n 10 backup.sql
②文件路径错误:使用绝对路径导入,确保 MySQL 进程有权限读取文件
③SQL 语法错误:查看错误日志定位具体错误行:grep "ERROR" /var/log/mysql/error.log
2、误删数据后的备份与恢复方法(备份剩余数据 + 备份 / 二进制日志 / 第三方工具)
(1)利用全量备份 + 二进制日志恢复
①恢复全量备份到故障前状态
# 假设全量备份为 full_backup.sql mysql -u root -p 数据库名 < full_backup.sql
②找到全量备份对应的二进制日志位置
grep "CHANGE MASTER TO" full_backup.sql
③导出从备份点到误删前的二进制日志
mysqlbinlog --start-position=154 --stop-datetime="2024-08-27 10:00:00" /var/log/mysql/binlog.000003 >增量日志.sql
④导入增量日志
mysql -u root -p 数据库名 < 增量日志.sql
(2)无备份但开启二进制日志:直接通过 binlog 恢复
①mysql -u root -p -e "SHOW BINARY LOGS;" # 分析日志内容,定位误删语句
mysqlbinlog /var/log/mysql/binlog.000003 | grep -i "DELETE FROM 表名"
②生成反向 SQL(跳过误删操作或执行反向语句):
- 若为 DELETE,可提取对应 INSERT 语句恢复;
(三)MySQL 表结构与约束类
文件与存储引擎类(核心:表文件含义、缺失与结构关联)
1、表空间缺失(报错 “Tablespace is missing”,.ibd 文件丢失 / 损坏)
解释:InnoDB 表的表空间文件(.ibd
)丢失或损坏,导致 MySQL 无法加载表数据。.ibd
是 InnoDB 独立表空间文件,存储表数据和索引,若误删、磁盘损坏或迁移时遗漏该文件,会触发此错误。
外键约束类(核心:外键创建 / 删除 / 数据操作的约束冲突)
1、删除表因外键约束失败(报错 “referenced by a foreign key constraint”)
解释:要删除的表是 “主表”,有其他 “子表” 通过外键关联它(子表外键引用主表主键),MySQL 为保证数据一致性,禁止直接删除被引用的主表,需先删除子表或解除外键约束。
2、创建外键报错 “incompatible”(tid 字段 UNSIGNED 属性不一致)
解释:外键字段与引用的主键字段 “数据属性不兼容”—— 子表外键 tid
若为 UNSIGNED
(无符号),主表被引用的 tid
必须也是 UNSIGNED
;若一方有、一方无,MySQL 判定类型不匹配,拒绝创建外键。
3、添 / 更数据报错 “cannot add or update a child row”(子表外键值主表不存在)
解释:子表插入 / 更新数据时,外键字段的值在主表中不存在(违反 “外键引用完整性”)。例如:子表(订单表)外键 user_id=100
,但主表(用户表)中无 user_id=100
的记录,MySQL 阻止操作以避免数据孤立。
表设计与数据操作类(核心:建表、插数、查询的具体实现)
语法转换与错误修正类(核心:跨数据库语法适配、建表 / 查询错误修复)
(四)MySQL 查询与 SQL 语法类
1. 语法报错
-
先查关键字 / 命令格式:确认命令结构完整无多余空格、关键字拼写正确、标点为英文格式;
-
再查对象名匹配性:核对表 / 字段名与数据库实际结构一致,别名在查询中已定义且作用域正确,含特殊字符的对象名用反引号包裹;
-
最后查查询结构逻辑:确保 SELECT/FROM/WHERE/GROUP BY 等子句完整,GROUP BY 与 SELECT 字段匹配,子查询返回结果符合关联要求。
(1)关键字 / 命令格式错误(语法规则违反)
① 命令关键字空格 / 拼写错误
示例:SHOW SLAVE Hosts; 报错(多余空格 + 关键字小写)、show database user 报错(语法结构错误)。
原因:MySQL 关键字需遵循固定格式:无多余空格、命令结构完整(如查看用户需 SELECT user FROM mysql.user,而非 show database user),且关键字大小写不敏感但格式需规范。
② 标点符号错误
示例:字段列表多逗号(如 SELECT id, name, FROM student)、中文标点(如用 “,” 代替 “,”、“()” 代替 “()”)、占位符 / 括号不匹配。
原因:MySQL 仅识别英文标点,且语法解析对 “逗号、括号” 敏感 。 多逗号会导致解析中断,中文标点被判定为非法字符,最终触发 1064 语法错。
③ 注释特殊字符干扰
示例:注释中含 # -- 外的特殊字符(如 /* 注释内容@# */)导致 SQL 解析失败。
原因:MySQL 注释格式有严格限制(# 单行注释、-- 单行注释需加空格、/* */ 多行注释),注释内若含未转义的特殊字符,可能被误认为 SQL 语句一部分,引发解析错误。
(2)对象名(表 / 字段 / 别名)错误(标识符无法识别)
① 字段名拼写 / 格式错误
示例:“查卖笔记本商店 ID” 报错(实际字段为 ID,写为 “商品 ID” 含空格)、Unknown column 's. 商店 ID'(字段名含空格未用反引号包裹)。
原因:字段名若含空格、特殊字符(如中文),需用反引号 ` 包裹(如 `商店 ID`);直接写 “商品 ID” 会被 MySQL 拆分为 “商品” 和 “ID” 两个未知字段,触发 1054 未知列错误。
② 表 / 别名未定义 / 不匹配
示例:表别名未定义(如 SELECT t.name FROM student 中 t 未关联表)、子查询用外部表别名(如子查询中用 t.TID,但 t 是外部查询的表别名,子查询内未定义)、子查询改原表名仍报错(如未关联 tutors 表却用其字段)。
原因:表别名需在 FROM/JOIN 中定义(如 FROM tutors t),且作用域仅限当前查询层级 —— 子查询无法直接使用外部查询的别名,未关联的表其字段也无法被识别,均会触发 1054 错误。
③ 字段 / 表名混淆
示例:“查卖笔记本商店 ID” 中,误将 “商品表” 字段写为 “商店表” 字段(如实际商品表存商品类型,却从商店表查 “笔记本” 相关字段)、表名拼写错(如 FROM studnet 代替 student)。
原因:查询时引用的表 / 字段与实际数据库结构不匹配,MySQL 无法在指定表中找到对应字段,或无法找到指定表,导致报错。
(3)查询结构不完整 / 逻辑错误(语法逻辑违反)
① 查询核心子句缺失
示例:查询结构缺 FROM(如 SELECT id, name WHERE age>18)、子查询缺 FROM(如 SELECT (SELECT name WHERE id=1))。
原因:SELECT 查询需 FROM 子句指定数据来源表(除非是无表查询如 SELECT 1+1),缺失 FROM 会导致 MySQL 无法定位数据,直接报错。
②GROUP BY 用法错误
示例:GROUP BY 单独使用(无 SELECT 对应字段)、未按非聚合字段分组(如 SELECT t.TID, t.Tname, SUM(score) FROM test GROUP BY t.TID,缺 t.Tname 分组)、HAVING 子句处理不当(如 HAVING score>90 中 score 未聚合且非分组字段)。
原因:MySQL 开启 ONLY_FULL_GROUP_BY 模式时,SELECT 中非聚合字段必须全部在 GROUP BY 中;GROUP BY 需配合 SELECT 聚合 / 分组字段使用,单独使用或字段不匹配会触发语法错,且可能导致结果逻辑错误(如未分组字段返回随机值)。
③ 子查询逻辑错误
示例:子查询 HAVING 子句返回多列(如 SELECT * FROM student WHERE EXISTS (SELECT id, name FROM score HAVING avg>80))、子查询结果与外部查询不匹配(如用 = 关联返回多列的子查询)。
原因:HAVING 子句用于过滤分组结果,需配合 GROUP BY 且返回单值;子查询若用 = 与外部字段关联,需确保子查询仅返回一列一行,多列 / 多行会导致语法解析失败。
2. 查询逻辑与结果异常
(1)索引使用异常:联合索引失效
核心是未遵循联合索引的使用规则,导致索引无法生效、查询效率下降。
当联合索引(如idx_col1_col2_col3
)遇到以下情况时会失效:
-
未遵循 “最左前缀原则”(如仅用右侧列
col2
/col3
过滤,跳过左侧col1
); -
对索引列使用函数(如
DATE(col1)='2024-01-01'
),破坏索引结构; -
发生隐式类型转换(如索引列
col1
为INT
,查询用col1='123'
字符串匹配),无法匹配索引格式。
(2)查询结果不符合预期:数据 / 条件匹配错误
此类问题均因 “查询条件不精准” 或 “数据关联异常”,导致结果与业务需求偏差,具体分两类
① 结果范围过大(返全部 / 多余数据)
如 “查卖笔记本商店 ID 返全部”“商店 1 有铅笔库存返 1-3”,本质是筛选条件未精准锁定目标:
-
要么 “商品标识错误”(如笔记本 / 铅笔的 ID / 名称写错,匹配到所有商品);
-
要么 “数据关联异常”(如库存表中所有商店都关联了目标商品,或未加商店 ID 筛选条件);
-
或 “子查询逻辑错误”(子查询未返回有效筛选结果,导致主查询无法过滤)。
② 结果缺失(部分数据无值)
如 “查询部分课程无平均分”,核心是左连接的特性与数据缺失共同导致:
-
用 “课程表左连接成绩表” 时,若某课程在成绩表中无记录,左连接会保留课程信息,但成绩字段为NULL;
-
而AVG()函数会忽略NULL,最终该课程无平均分结果,表现为 “结果缺失”。
3. SQL 函数与语法知识
(1)函数用法类
-
SUM 函数写法与大小写
-
写法:
SUM(列名/表达式)
,函数名与括号间可加空格(如SUM (price*num)
),括号内支持列名或计算表达式(如统计总金额SUM(price*quantity)
)。 -
大小写:MySQL 中不强制函数名大写,
SUM()
与sum()
效果一致,仅为代码规范建议大写以区分关键字。
-
-
SELECT 1 返回 TRUE 与 WHERE TRUE 含义
-
SELECT 1
:查询结果返回一个值为1
的单列数据,本质是返回 “逻辑真”(非空结果即代表条件成立),常用于EXISTS
子查询中判断 “是否存在满足条件的记录”。 -
WHERE TRUE
:WHERE
子句中条件恒为真,会查询表中所有记录(类似WHERE 1=1
),常用于动态拼接 SQL 时避免开头多逗号的问题(如后续可灵活追加AND 条件
)。
-
(2)条件查询与逻辑运算符类
-
NOT EXISTS 定义 / 语法 / 原理 / 场景
-
定义:判断子查询是否 “无满足条件的记录”,若子查询返回空,则
NOT EXISTS
结果为TRUE
,否则为FALSE
。 -
语法:
SELECT 列 FROM 主表 WHERE NOT EXISTS (子查询);
。 -
原理:子查询不返回具体数据,仅判断 “是否存在记录”,效率高于
NOT IN
(避免NULL
值影响)。 -
场景:查询 “无关联数据的记录”,如 “未下单的用户”(
SELECT * FROM user u WHERE NOT EXISTS (SELECT 1 FROM order o WHERE o.user_id = u.id)
)。
-
-
NOT 逻辑运算符用法
-
作用:对条件结果取反,仅作用于单个布尔条件(如
NOT (price > 10)
等价于price <= 10
)。 -
常见场景:结合
IN
(NOT IN
,查 “不在指定范围内的记录”)、EXISTS
(NOT EXISTS
)、BETWEEN
(NOT BETWEEN
)等,如SELECT * FROM product WHERE NOT category IN ('文具', '玩具')
。
-
(五)ProxySQL 相关问题类
ProxySQL 连接与命令报错类
1. ProxySQL 管理端连接报错
-
问题现象:使用
mysql -uadmin
连接管理端时,系统默认寻找本地 socket 文件,导致连接失败。 -
原因与解决:ProxySQL 管理端默认监听端口 6032,需显式指定端口,正确命令为
mysql -uadmin -P6032 -h127.0.0.1
(需补充密码时加-p
)。
2. mysql_server_connect_log 查询报错
-
问题现象:查询连接日志表
mysql_server_connect_log
时,使用time_start
或time
字段提示不存在。 -
原因与解决:该表中存储时间的字段实际名为 time_start_us(微秒级时间戳),需用此字段查询。
3. stats_mysql_query_digest 查询报错
-
问题现象:执行查询时提示
Unknown database 'stats'
。 -
原因与解决:
stats_mysql_query_digest
属于stats
数据库下的表,需先显式指定数据库(如USE stats;
),再执行查询。
ProxySQL 核心配置与表结构类
1. mysql_users 表核心字段含义
字段名 | 作用 |
---|---|
| 控制用户是否启用:值为 1 表示用户可用于连接 ProxySQL,0 表示禁用该用户。 |
| 控制事务路由一致性:值为 1 时,同一事务的所有 SQL 会路由到同一后端节点,避免事务跨节点问题,与 |
2. ProxySQL 用户与主库用户关系
-
核心规则:ProxySQL 中配置的用户(
mysql_users
表),其用户名、密码需与后端主库的用户 完全一致。 -
影响:若不一致,ProxySQL 转发连接请求时会因主库身份验证失败,导致客户端连接报错。
3. ProxySQL 不支持的操作
-
不支持
DESCRIBE
命令:查看表结构需用SHOW COLUMNS FROM 表名;
替代。 -
无
information_schema.columns
表:ProxySQL 不兼容 MySQL 原生的information_schema
库,需通过SHOW COLUMNS
查看字段信息。
4. 不同 LOAD/SAVE 命令区别
-
作用:用于将配置在 “磁盘文件”“运行时内存”“管理端内存” 间同步,对应不同配置模块:
-
规则类(如
mysql_query_rules
):LOAD MYSQL QUERY RULES FROM DISK/RUNTIME
;SAVE MYSQL QUERY RULES TO DISK/RUNTIME
; -
变量类(如全局变量):
LOAD MYSQL VARIABLES FROM DISK/RUNTIME
;SAVE MYSQL VARIABLES TO DISK/RUNTIME
; -
管理配置(如
mysql_users
):LOAD MYSQL USERS FROM DISK/RUNTIME
;SAVE MYSQL USERS TO DISK/RUNTIME
。
-
ProxySQL 路由与查询分析类
1. 路由规则修改问题
- 问题场景:向
mysql_query_rules
表插入路由规则后发现错误(如规则条件写错)。 - 解决方式:ProxySQL 无 “修改规则” 的直接命令,需先通过
DELETE FROM mysql_query_rules WHERE 条件;
删除错误规则,或用UPDATE
修正字段值,再执行LOAD MYSQL QUERY RULES TO RUNTIME; SAVE MYSQL QUERY RULES TO DISK;
生效。
MySQL 从库问题类
1、从库 IO 线程启动失败(Slave_IO_Running: No)
-
问题现象:查看从库状态(
SHOW SLAVE STATUS\G
)时,Slave_IO_Running
字段值为 No,IO 线程未启动。 - 常见原因:
master_log_file
配置错误,即从库指定的主库二进制日志文件名前缀错误(如主库实际日志为mysql-bin.000001
,从库误写为master-bin.000001
)。 - 解决方向:重新在从库执行
CHANGE MASTER TO
命令,指定正确的master_log_file
和master_log_pos
(主库当前日志位置),再启动从库线程(START SLAVE;
)。
(六)版本差异类
MySQL 5.X(以 5.7 为代表)与 8.0 在用户创建和授权上的核心区别,主要源于 8.0 对权限管理逻辑的重构(更严格的权限分离、默认加密升级等),具体可从 4 个关键维度简单解释:
1. 操作逻辑:“创建用户” 与 “授权” 是否可合并
-
MySQL 5.X:支持 “创建用户” 与 “授权” 合并为一条命令,无需先单独创建用户。
示例:直接通过授权语句自动创建用户(若用户不存在)-- 5.X 支持:创建 test 用户并授权,无需提前 CREATE USER GRANT SELECT ON db1.* TO 'test'@'localhost' IDENTIFIED BY '123456';
-
MySQL 8.0:强制 “先创建用户,再授权”,不允许通过
GRANT
直接创建用户(IDENTIFIED BY
无法在GRANT
中使用)。
示例:必须分两步执行-- 8.0 必须先创建用户 CREATE USER 'test'@'localhost' IDENTIFIED BY '123456'; -- 再执行授权 GRANT SELECT ON db1.* TO 'test'@'localhost';
2. 默认认证插件:密码加密方式不同
-
MySQL 5.X:默认使用
mysql_native_password
插件,密码加密算法较简单(基于 SHA-1)。
(若需兼容旧客户端,5.X 通常无需额外配置插件) -
MySQL 8.0:默认使用
caching_sha2_password
插件,密码加密算法更安全(基于 SHA-256),但可能存在旧客户端兼容问题(如低版本 Navicat、JDBC 驱动)。
若需兼容 5.X 客户端,需手动指定旧插件:-- 8.0 创建兼容 5.X 的用户(指定 mysql_native_password) CREATE USER 'test'@'localhost' IDENTIFIED WITH mysql_native_password BY '123456';
3. 权限回收:REVOKE
对 “隐式创建用户” 的处理
-
MySQL 5.X:若用户是通过
GRANT
隐式创建的(未手动CREATE USER
),执行REVOKE ALL
后,用户会被自动删除(因无独立用户记录)。 -
MySQL 8.0:因强制 “先创建用户”,用户是独立存在的,
REVOKE
仅回收权限,不会删除用户;需单独执行DROP USER
才能删除用户。
4. 角色功能:官方角色支持差异
-
MySQL 5.X:无官方 “角色” 功能(无法创建角色并批量授权),若需批量管理权限,需手动维护相同权限的用户,操作繁琐。
-
MySQL 8.0:新增官方角色功能,可创建角色、给角色授权,再将角色赋予用户,简化批量权限管理。
示例:-- 8.0 创建角色并授权 CREATE ROLE 'read_role'; -- 创建角色 GRANT SELECT ON db1.* TO 'read_role'; -- 给角色授权 GRANT 'read_role' TO 'test'@'localhost'; -- 将角色赋予用户