mysql锁
当多线程并发操作数据库时,锁用来让数据库的数据保持一致性和完整性,mysql提供了不同的锁来应对不同的情况。
mysql里面有多种存储引擎(engine),比较常见的是MYISAM,INNODB,BDB三种引擎,其中有不同的锁来进行对数据的加锁。
表级锁
MYISAM里默认的就是表级锁,锁定粒度最大,但是由于是将整张表都进行加锁,所以逻辑非常简单,以至于加锁要快于其他锁,对系统的操作影响最小,并
且死锁的发生率非常小,其他锁的冲突发生就很大。
使用表级锁的引擎MyISAM、MEMORY、CSV 等一些非事务性存储引擎。
使用方式是
1 | Lock tables 表名 read local; |
页级锁
页级锁是锁定一段范围的数据,粒度在表锁和行锁之间,所以性能是一般的,介于两者之间,使用的引擎是BDB
行级锁
行级锁是对一行或者是多行进行上锁,粒度最小,但是消耗性能非常大,并且锁的冲突最大,发生死锁的概率最大,使用的引擎是INNODB,但是并发度很高
InnoDB锁的操作
共享锁和排他锁
共享锁: 是能多线程读取数据,但是不能修改数据
排它锁:是能修改数据,但是也能读取数据
InnoDB支持多种锁粒度,允许使用行锁和表锁同时存在,为了支持这种操作,引入了另一种锁,叫意向锁(intention lock)。
意向锁是将对象分为多个层次,希望可在不同粒度上加锁。
InnoDB意向锁为表级别的锁,设计目的主要是为了在一个事务中揭示下一行将被请求的锁类型。
意向共享锁( intention shared lock, Is),事务有意向对表中的某些行加共享锁
意向排它锁(intention exclusive lock,IX),事务有意向对表中的某些行加排他锁
在InnoDB里,默认是行级锁,如果是索引普通列或者是没有索引列,那么就会使用表级锁,如果是索引索引列或者是主键,那么就上行级锁。
上锁的方式,一般mysql是自动上锁的,如果是有特殊的要求,可以手动上锁
1 | select * from table where ... lock in share mode; |
上面一句是上共享锁,下面一句是上排他锁
间隙锁(next-key lock)或者叫gap锁,就是当使用范围检索条件时并上锁时,InnoDB会给符合条件的已有数据记录的 索引项加锁;对于键值在条件范围内但并不存在的记录,叫
做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁 (Next-Key锁)。
例如:select * from table where id>100 for update; 这个语句不仅会100以内已有的数据,那些没有的数据也会上锁,也就是如果有id(101,102,103),那么会上锁101,102,
103,那些104,105,106…尽管不存在,也依然上锁