锁机制
概述
首先来看两个事务的写操作之间的相互影响。隔离性要求同一时刻只能有一个事务对数据进行写操作,InnoDB通过锁机制来保证这一点。
基本原理:事务在修改数据之前,需要先获得相应的锁;获得锁之后,事务便可以修改数据;该事务操作期间,这部分数据是锁定的,其他事务如果需要修改数据,需等待当前事务提交或回滚后释放锁。
行锁和表锁
按照粒度,锁可以分为表锁、行锁以及其他位于二者之间的锁。表锁在操作数据时会锁定整张表,并发性能较差;行锁只锁定要操作的数据,并发性能好。
但是由于加锁本身需要消耗资源(获得锁、检查锁、释放锁等都需要消耗资源),因此在锁定数据较多情况下使用表锁可以节省大量资源。
Mysql中不同的存储引擎支持的锁是不一样的,例如MyIsam只支持表锁,而InnoDB同时支持表锁和行锁,且出于性能考虑,绝大多数情况使用的都是行锁。
行锁
行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为 共享锁 和 排他锁。
特点:
- 开销大,加锁慢
- 会出现死锁
- 锁定粒度最小,发生锁冲突的概率最低,并发度也最高
共享锁(S):
又称读锁。允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁。若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,知道T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
排他锁(X):
又称写锁。允许获取排他锁的事务更新数据,阻止其他事务取得相同的数据集共享读锁和写锁。若事务T对数据对象A加上X锁,事务T可以读取也可以修改A,其他事务不能再对A加任和锁,直到T释放A上的锁。update,delete,insert 都会自动给涉及到的数据加上排他锁,select 语句默认不会加任何锁类型,如果加排他锁可以使用 select …for update 语句,加共享锁可以使用 select … lock in share mode 语句。
表锁
表锁是Mysql中粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分Mysql引擎支持。最长使用的MyIsam与InnoDB都支持表锁。表锁分为表共享锁和表排它锁。
特点:
- 开销小,加锁快
- 不会出现死锁
- 锁定粒度大,发出锁冲突的概率最高,并发度最低