锁机制详解
锁是计算机协调多个进程或线程并发访问某一资源的机制。 在数据库种,除了传统的计算机资源(如CPU RAM I/O)的争用以外,数据也是一种供需要用户共享的资源。如何保证数据并发访问的一致性,有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。
锁分类
从性能上分为乐观锁(用版本对比或CAS机制)和悲观锁,乐观锁适合读操作较多的场景,悲观锁适合写操作较多的场景,如果在写操作较多的场景使用乐观锁会导致比对次数过多,影响性能
从数据对比操作的粒度分,分为表锁 页锁 行锁。
从对数据库操作的类型分,分为读锁和写锁(都属于悲观锁),还有意向锁。
读锁(共享锁 S锁shared)针对同一份数据 多个读操作可以同时进行而不会相互影响
如 select *from T where id=1 lock in share mode
写锁(排它锁 X锁 eXclusive)当前写操作没有完成前,它会阻断其他写锁和读锁,数据修改操作都会加写锁,查询页可以通过for update加写锁
如 select * from T where id=1 for update
表锁 每次操作锁住整张表。开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低,一般用在整表数据迁移的场景。
手动增加表锁lock table 表名 read(write), 表名2 read(write);
查看表上加过的锁show open tables;
删除表锁 unlock tables;
页锁 只有BDB存储引擎支持页锁,页锁就是在页的粒度上进行锁定,锁定的数据资源比行锁要多,因为一个页种可以有多个行记录。当我们使用页锁的时候,会出现数据浪费的现象,但这样的浪费最多也就是一个页上的数据行。页锁的开销介于表锁和行锁之间,会出现死锁。锁定粒度介于表锁和行锁之间,并发度一般。
行锁 每次操作锁住一行数据。开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度最高。 InnoDB相对于MYISAM的最大不同有两点。
innodb支持事务
innodb支持行级锁
innoDB的行锁实际上是针对索引加的锁(在索引对应的索引项上做标记),不是针对整个行记录加的锁,并目该索引不能失效,否则会从行锁升级为表 锁。(RR级别会升级为表锁,RC级别不会升级为表锁)
MYISAM在执行查询语句select之前,会自动给射妓的所有表加读锁,在执行update insert delete操作会自动给涉及的表加锁。 innoDB在执行查询语句select时(非串行隔离级别),不会加锁,但是update insert delect操作会加锁。 另外,读锁会阻塞写,但是不会阻塞读。而写锁会把读和写都阻塞。
间隙锁
MySQL5.7 版本中,binlog默认是关闭的,8.0版本默认是打开的。