mysql权限与表加锁有什么关系_mysql锁与权限管理

来源:这里教程网 时间:2026-02-28 20:49:43 作者:

权限不足时,
LOCK TABLES
会直接报错

不是所有用户都能加表锁。MySQL 要求执行

LOCK TABLES
必须拥有
LOCK TABLES
权限(属于全局权限),且不能是只读账号(
read_only=1
时 super 用户仍可锁,但普通用户会被拒绝)。常见错误:
ERROR 1045 (28000): Access denied for user 'app'@'%' to database 'test'
—— 实际不是库权限问题,而是缺少
LOCK TABLES
权限。

检查权限:运行
SHOW GRANTS FOR CURRENT_USER;
,确认输出中包含
LOCK TABLES
授予权限(需 super 或 grant option):
GRANT LOCK TABLES ON *.* TO 'app'@'%'; FLUSH PRIVILEGES;
注意:MySQL 8.0+ 中,
LOCK TABLES
权限不再隐含在
SELECT
UPDATE
中,必须显式授予
即使有
LOCK TABLES
权限,若当前连接处于事务中(
AUTOCOMMIT=0
),执行
LOCK TABLES
会自动触发隐式提交,导致事务中断——这是极易被忽略的副作用

FLUSH TABLES WITH READ LOCK
需要
RELOAD
权限,且绕过
read_only
限制

全局读锁命令

FLUSH TABLES WITH READ LOCK
不同于普通表锁,它要求
RELOAD
权限(而非
LOCK TABLES
),并且能强制阻塞所有写入——哪怕你已设
read_only=1
,这个命令仍会让 super 用户也无法写,因为它是物理级阻塞。

验证权限:
SELECT Reload_priv FROM mysql.user WHERE User='root' AND Host='%';
返回
Y
才有效
执行后,任何 DML(
INSERT
/
UPDATE
/
DELETE
)、DDL(
CREATE
/
DROP
)都会挂起等待,包括 root 用户
解锁必须用
UNLOCK TABLES
,且只能由同一连接执行;断开连接会自动释放锁,但可能导致备份不一致
该命令会阻塞
mysqldump --single-transaction
的一致性快照起点,所以不要在备份脚本里混用

InnoDB 行锁不受用户权限控制,但权限影响能否触发行锁

行锁(如

SELECT ... FOR UPDATE
)本身不校验权限——只要语句能执行成功,InnoDB 就加行锁。但“能否执行成功”取决于权限:比如没
SELECT
权限,连查询都失败,自然无法加锁;没
UPDATE
权限,
SELECT ... FOR UPDATE
可以执行(因只读),但后续
UPDATE
会报错。

典型陷阱:给应用账号只授
SELECT
权限,却让它执行
SELECT ... FOR UPDATE
—— 看似能跑通,但实际锁住了行,而业务逻辑又没后续更新,导致锁长期滞留
行锁是否生效,还依赖索引:若
WHERE
条件未命中索引,InnoDB 会升级为表锁(甚至全表扫描锁),此时又回到权限和锁粒度双重风险
权限越精细,越容易误判锁行为:例如对某列有
SELECT
权限但无
UPDATE
权限,
SELECT col1 FROM t WHERE id=1 FOR UPDATE
成功加锁,但
UPDATE t SET col2=1 WHERE id=1
直接报错
ERROR 1142 (42000): UPDATE command denied
,锁却没释放

备份/维护场景下,权限与锁的组合最容易出事

线上做逻辑备份、主从切换或数据迁移时,常同时涉及权限变更和锁操作。这时权限配置稍有偏差,就会让锁失效或过度阻塞。

例如用
mysqldump --lock-all-tables
:它内部执行
FLUSH TABLES WITH READ LOCK
,所以 dump 账号必须有
RELOAD
权限,否则报错退出,但 dump 进程可能已部分写入脏文件
再如用
pt-online-schema-change
:它依赖
SELECT
/
INSERT
/
UPDATE
/
DELETE
TRIGGER
权限,若漏授
TRIGGER
,工具会退化为锁表方式,导致业务阻塞
最隐蔽的是权限缓存:修改了
mysql.user
表但忘了
FLUSH PRIVILEGES
,新权限不生效,锁命令看似执行成功,实则未真正加锁(尤其在 MySQL 5.7 及更早版本)

权限本身不控制锁的类型或范围,但它决定了你“有没有资格发起锁操作”。真正危险的不是锁不住,而是锁住了却没人意识到——比如一个只有

SELECT
权限的账号执行了
FOR UPDATE
,锁持续到事务结束,而 DBA 查权限时只看 DML 权限,完全忽略这种“只读但带锁”的中间态。

相关推荐