全局锁 (Global Lock)
定义
全局锁作用于整个 MySQL 实例。加上全局锁后,整个数据库实例会被锁定,其他线程无法对数据库中的任何表或数据进行读写操作。
使用方式
通过命令 FLUSH TABLES WITH READ LOCK (FTWRL)
来加全局锁。
特点
- 影响范围:整个数据库实例。
- 常见应用场景:
- 一致性备份:为了确保备份数据的一致性,使用全局锁防止在备份期间有写入操作。
- 维护任务:如全量迁移或升级。
- 注意事项:
- 全局锁会导致数据库处于只读状态,所有写入操作会被阻塞,可能对线上服务造成较大影响。
- 不适用于高并发生产环境。
应用实例
一致性备份
FLUSH TABLES WITH READ LOCK;
-- 备份数据库
UNLOCK TABLES;
注意事项:
- 备份期间阻止写操作,会影响系统性能,不适合高并发场景。
- 建议优先使用逻辑备份工具(如
mysqldump
)或 InnoDB 的快照备份代替。
表锁 (Table Lock)
定义
表锁是作用于单个表的锁,限制其他线程对该表的读写操作。
使用方式
通过 LOCK TABLES
和 UNLOCK TABLES
命令手动加锁和解锁。
分类
- 读锁 (READ LOCK):
- 允许多个线程同时读取表数据。
- 禁止任何线程写入。
- 写锁 (WRITE LOCK):
- 独占锁,只有获取写锁的线程可以读写表数据。
- 其他线程的读写操作都会被阻塞。
特点
- 影响范围:单个表。
- 常见应用场景:
- 批量导入数据:避免并发写操作干扰。
- 精确控制并发行为:需要对表加锁进行复杂逻辑处理。
- 注意事项:
- 表锁的粒度较粗,会导致较高的锁冲突,影响并发性能。
应用实例
批量数据导入
LOCK TABLES my_table WRITE;
-- 批量插入数据
INSERT INTO my_table VALUES (1, 'A'), (2, 'B');
UNLOCK TABLES;
注意事项:
- 写锁期间,其他线程的读写请求会被阻塞。
- 对并发性能影响较大,适合低并发的管理任务。
行锁 (Row Lock)
定义
行锁是作用于表中的特定行的锁,仅限制其他线程对特定行的操作。
使用方式
行锁主要由事务机制自动实现,并通过以下语句触发:
SELECT ... FOR UPDATE
:对查询结果加写锁。SELECT ... LOCK IN SHARE MODE
:对查询结果加读锁。
特点
- 影响范围:特定行。
- 常见应用场景:
- 在高并发环境中,精细控制对特定记录的访问。
- 确保事务的隔离性(主要在
InnoDB
存储引擎中实现)。
- 注意事项:
- 行锁依赖索引。如果未使用索引,会升级为表锁。
- 行锁的开销相对较高,但并发性能较好。
应用实例
场景 1:悲观锁确保更新操作的安全性
START TRANSACTION;
SELECT * FROM my_table WHERE id = 1 FOR UPDATE;
-- 执行更新操作
UPDATE my_table SET value = 'Updated' WHERE id = 1;
COMMIT;
场景 2:乐观锁防止更新冲突
在数据表中添加版本号字段,通过比较版本号实现更新。
-- 查询时获取当前版本号
SELECT version FROM my_table WHERE id = 1;
-- 更新时检查版本号是否匹配
UPDATE my_table
SET value = 'Updated', version = version + 1
WHERE id = 1 AND version = CURRENT_VERSION;
注意事项:
- 行锁需要依赖索引。如果未命中索引,MySQL 会将行锁退化为表锁。
- 使用
SELECT ... FOR UPDATE
时,要确保事务及时提交以避免死锁。
总结对比
锁类型 | 作用范围 | 加锁方式 | 优缺点 | 常用场景 |
---|---|---|---|---|
全局锁 | 整个数据库实例 | FLUSH TABLES WITH READ LOCK | 粒度最大,影响整个实例,不适合高并发环境。 | 一致性备份、全库维护 |
表锁 | 单个表 | LOCK TABLES | 粒度较粗,影响整个表的操作,简单易用,但会降低并发性能。 | 批量操作、逻辑控制 |
行锁 | 表中的特定行 | 自动加锁或显式事务控制 | 粒度最细,并发性能高,但加锁开销大,需依赖索引实现。 | 高并发场景、事务操作 |