1. 全局锁(Global Lock)
全局锁的概念与使用:
全局锁是 MySQL 在进行某些操作时,会对整个数据库加锁的机制,通常会影响到整个数据库的所有操作。常见的全局锁操作包括 FLUSH TABLES WITH READ LOCK,这种锁会使得所有的表都被锁定,直到锁被释放。全局锁常用于 备份数据库时,确保备份期间数据一致性。应用场景:
- 数据库备份: 全局锁最常见的应用场景就是数据库备份。通过
FLUSH TABLES WITH READ LOCK
,可以保证在备份过程中,数据库不会发生写操作,从而避免数据的不一致性。 - 数据一致性: 例如,在主从复制的环境中,需要通过全局锁来保证主库和从库的数据一致性。
- 数据库备份: 全局锁最常见的应用场景就是数据库备份。通过
全局锁的缺点:
- 阻塞所有写操作: 全局锁会将整个数据库的写操作阻塞,直到锁被释放。这意味着数据库中的所有应用都会被暂停写操作,这对性能和可用性有极大的影响。
- 影响系统性能: 长时间持有全局锁会导致业务不可用,因此必须尽量减少锁的持有时间。
避免全局锁影响的方法:
- 使用 MySQL 的
mysqldump
工具:mysqldump
提供了--single-transaction
选项,这样可以在不使用全局锁的情况下进行备份(适用于事务型存储引擎,如 InnoDB)。 - 使用增量备份: 通过定期备份数据,并在备份时使用
--flush-logs
,可以避免每次备份都全盘扫描和锁定数据库。
- 使用 MySQL 的
2. 表级锁(Table-level Lock)
表级锁是指锁住整个表,使得表中的数据无法被修改,直到锁释放。表级锁相较于行级锁,锁的粒度较大,性能上会受到影响。
- 常见的表级锁类型:
表锁(Table Lock):
- 锁定表时会使得其他线程不能对表进行操作,直到当前操作完成。
- 应用场景: 比如在某些业务场景下,需要对某个表进行大批量的修改,而不希望其他线程同时访问表。
实例:
LOCK TABLE users WRITE; -- 锁定 users 表,其他线程不能对该表进行任何操作 UPDATE users SET status = 'inactive' WHERE last_login < '2020-01-01'; UNLOCK TABLES; -- 解锁
元数据锁(MDL,Metadata Lock):
元数据锁是 MySQL 在操作表结构时会自动加上的锁,主要用于 保证在查询或修改表结构时,不会有其他操作修改表的元数据。实例:
ALTER TABLE employees ADD COLUMN age INT; -- 这种操作会加上 MDL 锁,其他线程不能修改表结构
意向锁(Intention Lock): 意向锁是一种 对某个表的意图进行加锁的机制,分为意向共享锁(IS)和意向排他锁(IX)。意向锁的作用是为了在表级锁下进行协调,避免锁冲突。
应用场景: 用于优化表级锁与行级锁的并发性能。它允许在行级锁定时,表级锁可以不被阻塞。
AUTO-INC 锁: AUTO-INC 锁是与自动递增列相关的锁。当插入数据并使用自增字段时,MySQL 会为自增列加锁,以确保自增值的唯一性。
实例:
CREATE TABLE test (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100)); INSERT INTO test (name) VALUES ('Alice'); -- 在自增字段插入时,会使用 AUTO-INC 锁
3. 行级锁(Row-level Lock)
行级锁是最精细的锁类型,锁的粒度最小,只影响具体的一行数据,其他线程可以继续操作其他行。行级锁的并发性非常高,但实现的复杂性也较高,容易导致死锁问题。
- 常见的行级锁类型:
Record Lock(记录锁): 记录锁是锁住某一行数据,确保其他事务无法修改这行数据。在 InnoDB 中,通常通过 WHERE 条件 来确定锁定的行。
实例:
SELECT * FROM users WHERE id = 1 FOR UPDATE; -- 锁住 id 为 1 的记录
Gap Lock(间隙锁): 间隙锁是锁住某个范围内的空隙,不允许其他事务插入新记录到这个范围。它避免了幻读的问题,但会影响插入操作。
实例:
SELECT * FROM users WHERE id > 10 AND id < 20 FOR UPDATE; -- 锁住 id 10 和 20 之间的空隙,避免插入新数据
Next-Key Lock(下一个键锁): Next-Key 锁是 Record Lock 和 Gap Lock 的组合。它不仅锁住当前记录,还锁住记录间的空隙,确保其他事务无法插入或者修改被锁定范围内的数据。
实例:
SELECT * FROM users WHERE id BETWEEN 10 AND 20 FOR UPDATE; -- 锁住 id 10 到 20 范围内的记录及空隙
插入意向锁(Insert Intent Lock): 插入意向锁是用于记录即将插入的行,防止其他事务在插入操作的间隙范围内插入数据。它和 Gap Lock 配合使用,通常会在对一个范围进行加锁时自动加上。
实例:
INSERT INTO users (id, name) VALUES (100, 'Tom'); -- 插入数据时可能涉及插入意向锁
4. 总结
- 全局锁:主要用于保证数据库的全局一致性,常用于备份操作,但会导致所有其他操作的阻塞,影响系统的可用性和性能。
- 表级锁:适用于需要对整个表加锁的场景,常见锁类型包括表锁、MDL 锁、意向锁和 AUTO-INC 锁。这些锁的粒度较大,影响系统的并发性能,但实现较为简单。
- 行级锁:粒度最细,适合高并发的场景。常见的行级锁包括记录锁、间隙锁、下一个键锁和插入意向锁。虽然行级锁能够提供更高的并发性,但容易出现死锁问题,且实现更复杂。