前言
之前讲解过MySQL四种隔离级别的相关内容,但实际上事务的隔离级别通常伴随着锁机制一起出现,两者息息相关。本篇文章主要介绍了MySQL的锁机制以及MySQL常见的几种锁以供参考学习。
一、锁机制
事务的隔离性要求同一时刻只能有 一个事务对数据进行写操作,InnoDB 通过锁机制来保证这一点。
在InnoDB引擎下,按锁的粒度分类,可以简单分为行锁和表锁。
行锁实际上是作用在索引之上的,当我们的SQL命中了索引,那锁住的就是命中条件内的索引节点(这种就是行锁),如果没有命中索引,那我们锁的就是整个索引树(表锁)。
简单总结:锁住的是整棵树还是某几个节点,完全取决于SQL条件是否有命中到对应的索引节点。
二、行锁
行锁又可以简单分为读锁(共享锁、S锁)和写锁(排它锁、X锁)。
1.读锁是共享的,多个事务可以同时读取同一个资源,但不允许其他事务修改。
2.写锁是排他的,写锁会阻塞其他的写锁和读锁。
联系事务隔离级别:在读未提交隔离级别下,读不会加任何锁,而写会加排他锁。读什么锁都不加,这就让排他锁无法排它。对于更新操作,InnoDB是肯定会加锁的(数据库是不可能允许在同一时间,更新同一条记录),而读操作,如果不加任何锁,那就会造成上面的脏读。
脏读在生产环境下肯定是无法接受的,那如果读加锁的话,那意味着:当更新数据的时,就没办法读取了,这会极大地降低数据库性能。
解决办法:在MySQL InnoDB引擎层面,又有新的解决方案(解决加锁后读写性能问题),叫做MVCC(Multi-Version Concurrency Control)多版本并发控制(之前的文章已经讲解到)。
总结:使用MVCC替代给读加锁,让不同事务的 读-写、写-读操作可以并发执行,从而提升系统性能。
三、表锁
如果没有命中索引,那我们锁的就是整个索引树(表锁)。
MySQL 中锁定粒度最大的一种锁,表示对当前操作的整张表加锁。 MYISAM 与 INNODB 都支持表级锁定。表级锁定分为表共享锁与表排他锁。
行锁特点:开销大,会出现死锁,并发度最高。
表锁特点:开销小,不会出现死锁,并发度最低。
四、间隙锁
间隙锁:当我们用范围条件而不是相等条件检索数据,InnoDB 会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但并不存在的记 录,叫做“间隙",InnoDB 也会对这个“间隙”加锁。
使用间隙锁的目的?解决幻读问题。
幻读:事务A按照一定条件读取某些数据记录之后,事务B插入或者删除了一些记录,事务A再次按照相同的条件读取数据时,发现多了或者少了一些记录。
例如:事务A执行update user set name=‘张三’ where id >1 and id<4; 假如表中只有id=1、2 两条数据,A事务还没提交,那么此时事务B再次插入一条id=3的数据,理论上是允许的,但是实际上是B只能等A提交,因为事务A执行的是id>1and id<4,范围涵盖了id=3的,也即是把id=3的这个间隙也给锁了,叫做间隙锁,这样就能解决幻读的问题。
总结
通过学习锁机制,我们能够对事务的隔离级别有更深刻的认识,每个知识点都不是单独存在的,将所有的知识点联系在一起讲解出来,将会给人留下更深刻的印象。