MySQL-锁的基本概念
并发和锁
在学习事务隔离级别级别之前,我们首先需要知道为什么要有事务隔离级别,事务的隔离级别就是为了做好 「 并发的控制 」。
当多个查询出现的时候,就会产生 「 并发问题 」 ,对于大多数涉及到数据的应用程序来说,操作主要有两种,读取和写入。假如一个读取和一个写入同时进行操作的话,结果是有很多不确定性的,这种不确定将会导致不同的结果。
并发控制常用的方法就是建立锁。
在操作数据的时候,对线程进行加锁操作,操作完成后释放锁,持有锁期间,其它操作均无法占有锁,因此只能阻塞,无法执行成功。
读写锁
如果对任何的操作都将数据完全锁死,那么系统的并发处理能力就会十分低效,因此MySQL的锁系统中有两种锁: 读锁和写锁。
读锁 : 读锁是一种 共享锁 ,多个申请获取读锁的操作可以同时持有并同时进行。
写锁 : 写锁是一种 排他锁 ,占有时会排斥其它操作占有锁。
为什么要分 读写锁 ?
假如是 「 多读取 」 的场景,大量的读操作只是获取数据而不是去修改数据的值,不会造成数据的混乱,那么这时候用排他锁就显得十分没有必要,低效。
假如是 「 多写入 」 的场景,大量的写操作同时操作同一条数据,就会有不同的结果出现,无法控制,数据混乱,因此写入数据是需要排他锁来防止数据混乱的。
锁的粒度
锁的粒度其实就是我们经常说的 锁级别。
数据库引擎具有多粒度锁定,允许一个事务锁定不同类型的资源。为了尽量减少锁定的开销,数据库引擎会自动将资源锁定在适合的任务级别。
MySQL有三种锁的级别: 页、表、行。
表级锁 :开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁 :开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁 :开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
不同的数据库引擎都有不同的上锁策略,而所谓的 锁策略 ,就是在 锁的开销与数据的安全性 之间寻求平衡。
死锁
上锁就会存在 死锁 问题。
死锁就是当两个操作线程 各自占有自己的锁不释放,同时又在请求对方的锁资源 ,就会产生死锁,死锁一旦产生,没有外力的介入是无法打破的。
而死锁又是很难完全避免的,所以MySQL提供了比较充足的死锁检测策略,当检测到死锁后,Innodb会将持有 「 最少行级排他锁 」 的事务进行回滚,来打破死锁,这是一种简单的策略。还有其它的可以自行深入了解一下。
都结合网上资料加上自己的一些理解,如果有影响到他人的地方,可以联系我:[email protected]