MySQL全局锁类型及使用场景总结
MySQL 中的全局锁主要用于对整个数据库实例施加只读限制,确保操作期间数据的一致性(例如备份)。主要有以下几种:
FLUSH TABLES WITH READ LOCK
(FTWRL)作用: 这是最经典、最严格的全局读锁。
关闭所有打开的表。
对整个数据库实例施加全局读锁。所有数据库的所有表都变为只读状态,阻止任何写操作(
INSERT
,UPDATE
,DELETE
,DDL
等)和显式/隐式的事务提交。阻止新的写连接尝试(新连接可以建立,但执行写操作会被阻塞)。
特点:
严格性: 会阻塞所有正在进行的数据修改语言(DML)和DDL操作,并等待它们完成(或超时)后才获得锁。
阻塞新事务: 获得锁后,会阻止新事务的启动(无论是读还是写事务)。
释放方式: 必须显式使用
UNLOCK TABLES
命令释放。持有锁的会话断开也会自动释放。存储引擎无关: 作用于整个 MySQL 服务器层,对所有存储引擎生效。
主要用途: 获取全局一致性读视图(例如,配合
SHOW MASTER STATUS
记录二进制日志位置做一致性备份)、在非事务性存储引擎(如 MyISAM)上做一致性备份(虽然现在推荐用 InnoDB 和在线备份工具)。风险: 长时间持有会严重阻塞所有写入操作,影响业务可用性
SET GLOBAL read_only = ON
作用: 将整个 MySQL 实例设置为只读模式。
阻止普通用户账户(没有
SUPER
权限)执行写操作(INSERT
,UPDATE
,DELETE
,DDL
)和事务提交。不会影响具有
SUPER
权限的用户(通常是管理员)的写操作。特点:
非严格锁: 它不阻塞正在进行的写操作。它只是阻止新的非
SUPER
用户的写操作尝试。已经开始的写事务可以继续执行直到提交。不影响现有连接: 已经建立的连接,如果正在执行写操作且尚未完成,可以继续执行。
释放方式: 使用
SET GLOBAL read_only = OFF
解除。存储引擎无关: 作用于整个 MySQL 服务器层。
主要用途: 进行数据库维护、防止应用在特定时段(如迁移、报表生成)意外写入数据。通常与
super_read_only
结合使用。风险: 较低,因为
SUPER
用户仍可写入。如果单独使用,不足以完全阻止写入(管理员可能误操作)SET GLOBAL super_read_only = ON
作用: MySQL 5.7.8 引入。在
read_only=ON
的基础上,进一步限制具有SUPER
权限的用户。设置
super_read_only=ON
会自动将read_only
设置为ON
。阻止所有用户(包括
SUPER
用户)执行写操作和事务提交。特点:
最严格的管理性锁: 真正实现整个实例的只读,无人能写(除非先关闭
super_read_only
)。非严格锁(同
read_only
): 同样不阻塞正在进行的事务,只阻止新的写操作尝试。释放方式: 使用
SET GLOBAL super_read_only = OFF
解除(这也会将read_only
设置为OFF
,除非显式设置了read_only=ON
)。存储引擎无关: 作用于整个 MySQL 服务器层。
主要用途: 高可用环境(如主从切换时确保原主库绝对不可写)、需要绝对保证无任何写入的维护场景。是保护主库避免意外写入的推荐方式。
风险: 最低(在阻止写入方面),但仍需注意设置后管理员也无法直接写入
mysqldump
使用--lock-all-tables
选项作用: 当使用
mysqldump
工具备份数据并指定--lock-all-tables
或-x
选项时,在备份开始前,mysqldump
会自动执行FLUSH TABLES WITH READ LOCK
来获取全局读锁。特点: 本质上是工具自动调用了 FTWRL。
用途: 为使用非事务存储引擎的表或在特定场景下获取一致性备份。对于 InnoDB 表,强烈推荐使用
--single-transaction
选项(基于 MVCC 获取一致性视图)代替--lock-all-tables
,以避免全局锁。MySQL Locking Service (
GET_LOCK()
) - 间接/应用层全局锁作用: 使用函数
GET_LOCK('lock_name', timeout)
可以获取一个用户命名的锁。如果锁名相同(如'global_lock'
),并且多个客户端尝试获取,则只有一个客户端能成功,其他客户端会被阻塞(直到超时或锁释放)。特点:
这不是 MySQL 内置的用于数据库一致性的全局锁,而是提供给应用程序使用的协作式锁。
锁的作用域是整个 MySQL 服务器实例(同一个锁名在整个实例内唯一)。
锁的生命周期与会话绑定(会话结束或显式
RELEASE_LOCK()
释放)。需要应用程序逻辑来实现基于此锁的全局协调。
用途: 实现应用层面的全局互斥逻辑(例如,防止多个实例同时执行某个后台任务)。