行锁&表锁
只有明确指定主键,才会执行行锁,否则执行表锁
无锁
select * from user where id = -1 for update;
#主键不存在
行锁
select * from user where id = 1 for update;
select * from user where id = 1 and name = ‘kk‘ for update;
#只要where后的字段建了索引,就会用行锁
表锁
#主键不明确
select * from user where name = ‘kk‘ for update;
select * from use where id <>3 for update;
Record Lock(普通行锁)
#主键值在条件范围内,单个行记录上的锁
#记录存在
Gap Lock(间隙锁)
#主键值不存在条件范围内,叫做间隙GAP,引擎就会对这个间隙加锁。
#间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况
Next-key Lock(行& 间隙锁)
#主键值一部分在条件范围内。
#比如user表id字段自增共50条数据。
select * from user where id >49;
1+2,锁定一个范围,并且锁定记录本身。对于行的查询,都是采用该方法,主要目的是解决幻读的问题。
意向锁(升级机制)
#当一个事务,带着表锁去访问被加了行锁的资源,此时,这个行锁就会升级为意向锁,将表锁住。
#Session A
select * from user where id = 1 for update ;
#Session B
select * from user where name like ‘kkk%‘ for update;
那么Session A 就会升级成意向锁
自增锁
#事务插入自增类型的列时,获取自增锁。
#如果一个事务正在往表中插入自增记录,其他事务都必须等待。
行锁和表锁是粒度的概念,共享锁和排他锁是他们的具体实现。
共享锁(S)
允许一个事务去读一行,阻止其他事务去获取该行的排他锁。
select lock in share mode #MySQL 8以下版本
select for share #MySQL 8以上版本,支持nowait、skip locked,配合自旋锁可以实现等待队列。
排他锁(X):写锁
允许持有排它锁事务读写数据,阻止其他事务获取该资源的共享锁和排它锁。
select for update\insert\delete\update
加锁是当前读,保证读取的是最新的数据;在隔离级别为REPEATABLE时,不加锁的select操作是快照读,有可能读到的不是最新的版本。ps:在串行级别下,快照读会退化成当前读。
乐观锁
一般通过版本号进行更新检查
悲观锁
利用数据库本身提供的锁去实现
原文:https://www.cnblogs.com/danaohu/p/14835497.html