1.间隙锁(Gap锁)
间隙锁是一个在索引记录之间的间隙上的锁。
例:
间隙锁的作用:
保证某个间隙内的数据在锁定情况下不会发生任何变化。比如mysql默认隔离级别下的可重复读(RR)
当使用唯一索引来搜索唯一行的语句时,不需要间隙锁定。如下面语句的id列有唯一索引,此时只会对id值为10 的行使用记录锁
select * from t where id = 10 for update;注意:普通查询是快照读,不需要加锁。
如果上面语句中id列没有建立索引或者是非唯一索引时,则语句会产生产生间隙锁。
gap锁如何锁区间?
通过InnoDB中索引树的结构可以了解到:gap锁的关键就是锁住索引树的叶子结点之间的间隙,不让新的记录插入到间隙之中。
2.表锁 :
表锁就是锁住整张表,其他用户对该表的任何操作都受影响,具体影响取决于锁的形式。
MySQL的表锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock):
表共享读锁(Table Read Lock):不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;
表独占写锁:会阻塞其他用户对同一表的读和写操作;
2.1表锁细节需要区分是MyISAM还是InnoDB
MyISAM:
MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等),会自动给涉及的表加写锁,这个过程并不需要用用户干预。
InnoDB:
必须显示加表锁语句
注意:如果没有索引,InnoDB的行锁会升级为表锁,效果和表锁一样,锁住全部索引。
3.行锁(record lock)
行锁就是对具体的索引数据进行加锁,与表锁相比,粒度更小,减少竞争
行锁不是只能在一行上加锁,可以是若干行,可以是连续的,也可以是跳跃的
对于UPDATE、DELETE、INSERT语句,InnoDB会自动给涉及的数据集加排他锁(X);对于普通SELECT语句,InnoDB不会加任何锁。
4.共享锁(读锁)和排他锁(写锁)
InnoDB实现了以下两种类型的行锁:
共享锁(s):共享锁又称为读锁,简称S锁,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改。
排他锁(X):排他锁又称为写锁,简称X锁,排他锁就是不能与其他锁并存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁和排他锁,但是获取排他锁的事务是可以对数据进行读取和修改。
共享锁=读锁、排他锁=写锁,确切来说mysql没有读锁和写锁概念的,但是在实际应用中,读锁表示并发操作,写锁不支持并发,必须阻塞,因此可以这样划等号。但严格来说,在计算机概念中,不是所有的读锁都是支持并发的。
事务可以通过以下语句显示给记录集加共享锁或排他锁:
共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE
排他锁(X):SELECT * FROM table_name WHERE ...FOR UPDATE
InnoDB引擎默认的修改数据语句,update,delete,insert都会自动给设计到的数据加上排他锁,select语句默认不会加任何锁类型。
5.意向锁
意向锁是InnoDB自动加的,不需用户干预。
为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁:
意向共享锁(IS):事务打算给数据行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务大Susan给数据行加排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
事务在请求行锁中的共享锁和排他锁前,会先自动获得意向锁。