行锁的3中算法

Record Lock:单个行记录上的锁

Gap Lock:间隙锁,锁定一个范围,但不包含记录本身

Next-key Lock:Gap Lock+Record Lock锁定一个范围,并且锁定记录本身

Record Lock总是会去锁住索引记录,如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,那么这是会使用隐式的主键来进行锁定

Next-Key Lock是结合Gap Lock和Record Lockd 一种锁定算法,在Nex-Key Lock算法下,InnoDB对于行的查询都是采用这种锁定算法,例如一个索引有10 11 13 20这四个值,那么该索引可能被Next-Key Locking的区间为:

看一下执行表的SQL语句

表t共有1 2 5 三个值,在会话A中首先对a=5进行了X锁定。而由于a是主键且唯一,因此锁定的仅是5这个值,而不是(2,5)这个范围,这样在会话B中插入4不会阻塞,可以立即插入并返回,及锁定由Next-Key Lock算法降级为了Record Lock,从而提高应用的并发性

正如前面介绍,Next-Key Lock 降级为Record Lock仅在查询的列是唯一索引的情况下,如果是辅助索引,有不同

>create table z(a INT,b INT, PRIMARY KEY(a),KEY(b));

>INSERT INTO z SELECT 1,1;

>INSERT INTO z SELECT 3,1;

>INSERT INTO z SELECT 5,3;

>INSERT INTO z SELECT 7,6;

>INSERT INTO z SELECT 10,8;

表z的列b是辅助索引,若在会话A中执行下面的SQL语句

>SELECT  * FROM z WHERE b=3 FRO UPDATE;

很明显,这是SQL语句通过索引b进行查询,因此使用传统的Next-Key Locking技术加锁,并且由于有两个索引,其需要分别进行锁定,对于聚集索引,其仅对列a等于5的索引加Record Lock,而对于辅助索引,其加上了Next-Key Lock,锁定的范围是(1,3)特别需要注意的是,InnoDB存储引擎还会对辅助索引的下一个键值加上gap lock,即还有一个辅助索引范围为(3,6)的锁。因此在会话B中运行下面语句会被阻塞

>SELECT * FROM z WHERE a=5 LOCK IN SHARE MODE;

>INSERT INTO z SELECT 4,2;

>INSERT INTO z SELECT 6,5;

第一个SQL语句不能执行,因为在会话A中执行的SQL语句已经对聚集索引中的列a=5的值做了X锁,因此执行会阻塞,第二个SQL语句,主键插入4,没有问题,但是辅助索引2在锁定的范围(1,3)中,因此执行同样会被阻塞。第三个SQL语句,插入主键6没有被锁定,5也不再范围(1,3)之间,但是插入的值5在另一个锁定的范围(3,6)中,故同样需要等待。而下面的SQL语句,不会被阻塞。可以理解执行

>INSERT INTO z SELECT 8,6;

>INSERT INTO z SELECT 2,0;

>INSERT INTO z SELECT 6,7;

从上面的例子可以看到,Gap Lock的作用是为了阻止多个事务将记录插入到同一个范围内,而这会导致Phantom Problem问题的产生。例如上面例子中,会话A中用户已经锁定了b=3的记录,若此时没有Gap Lock锁定(3,6)那么用户可以插入索引b列为3的记录,这样会导致会话A中的用户再次执行同样查询时会返回不同的记录,即导致Phantom Problem问题的产生。

用户可以通过以下两种方式来显式的关闭Gap Lock:

将事务的隔离级别设成RC

将参数innodb_locks_unsafe_for_binlog 设置为1

在上述配置中,除了外键约束和唯一性约束检查依然需要Gap Lock,其余情况仅适用于Record Lock进行锁定,但需要牢记,上述设置破坏了事务的隔离性,并且对于replication,可能会导致主从不一致。此外,从性能上看,RC也不会优于默认的事务隔离级别RR

在InnoDB存储引擎中,对于INSERT操作,其会检查插入记录的下一条记录是否被锁定,若已经被锁定,则不允许查询,对于上面例子,会话A已经锁定了表z中b=3的记录,即已经锁定(1,3)范围,这是若在其他会话插入同样的会导致阻塞

>INSERT INTO t SELECT 2,2;

因为在辅助索引b上插入值为2的记录时,会检测到下一个记录3已经被索引,而将插入的值修改为如下的值,则可以立即执行

>INSERT INTO t SELECT 2,0;

需要再次提醒,对于唯一键值的锁定,Next-Key Lock降级为Record Lock进存在于查询所有的唯一索引列。若唯一索引由多个列组成,而查询仅是查找多个唯一索引列中的其中一个,那么查询其实是range类型查询,而不是point类型查询,故InnoDB存储引擎依然使用Next-Key Lock进行锁定

