锁机制是 MySQL 用于控制并发访问的重要手段,通过锁定资源避免数据冲突。理解 MySQL 的锁机制,有助于开发者优化数据库性能并处理高并发场景。
1. 锁的概念
锁(Lock)是数据库系统为保证数据一致性和完整性,对特定资源(如表、行)设置的访问限制。通过锁机制,可以实现以下目标:
- 保证事务的隔离性。
- 防止数据读写冲突。
- 提升并发性能。
2. 全局锁
2.1 概念
全局锁是针对整个数据库实例的一种锁机制。一旦加锁,所有对数据库的读写操作都会被阻塞。
2.2 作用和原理
全局锁的常见使用场景是数据备份,利用全局锁可以保证备份期间数据的一致性。
2.3 缺点和优点
优点 | 缺点 |
---|---|
能保证数据库的全局一致性 | 会阻塞所有读写操作,影响性能 |
适用于小型业务场景 | 不适合高并发、大规模业务场景 |
2.4 对应的业务场景
- 数据库全量备份。
- 需要短时间冻结业务的场景。
2.5 操作指令
-
加锁:
sqlFLUSH TABLES WITH READ LOCK;
-
数据备份: 使用 mysqldump 工具时,搭配
sql--lock-all-tables
参数。
sqlmysqldump --lock-all-tables -u root -p dbname > backup.sql
-
解锁:
sqlUNLOCK TABLES;
2.6 案例
sql
-- 加锁
FLUSH TABLES WITH READ LOCK;
-- 数据备份
mysqldump --lock-all-tables -u root -p test_db > backup.sql
-- 解锁
UNLOCK TABLES;
3. 表锁
3.1 简介
表锁是对整个表加锁,控制表的读写权限。表锁的范围比行锁更大,但实现简单。
3.2 分类
- 表锁:直接对表进行锁定。
- 元数据锁:用于保护表的元数据结构。
- 意向锁:用来协调表锁和行锁。
3.3 表锁
分类及特点
类型 | 特点 |
---|---|
表共享读锁(S锁) | 允许多个事务同时读取表,但不允许写入 |
表独占写锁(X锁) | 阻塞所有读写操作,仅允许持有锁的事务操作表 |
加锁和查看锁
-
加锁:
sqlLOCK TABLES table_name READ; -- 表共享读锁 LOCK TABLES table_name WRITE; -- 表独占写锁
-
解锁:
sqlUNLOCK TABLES;
-
查看锁状态:
sqlSHOW OPEN TABLES WHERE In_use > 0;
案例
sql
-- 给表加共享读锁
LOCK TABLES employees READ;
-- 查询数据
SELECT * FROM employees;
-- 解锁
UNLOCK TABLES;
3.4 元数据锁(MDL)
概念和作用
元数据锁是 MySQL 用于保护表结构的锁,当执行 ALTER TABLE
或 DROP TABLE
时,会自动加上 MDL 锁。
查看锁状态
sql
SHOW PROCESSLIST;
案例
sql
-- 开启事务
START TRANSACTION;
-- 查询表数据(持有 MDL 锁)
SELECT * FROM employees;
-- 在另一个会话尝试修改表结构
ALTER TABLE employees ADD COLUMN age INT;
-- 此时会发现 ALTER 操作被阻塞。
3.5 意向锁
简介和作用
意向锁是表锁和行锁之间的一种协作机制,用于标记事务对表中某些行的意图。
分类
锁类型 | 含义 |
---|---|
意向共享锁(IS) | 标识事务想获取行级共享锁 |
意向排它锁(IX) | 标识事务想获取行级排它锁 |
兼容关系
表锁类型 | IS | IX | S | X |
---|---|---|---|---|
IS | √ | √ | √ | ✗ |
IX | √ | √ | ✗ | ✗ |
S | √ | ✗ | √ | ✗ |
X | ✗ | ✗ | ✗ | ✗ |
案例
sql
-- 开启事务
START TRANSACTION;
-- 更新某行数据(自动加 IX 锁和行级锁)
UPDATE employees SET name = 'John' WHERE id = 1;
-- 查看锁信息
SHOW ENGINE INNODB STATUS;
4. 行级锁
4.1 简介
行级锁是最细粒度的锁,用于锁定表中的特定行,减少并发冲突。
4.2 分类
行锁
-
共享锁(S 锁):允许其他事务读取,但不允许写入。
sqlSELECT * FROM employees WHERE id = 1 LOCK IN SHARE MODE;
-
排它锁(X 锁):禁止其他事务的读写。
sqlSELECT * FROM employees WHERE id = 1 FOR UPDATE;
间隙锁
- 锁定索引之间的范围,防止插入操作。
- 适用于
范围查询
(如BETWEEN
)。
临建锁
- 间隙锁和行锁的组合,用于防止幻读。
4.3 案例
sql
-- 开启事务
START TRANSACTION;
-- 加行级共享锁
SELECT * FROM employees WHERE id = 1 LOCK IN SHARE MODE;
-- 加行级排它锁
SELECT * FROM employees WHERE id = 1 FOR UPDATE;
-- 提交事务
COMMIT;
通过以上内容,可以掌握 MySQL 锁的分类、使用场景及实际操作方法。这些知识对于优化并发性能和解决锁冲突问题至关重要。