权限不足时lock tables会报错,需显式授予lock tables全局权限;flush tables with read lock需reload权限且绕过read_only;行锁本身不校验权限,但执行前提受权限限制。

权限不足时,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 权限,完全忽略这种“只读但带锁”的中间态。










