目录
1、MySql中的锁分类
按照锁粒度分类:表锁和行锁,即这这个锁是锁住整张表还是表中的某几行
按照读写分类:表级锁和行级锁可以进一步划分为共享锁和排它锁,即有表级共享锁、表级排他锁、行级共享锁、行级排他锁
还有两种表级锁:意向共享锁和意向排他锁
2、读写锁和意向锁
-
共享锁(s)
共享锁(S锁)又称为读锁,若事务T对数据对象A加上S锁,则事务T只能读A;其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这就保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
-
排他锁(X):
排它锁((Exclusive lock,简记为X锁))又称为写锁,若事务T对数据对象A加上X锁,则只允许T读取和修改A,其它任何事务都不能再对A加任何类型的锁,直到T释放A上的锁。它防止任何其它事务获取资源上的锁,直到在事务 的末尾将资源上的原始锁释放为止。在更新操作(INSERT、UPDATE 或 DELETE)过程中始终应用排它锁。
两者之间的区别:
- 共享锁(S锁):如果事务T对数据A加上共享锁后,则其他事务只能对A再加共享锁,不 能加排他锁。获取共享锁的事务只能读数据,不能修改数据。
- 排他锁(X锁):如果事务T对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获取排他锁的事务既能读数据,又能修改数据。
-
意向共享锁(IS)和意向排他锁(IX)
如果事务想要给表中几行数据加上行级共享锁,那么需要先在表级别加上意向共享锁(IS);如果事务想要给表中几行数据加上行级排他锁,那么需要先在表级别加上意向排他锁(IX)(注意:如果是想要加表级S锁或X锁,不需要先加意向锁。)
-
意向锁的作用
当向一个表添加表级X锁或者S锁时,如果没有意向锁的话,则需要遍历所有整个表判断是否有不兼容的行锁的存在,以免发生冲突。如果有了意向锁,只需要判断该意向锁与即将添加的表级锁是否兼容即可,因为意向锁的存在代表了有行级锁的存在或者即将有行级锁的存在,因而无需遍历整个表,即可获取结果。
以下是表级X和S锁和意向锁的兼容性
个人理解:意向锁和意向锁之间总是兼容,因为都是表示自己要对某几行加锁,行锁之间不一定冲突,意向共享锁也和表级共享锁兼容,因为共享锁可以同同时加。
3. 数据库行锁、表锁(封锁粒度)
MySQL 中提供了两种封锁粒度:行级锁以及表级锁。
- 表锁是mysql中开销最小的策略,它会锁定整张表,用户在对表进行写操作前,需要先获得写锁,这会阻塞其他用户对该表的所有读写操作。MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。
- 特点:锁粒度大,系统开销小,发生锁冲突的概率最高,并发度最低。加锁快,不会出现死锁。表锁是由MySQL Server负责的。
- 行锁可以最大程度的支持并发处理,同时也带来了最大的锁开销,InnoDB存储引擎实现了两种行锁:共享锁和排他锁。行锁在存储引擎层实现。
- 特点: 锁粒度小,系统开销大,发生锁冲突的概率小,并发度最高。加锁慢,会出现死锁。行锁是由InnoDB存储引擎管理的。
4. 什么时候使用表锁?
- 事务更新大表中的大部分数据直接使用表级锁效率更高。如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间锁等待和锁冲突,这种情况下可以考虑使用表锁来提高该事务的执行速度。
- 事务比较复杂,使用行级索很可能引起死锁导致回滚。这种情况也可以考虑一次性锁定事务涉及的表,从而避免死锁、减少数据库因事务回滚带来的开销。