目录
前言
MySQL中的锁机制是在多线程或并发场景下的一种资源调度策略,旨在维护数据的完整性和一致性。
一、锁的分类
-
按锁的粒度划分:
- 全局锁:影响整个数据库实例,非常少见,通常用于备份等场景。
- 表级锁:锁定整个表,开销较小,但并发性低,MyISAM和MEMORY存储引擎支持。
- 行级锁:粒度最细,只锁定需要的行,开销较大,但并发性能好,InnoDB存储引擎支持。
- 页级锁:介于表锁和行锁之间,锁定数据页,BDB存储引擎支持。
-
按锁的类型划分:
- 共享锁(S锁,Read Lock):允许事务读取一行数据,但不允许其他事务修改。
- 排他锁(X锁,Write Lock):允许事务修改一行数据,阻止其他事务读取或修改。
-
特殊类型的锁:
- 间隙锁(Gap Lock):仅在可重复读(Repeatable Read)隔离级别下,锁定两个记录之间的范围,防止插入新的记录到这个范围内,从而避免幻读。
- 临键锁(Next-Key Lock):是Gap Lock加上Record Lock的组合,锁定一个范围并包括记录本身,同样用于解决幻读问题。
- 意向锁(Intent Lock):表级别的锁,用来表示事务有意向在表中的某几行上加行级锁,分为意向共享锁(IS)和意向排他锁(IX)。
二、使用场景
全局锁
- 场景:主要用于数据库的备份操作,如使用
FLUSH TABLES WITH READ LOCK
命令全局锁定数据库,确保备份期间数据的一致性。 - 注意事项:使用全局锁会导致整个数据库无法进行写操作,应尽量减少其使用时间,或在低峰时段执行。
表级锁
- 场景:
- MyISAM引擎:常用于读多写少的场景,如统计分析、报表生成等。
- 备份操作:当备份工具不支持InnoDB在线热备份时,可锁定表进行备份。
- 注意事项:
- 写锁会阻塞所有其他读写操作,导致并发性能低下。
- 应谨慎使用,尤其是在高并发环境下,考虑使用行级锁的存储引擎。
行级锁
- 场景:
- InnoDB引擎:适用于高并发写操作的场景,如在线事务处理系统。
- 更新或查询单行或少量行数据时,以减少锁冲突,提高并发处理能力。
- 注意事项:
- 索引优化至关重要,InnoDB行锁基于索引来实现,无索引的查询会升级为表锁。
- 避免长事务,长时间持有行锁会影响其他事务的执行。
间隙锁与临键锁
- 场景:在可重复读(Repeatable Read)隔离级别下,用于防止幻读。
- 注意事项:
- 可能导致不必要的锁竞争,尤其是在大量范围查询或插入操作时。
- 了解并监控锁争用情况,必要时调整查询或事务逻辑。
三、锁与事物的隔离级别
在MySQL中,特别是针对InnoDB存储引擎,不同的事务隔离级别会采用不同的锁策略来保证事务的隔离性。
1. 读未提交(Read Uncommitted)
- 锁使用:在
Read Uncommitted
隔离级别下,事务在读取数据时通常不加锁或仅使用短暂的共享锁(S锁),这取决于存储引擎的具体实现。这意味着事务可以看到其他事务未提交的数据变更。 - PS:由于几乎不使用锁来保护读取操作,此隔离级别下容易发生“脏读”(Dirty Read),即事务可能读取到其他事务尚未提交的数据,如果这些数据随后被回滚,则读取到的信息就是无效的。
2. 读已提交(Read Committed)
- 锁使用:在读取数据时,事务会对读取的行加共享锁(S锁),但在读取完成后立即释放锁。在修改数据时,事务会获取排他锁(X锁),直到事务结束才释放。
- PS:这种模式下,事务读取的总是已经提交的数据,避免了脏读,但可能会出现“不可重复读”(Non-Repeatable Read)的问题,即在同一个事务内多次读取同一行数据,可能得到不同的结果,因为其他事务已经提交了对该行的修改。
3. 可重复读(Repeatable Read)
- 锁使用:InnoDB默认的隔离级别。在事务开始时,对于读取的每一行数据都会加共享锁,直到事务结束才释放。在修改数据时,同样使用排他锁。此外,InnoDB还使用了Next-Key Locks(包含行锁和间隙锁)来防止幻读。
- PS:通过在整个事务生命周期内保持读取锁,确保同一事务内多次读取同一数据的结果是一致的,即解决了不可重复读问题。间隙锁的引入是为了防止插入新的记录(幻读),但这在某些情况下仍可能无法完全避免幻读,除非配合MVCC(多版本并发控制)机制。
4. 串行化(Serializable)
- 锁使用:这是最严格的隔离级别。在事务开始时,对涉及的所有读取操作都加共享锁,并且对于写操作则加排他锁,相当于在整个事务处理过程中对涉及的表或行都加了锁。
- PS:通过在整个事务执行期间锁定相关资源,串行化可以彻底避免脏读、不可重复读和幻读问题,但代价是牺牲了并发性能,因为事务之间变得完全串行化,不能并发执行。
注意事项
- MVCC(多版本并发控制):在
Read Committed
和Repeatable Read
隔离级别下,InnoDB使用MVCC来提供一定程度的并发控制,减少锁的依赖,通过维护数据的多个版本来实现事务的隔离性,但具体实现细节和锁的结合在不同隔离级别有所不同。 - 锁的粒度:随着隔离级别的提高,锁的粒度一般会变得更细,从不加锁或表锁逐步过渡到行锁和间隙锁,以更精确地控制并发访问,但这也意味着更高的管理开销和潜在的锁竞争问题。
- 性能与并发:选择适当的隔离级别需要在数据一致性与系统并发性能之间做出权衡。较高的隔离级别虽然提供了更强的数据一致性保证,但可能会影响并发处理能力。