lock tables 权限只能全局授予,必须用 on .;不能按库或表限定,否则报错error 1221;即使只备份单库也须如此授权,且需与select等库级权限分开授予。

LOCK TABLES 权限不能按库授予,必须用 ON *.*
很多人写 GRANT LOCK TABLES ON app_db.* TO 'backup'@'%',结果 MySQL 直接报错 ERROR 1221 (HY000): Incorrect usage of DB GRANT and GLOBAL PRIVILEGES。这是因为 LOCK TABLES 是全局权限(global privilege),MySQL 强制要求它只能在 ON *.* 层级声明,不支持库级或表级限定。
正确写法只有这一种形式:GRANT LOCK TABLES ON *.* TO 'backup_user'@'10.20.30.%'。即使你只打算备份 app_db,也得这么授——它不影响安全性,因为 LOCK TABLES 本身不赋予读、写、删能力,只是允许执行 LOCK TABLES t1 READ 这类语句。
常见误操作:
- 混用
SELECT(库级)和LOCK TABLES(全局)时,误以为可以合并写成一条GRANT ... ON app_db.*—— 实际必须拆开:一条给SELECT, SHOW VIEW, TRIGGER ON app_db.*,另一条单独给LOCK TABLES ON *.* - 用
REVOKE ALL PRIVILEGES ON *.*清理账号后忘了重授LOCK TABLES ON *.*,导致后续备份突然失败 - 在 MySQL 8.0+ 中通过角色赋权,但角色本身没在全局层级被授予
LOCK TABLES,权限不生效
什么时候真正需要 LOCK TABLES 权限?
LOCK TABLES 不是“每次备份都必须”,它的实际触发取决于 mysqldump 的参数组合和存储引擎:
- 显式用了
--lock-tables或--lock-all-tables→ 必须有LOCK TABLES(且通常还需RELOAD配合FLUSH TABLES WITH READ LOCK) - 用了
--single-transaction(InnoDB 默认行为)→LOCK TABLES不会被调用,但若该参数因版本低(mysqldump 会自动 fallback 到锁表逻辑,此时缺权限就直接报错 - 备份含 MyISAM 表 →
--single-transaction无效,LOCK TABLES成为唯一一致性保障手段,必须存在
所以生产环境建议:哪怕主用 --single-transaction,也保留 LOCK TABLES ON *.* 作为降级兜底,避免某次备份因意外 fallback 而中断。
和 SELECT 权限必须同时存在,否则备份仍会失败
只给 LOCK TABLES ON *.*,不配 SELECT,mysqldump 会在第一步就读表时报错:Access denied; you need (at least one of) the SELECT privilege(s)。锁表不是目的,读数据才是核心。
典型权限组合(以备份 app_db 为例):
GRANT SELECT, SHOW VIEW, TRIGGER ON `app_db`.* TO 'backup_user'@'10.20.30.%'GRANT LOCK TABLES ON *.* TO 'backup_user'@'10.20.30.%'- 如需
--master-data或 GTID 信息,额外加:GRANT REPLICATION CLIENT ON *.* TO 'backup_user'@'10.20.30.%'
注意反引号:`app_db` 必须包裹库名,否则库名含短横(如 my-app)会语法报错;而 *.* 不需要引号。
验证 LOCK TABLES 是否真生效,别只信 GRANT 语句
执行完 GRANT 后必须 FLUSH PRIVILEGES,否则权限不加载(尤其在跳过 grant 表启动的实例上更明显)。验证不能只看命令是否执行成功,要登录后手动测:
- 用备份账号连接:
mysql -u backup_user -p -h 10.20.30.5 - 执行:
LOCK TABLES app_db.users READ;—— 成功即说明LOCK TABLES有效 - 再执行:
SELECT COUNT(*) FROM app_db.users;—— 成功说明SELECT也到位
如果第二步失败,检查点包括:库名大小写(Linux 下敏感)、host 匹配是否精确('backup_user'@'10.20.30.%' 无法匹配本地 localhost 连接)、是否漏了 FLUSH PRIVILEGES。
最易忽略的是 host 匹配细节:LOCK TABLES 授权里的 @'10.20.30.%' 和实际连接来源 IP 必须一致,否则权限查不到——这比权限类型错误更难排查。











