本篇内容介绍了“Lock锁的原理是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
公司主营业务:网站制作、成都做网站、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出北湖免费做网站回馈大家。
前提
MySQL中的行级锁,表级锁,页级锁中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大大减少数据库操作的冲突。行级锁分为共享锁和排他锁两种,本文将详细介绍共享锁及排他锁的概念、使用方式及注意事项等。
加锁目的
数据库是一个多用户使用的共享资源。当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。
锁是用于管理对公共资源的并发控制。也就是说在并发的情况下,会出现资源竞争,所以需要加锁。加锁解决了 多用户环境下保证数据库完整性和一致性。
Lock的对象是事务,用来锁定的是数据库中的对象,如表、页、行。并且一般lock的对象仅在事务commit或rollback后进行释放(不同事务隔离级别释放的时间可能不同)。
死锁
死锁是并发系统中常见的问题,同样也会出现在数据库MySQL的并发读写请求场景中。当两个及以上的事务,双方都在等待对方释放已经持有的锁或因为加锁顺序不一致造成循环等待锁资源,就会出现“死锁”。常见的报错信息为 ” Deadlock found when trying to get lock... ”。
死锁场景
举例来说A事务持有X1锁 ,申请 X2 锁,B事务持有 X2 锁,申请 X1 锁。A 和 B 事务持有锁并且申请对方持有的锁进入循环等待,就造成了死锁。
InnoDB 锁类型
为了分析死锁,我们有必要对 InnoDB 的锁类型有一个了解。
MySQL InnoDB引擎实现了标准行级别锁:共享锁( S lock ) 和排他锁 ( X lock )
不同事务可以同时对同一行记录加S锁。
如果一个事务对某一行记录加 X 锁,其他事务就不能加 S 锁或者 X 锁,从而导致锁等待。
如果事务T1持有行r的S锁,那么另一个事务 T2 请求r的锁时,会做如下处理:
T2 请求 S 锁立即被允许,结果 T1 T2 都持有 r 行的 S 锁
T2 请求 X 锁不能被立即允许
如果T1持有r的 X 锁,那么T2请求r的X、S锁都不能被立即允许,T2 必须等待 T1 释放 X 锁才可以,因为 X 锁与任何的锁都不兼容。共享锁和排他锁的兼容性如下所示:
间隙锁(gap lock)
间隙锁锁住一个间隙以防止插入。假设索引列有2, 4, 8 三个值,如果对 4 加锁,那么也会同时对(2,4)和(4,8)这两个间隙加锁。其他事务无法插入索引值在这两个间隙之间的记录。
但是,间隙锁有个例外:
如果索引列是唯一索引,只会锁住这条记录(只加行锁),而不会锁住间隙。 对于联合索引且是唯一索引,如果 where 条件只包括联合索引的一部分,那么依然会加间隙锁。
产生间隙的条件
使用普通索引锁定;
使用多列唯一索引;
使用唯一索引锁定多行记录。
next-key lock(Record Lock + Gap Lock 临键锁)
next-key lock 实际上就是 行锁+这条记录前面的 gap lock 的组合。假设有索引值10,11,13和 20,那么可能的 next-key lock 包括:
- (负无穷,10] - (10,11] - (11,13] - (13,20] - (20,正无穷)
在RR隔离级别下,InnoDB 使用 next-key lock 主要是防止幻读问题产生。
临键锁,是记录锁与间隙锁的组合,它的封锁范围,既锁住记录本身还锁住索引之间的间隙。
注:临键锁的主要目的,也是为了避免幻读(Phantom Read)。如果把事务的隔离级别降级为RC,临键锁则也会失效。
意向锁( Intention lock )
InnoDB为了支持多粒度的加锁,允许行锁和表锁同时存在。为了支持在不同粒度上的加锁操作,InnoDB 支持了额外的一种锁方式,称之为意向锁( Intention Lock ),意向锁是 InnoDB 自动加的,不需用户干预。
意向锁是将锁定的对象分为多个层次,意向锁意味着事务希望在更细粒度上进行加锁。
意向锁分为两种:
意向共享锁( IS ):事务有意向对表中的某些行加共享锁:(事务务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的 IS 锁)
意向排他锁( IX ):事务有意向对表中的某些行加排他锁:(事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的 IX 锁)
由于InnoDB存储引擎支持的是行级别的锁,因此意向锁其实不会阻塞除全表扫描以外的任何请求。表级意向锁与行级锁的兼容性如下所示: 意向锁有什么用? 主要作用是处理行锁和表锁之间的矛盾,能够显示“某个事务正在某一行上持有了锁,或者准备去持有锁” 当我们需要加一个排他锁时,需要根据意向锁去判断表中有没有数据行被锁定
比如事务A要在一个表上加S锁,如果表中的一行已被事务B加了X锁,那么该锁的申请也应被阻塞。如果表中的数据很多,逐行检查锁标志的开销将很大,系统的性能将会受到影响。为了解决这个问题,可以在表级上引入新的锁类型来表示其所属行的加锁情况,这就引出了“意向锁”的概念。
举个例子,如果表中记录1亿,事务A把其中有几条记录上了行锁了,这时事务B需要给这个表加表级锁,如果没有意向锁的话,那就要去表中查找这一亿条记录是否上锁了。
如果存在意向锁,那么假如事务A在更新一条记录之前,先加意向锁,再加X锁,事务B先检查该表上是否存在意向锁,存在的意向锁是否与自己准备加的锁冲突,如果有冲突,则等待直到事务A释放,而无须逐条记录去检测。 事务B更新表时,其实无须知道到底哪一行被锁了,它只要知道反正有一行被锁了就行了。
行锁的算法
Record Lock(单行记录)
单条索引上加锁,record lock 永远锁的是索引,而非数据本身,如果innodb表中没有索引,那么会自动创建一个隐藏的聚集索引,锁住的就是这个聚集索引。
当一条sql没有走任何索引时,那么将会在每一条聚集索引后面加X锁,这个类似于表锁,但原理上和表锁应该是完全不同的。
记录锁的条件
命中单行记录并且命中的条件字段是唯一索引或者主索引; update user_info set name=’张三’ where id=1;
//这里的id是唯一索引,使用了Record Lock
Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,那么这时InnoDB存储引擎会使用隐式的主键来进行锁定。
插入意向锁( Insert Intention lock )
插入意向锁是在插入一行记录操作之前设置的一种间隙锁,这个锁释放了一种插入方式的信号,即多个事务在相同的索引间隙插入时如果不是插入间隙中相同的位置就不需要互相等待。假设某列有索引值2,6,只要两个事务插入位置不同(如事务 A 插入3,事务 B 插入4),那么就可以同时插入。
锁模式兼容矩阵
横向是已持有锁,纵向是正在请求的锁:
“Lock锁的原理是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注创新互联网站,小编将为大家输出更多高质量的实用文章!
新闻标题:Lock锁的原理是什么
文章来源:http://lswzjz.com/article/pegdsi.html