MySQL数据库只读锁,网站维护禁止写入操作
网站改版、迁移数据或升级程序时,如果还有用户在提交表单、下单或评论,数据库里就会混入新旧不一致的记录。MySQL数据库只读锁能在维护窗口内阻止所有写入操作,让数据库暂时只接受查询。
本文面向零基础用户,分别给出命令和宝塔面板两种操作方式,并说明如何验证锁定是否生效、维护结束后如何安全解锁。
动手前先确认这三件事
加锁前不检查环境,很容易把自己也锁在外面。
- 确认当前连接账号有足够权限。执行只读设置需要
SUPER或SYSTEM_VARIABLES_ADMIN权限,普通业务账号通常没有。用SHOW GRANTS FOR CURRENT_USER();可以查看当前账号权限。 - 确认没有正在运行的长事务。如果有大查询或未提交的事务,加锁后可能长时间等待甚至超时。先执行
SHOW PROCESSLIST;,看到State列有大量Waiting或运行时间很长的Query,先联系对应人员处理。 - 确认维护窗口和回滚方案。只读锁会影响所有写入业务,建议在低峰期操作,并提前告知相关人员维护起止时间。
命令行方式:设置全局只读
MySQL 5.7及以上版本推荐使用read_only参数,它比全局锁表更温和,不会阻塞所有查询。
登录数据库:
mysql -u root -p
执行只读设置:
SET GLOBAL read_only = ON;
执行后返回Query OK即表示设置成功。
此时普通账号的INSERT、UPDATE、DELETE会被拒绝,但拥有SUPER权限的账号仍可写入。
如果希望连管理员也禁止写入,可以额外执行:
SET GLOBAL super_read_only = ON;
验证是否生效:新开一个终端,用业务账号尝试插入一条测试数据:
INSERT INTO test_table (name) VALUES ('readonly_test');
如果返回ERROR 1290 (HY000):,
The MySQL server is running with the --read-only option so it cannot execute this statement
说明只读锁已生效。
宝塔面板操作路径
不熟悉命令行的用户可以在宝塔面板完成同样操作。
- 登录宝塔面板,左侧菜单点击数据库。
- 找到目标数据库,点击右侧的管理,进入phpMyAdmin。
- 在phpMyAdmin顶部点击SQL标签页。
- 在输入框中粘贴
SET GLOBAL read_only = ON;,点击执行。 - 看到绿色成功提示后,回到网站前台尝试提交一次表单,确认写入被拒绝。
如果面板版本较新,也可以在软件商店找到MySQL,点击设置,在性能调整或配置修改中查看当前read_only状态,但修改建议仍通过SQL执行,避免误改配置文件导致重启后失效。
维护期间容易踩的坑
只读锁不是万能开关,下面几种情况需要特别留意。
- 主从复制环境:在从库上设置
read_only不会影响主库,但如果主库也设置了,从库的复制线程可能报错。建议只在主库操作,或确认复制账号拥有SUPER权限。 - 程序连接池:部分PHP或Java程序在写入失败后会不断重试,导致日志暴涨。维护前可以先暂停相关计划任务或队列消费者。
- 忘记解锁:维护结束后如果只恢复了网站代码却忘了关闭只读,用户会持续无法下单。建议把解锁步骤写进维护清单。
FLUSH TABLES WITH READ LOCK的适用场景:这个命令会阻塞所有表的写入并持有全局读锁,通常用于物理备份。日常维护更推荐read_only,因为它允许查询继续执行,对前台浏览影响更小。
维护结束后如何解锁
确认数据迁移或升级完成后,按相反顺序恢复写入。
SET GLOBAL super_read_only = OFF;
SET GLOBAL read_only = OFF;
如果之前执行过FLUSH TABLES WITH READ LOCK,需要单独执行:
UNLOCK TABLES;
解锁后再次用业务账号插入一条测试数据,能成功写入即表示恢复正常。
同时检查网站前台表单、订单提交等核心功能是否可用。
常见疑问
只读锁会影响网站访问速度吗?
read_only只限制写入,查询不受影响,正常浏览和搜索不会变慢。但如果程序在写入失败后反复重试,可能间接增加服务器负载。
能不能只锁定某一张表?
可以。使用LOCK TABLES 表名 WRITE;会锁定指定表,但这种方式需要当前会话保持连接,断开后锁自动释放,不适合长时间维护。全局只读更稳妥。
设置后为什么管理员还能写入?
read_only对拥有SUPER权限的账号不生效,这是设计行为。如果需要完全禁止,请同时开启super_read_only。
重启MySQL后只读状态会保留吗?
通过SET GLOBAL设置的参数在重启后失效。如果希望永久只读,需要在配置文件my.cnf的[mysqld]段添加read_only=1,但维护场景不建议这样做,以免忘记移除导致业务长期不可写。
维护窗口结束后,记得把只读状态、复制状态和程序日志都复查一遍。
只要按上面的步骤先确认权限和事务,再设置只读并验证,最后按顺序解锁,就能在网站维护期间安全地禁止写入操作,避免数据错乱。