MySQL中行锁的算法的更多相关文章

  1. MySQL:锁机制和隔离事务级别

    在mysql中的锁看起来是很复杂的,因为有一大堆的东西和名词:排它锁,共享锁,表锁,页锁,间隙锁,意向排它锁,意向共享锁,行锁,读锁,写锁,乐观锁,悲观锁,死锁.这些名词有的博客又直接写锁的英文的简写 ...

  2. Mysql Innodb 锁机制

    latch与lock latch 可以认为是应用程序中的锁,可以称为闩锁(轻量级的锁) 因为其要求锁定的时间必须要非常短,若持续时间长,则会导致应用性能非常差,在InnoDB存储引擎中,latch又可 ...

  3. MySQL InnoDB锁机制

    概述: 锁机制在程序中是最常用的机制之一,当一个程序需要多线程并行访问同一资源时,为了避免一致性问题,通常采用锁机制来处理.在数据库的操作中也有相同的问题,当两个线程同时对一条数据进行操作,为了保证数 ...

  4. 关于mysql 间隙锁

    前段时间系统老是出现update死锁,很是纠结.经过排查发现是间隙锁!间隙锁是innodb中行锁的一种, 但是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围.间隙锁的主要作用是为了防止出现 ...

  5. day 59 MySQL之锁、事务、优化、OLAP、OLTP

    MySQL之锁.事务.优化.OLAP.OLTP   本节目录 一 锁的分类及特性 二 表级锁定(MyISAM举例) 三 行级锁定 四 查看死锁.解除锁 五 事务 六 慢日志.执行计划.sql优化 七 ...

  6. MySQL间隙锁问题

    间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间. 最近用户反馈说系统老是出现insert时,等待超时了,最后发现是ins ...

  7. MySql 中锁的定义

    行级锁,一般是指排它锁,即被锁定行不可进行修改,删除,只可以被其他会话select.行级锁之前需要先加表结构共享锁. 表级锁,一般是指表结构共享锁锁,是不可对该表执行DDL操作,但对DML操作都不限制 ...

  8. mysql 乐观锁、悲观锁、共享锁,排它锁

    mysql锁机制分为表级锁和行级锁,本文就和大家分享一下我对mysql中行级锁中的共享锁与排他锁进行分享交流. 共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能 ...

  9. 一文详解MySQL的锁机制

    一.表级锁.行级锁.页级锁 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则. MySQL数据库由于其自身架构的特点,存在多种数据存储引擎, ...

随机推荐

  1. Tony zhao:到底怎么样才叫看书?

    http://blog.jobbole.com/25842/ 目录: 一.引入 二.经历了就能理解 三.读书要分级 四.只读经典 五.别吝惜你动笔的那点时间 一.引入 看到这个题目的时候你可能会感到有 ...

  2. ajax+webapi上传图片问题

    自己想写一个原生的JS的图片上传,不想一直只是使用上传文件的框架 网上有很多jquery上传图片上传文件的插件,但是要不是用特定的后台框架接收,要不就是只能上传图片,不是文件,还有一些其他的问题,所以 ...

  3. rac_安装软件时报版本号过高问题

    原创作品,出自 "深蓝的blog" 博客.欢迎转载,转载时请务必注明下面出处,否则追究版权法律责任. 深蓝的blog:http://blog.csdn.net/huangyanlo ...

  4. JSONP(转)

    1 什么是Jsonp? JSONP(JSON with Padding)是数据格式JSON的一种“使用模式”,可以让网页从别的网域要数据.另一个解决这个问题的新方法是跨来源资源共享. 由于同源策略,一 ...

  5. spring 基础回想 tips01

    spring 属性注入时,类中必须有setter 和 getter方法. spring配置文件里: java业务类中注入DAO: private StudentDao studentDao; // 通 ...

  6. JQuery常用操作实现方式

    http://www.cnblogs.com/guomingfeng/articles/2038707.html 一个优秀的 JavaScript 框架,一篇 jQuery 常用方法及函数的文章留存备 ...

  7. C++学习笔记34 模版的原理

    模版在C++中具有很重要的地位.STL就是大量运用模版写出来的. 模版的长处我就不一一列举了.这里我仅仅说一下模版的原理. 当编译器遇到模版方法定义的时候,编译器进行语法检查,可是并不会编译模版.编译 ...

  8. Python内置函数之bytes()

    该函数是一个类对象: class bytes([source[,encoding[,errors]]]) 返回值为字节对象,当第一个参数为字符串时,必须提供第二个参数,第二个参数为编码类型的字符串. ...

  9. PHP图片识别成文字

    http://apistore.baidu.com/apiworks/servicedetail/146.html 分类: php2011-- : 3576人阅读 评论() 收藏 举报 phpfunc ...

  10. object is not an instance of declaring class

    错误原因:invoke方法的时候,应该是类的实例对象,而不是类本身 解决方法:把 PowerMockito.doReturn(index_expect).when(IndexController.cl ...