mysql-【锁】总结

读锁与写锁

X锁 S锁
X锁 冲突 冲突
S锁 冲突 不冲突

读锁:当前事务给某些数据加了读锁,容许其余事务加读锁但不容许加写锁。也能够称之为共享锁、Shared Locks、S锁

示例

select * from table_a lock in share modemysql

使用场景:读出数据后其余事务不能修改,但本身也不必定能修改,由于其余事务也能够加读锁。主要用来保证数据在本事务内值不会变。但实际开发中用得比较少。sql

写锁:当前事务若是加了写锁,其余事务若加锁会阻塞。也能够称之为排他锁、Exclusice Locks、X锁

示例

select * from table_a for update 以及 DELETE/UPDATE/INSERT(插入后未提交的数据也会加写锁)性能

使用场景:只有本事务才能够修改这些数据,其余事务加锁会阻塞。通常开发过程当中大部分接触到的锁都是写锁。索引

行锁与表锁

行锁:只有InnoDB里才会有。

行锁又分为:事务

  • LOCK_REC_NOT_GAP:单个行记录上的锁。
  • LOCK_GAP:间隙锁,锁定一个范围,但不包括记录自己。什么意思呢?好比查询一条ID为7的数据,间隙锁是给ID=7这条数据上下记录间的间隙给锁定,但记录自己不上锁。就如MVCC是解决可重复读的问题同样,间隙锁是解决幻读的问题,即同一事务内,数据总数不变。
  • LOCK_ORDINARY:同上,也是间隙锁,只是锁定范围包括记录自己。咱们通常所说的间隙锁就是这个。

示例:

select * from table_a where a = 1 for update开发

  • 事务隔离级别为读提交时 会对查询出的全部每条数据加行锁(单个行记录上锁),但此时其余事务能够针对这个数据范围insert形成幻读。table

  • 当事务隔离级别为可重复读时(mysql默认的事务隔离级别) 若是走索引,mysql经过索引知道数据的范围,会对查询出的数据范围间隙及数据自己加锁,其余事务针对这个数据范围写操做都会阻塞,包括insert在这个间隙范围内的操做,以免幻读。class

但若是sql语句不走索引全表扫描,此时mysql并不知道数据范围,mysql只能对全部的数据和间隙上锁以免幻读。date

表锁

表锁在InnoDB中应用不多,写操做是不会加表级别的锁。select

而DDL语句也会发生阻塞,这个过程是经过使用元数据锁(Metadata Locks,MDL)来实现的,并非表级别的锁。 可是能够用过如下方式加表锁

  • LOCK TABLES t1 READ
  • LOCK TABLES t1 WRITE

可是不建议使用,由于InnoDB的优势就是行锁,表锁性能差。

总结

  • mysql默认事务隔离级别是可重复读,因此须要重点关注的概念:写锁、行锁、间隙锁。
  • 读锁与写锁是对锁功能的分类,而行锁与表锁是对锁范围的一个分类。
相关文章
相关标签/搜索