行级锁row-level loking
行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁,每次操作锁住一行数据。
特点:
- 开销大,加锁慢。
- 会出现死锁。
- 锁粒度最小,发生锁冲突概率最低,并发效率最高。
- 适合并发写,事务控制。
注:并不是直接丢记录行加锁,而是对行对应的索引加锁:
1、如果sql 语句操作了主键索引,Mysql 就会锁定这条主键索引。
2、如果sql语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。
3、在InnoDB中,如果SQL语句不涉及索引,则会通过隐藏的聚簇索引来对记录加锁。
4、对聚簇索引加锁,实际效果跟表锁一样,因为找到某一条记录就得扫描全表,要扫描全表,就得锁定表。
表级锁table-level locking
表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,锁住整个表,实现简单,资源消耗较少。
特点
- 开销小,加锁快。
- 不会死锁(一次性加载所需的所有表)。
- 锁粒度大,发生锁冲突概率最高,并发效率最低。
- 适合查询。
乐观锁Optimistic Lock
假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。
实现方式:
对表的数据进行操作时,同时将数据表的版本字段取出,等到操作完毕进行提交时,将数据版本号与表内的数据版本号进行比较,如果相等,说明这段时间内没有别的事务对数据表进行操作,则将版本号加一,并予以更新。否则认为是过期数据,进行回滚。
特点:
乐观锁的特点先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。
使用场景:
比较适合读取操作比较频繁的场景,如果出现大量的写入操作,数据发生冲突的可能性就会增大,为了保证数据的一致性,应用层需要不断的重新获取数据,这样会增加大量的查询操作,降低了系统的吞吐量。
乐观锁不是数据库本身自带的锁,需要程序员自己实现。
悲观锁Pessimistic Lock
假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。
实现方式:
是由数据库自己实现了的,要用的时候,我们直接调用数据库的相关语句就可以了
特点:
先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。通常所说的“一锁二查三更新”即指的是使用悲观锁。
使用场景:
比较适合写入操作比较频繁的场景,如果出现大量的读取操作,每次读取的时候都会进行加锁,这样会增加大量的锁的开销,降低了系统的吞吐量。