MySQL中行锁的算法
行锁的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中行锁的算法的更多相关文章
- MySQL:锁机制和隔离事务级别
在mysql中的锁看起来是很复杂的,因为有一大堆的东西和名词:排它锁,共享锁,表锁,页锁,间隙锁,意向排它锁,意向共享锁,行锁,读锁,写锁,乐观锁,悲观锁,死锁.这些名词有的博客又直接写锁的英文的简写 ...
- Mysql Innodb 锁机制
latch与lock latch 可以认为是应用程序中的锁,可以称为闩锁(轻量级的锁) 因为其要求锁定的时间必须要非常短,若持续时间长,则会导致应用性能非常差,在InnoDB存储引擎中,latch又可 ...
- MySQL InnoDB锁机制
概述: 锁机制在程序中是最常用的机制之一,当一个程序需要多线程并行访问同一资源时,为了避免一致性问题,通常采用锁机制来处理.在数据库的操作中也有相同的问题,当两个线程同时对一条数据进行操作,为了保证数 ...
- 关于mysql 间隙锁
前段时间系统老是出现update死锁,很是纠结.经过排查发现是间隙锁!间隙锁是innodb中行锁的一种, 但是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围.间隙锁的主要作用是为了防止出现 ...
- day 59 MySQL之锁、事务、优化、OLAP、OLTP
MySQL之锁.事务.优化.OLAP.OLTP 本节目录 一 锁的分类及特性 二 表级锁定(MyISAM举例) 三 行级锁定 四 查看死锁.解除锁 五 事务 六 慢日志.执行计划.sql优化 七 ...
- MySQL间隙锁问题
间隙锁(Gap Lock):锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间. 最近用户反馈说系统老是出现insert时,等待超时了,最后发现是ins ...
- MySql 中锁的定义
行级锁,一般是指排它锁,即被锁定行不可进行修改,删除,只可以被其他会话select.行级锁之前需要先加表结构共享锁. 表级锁,一般是指表结构共享锁锁,是不可对该表执行DDL操作,但对DML操作都不限制 ...
- mysql 乐观锁、悲观锁、共享锁,排它锁
mysql锁机制分为表级锁和行级锁,本文就和大家分享一下我对mysql中行级锁中的共享锁与排他锁进行分享交流. 共享锁又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能 ...
- 一文详解MySQL的锁机制
一.表级锁.行级锁.页级锁 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种规则. MySQL数据库由于其自身架构的特点,存在多种数据存储引擎, ...
随机推荐
- Quartz.net基于数据库的任务调度管理(Only.Jobs)
一 前言: 各大调度组件优缺点在这就不讨论了,使用Quartz.net是因为它可以执行秒级任务. Only.Jobs 项目通过将各Job存储在数据库中,启动一个专门的Job管理任务来循环调度各Job的 ...
- Codeforces 476C Dreamoon and Sums (水
题目链接:点击打开链接 题意: 给定a,b 对于一个数x.若x是nice number,则满足(x/b)/(x%b) == [1,a](即结果在1-a之间) 问: 输出一个数表示 全部nice num ...
- iOS机型适配
机型变化 坐标:表示屏幕物理尺寸大小,坐标变大了,表示机器屏幕尺寸变大了: 像素:表示屏幕图片的大小,跟坐标之间有个对应关系,比如1:1或1:2等: ppi:代表屏幕物理大小到图片大小的 ...
- 初识WatiN
WatiN —— Web Application Testing In .Net 为什么会有WatiN? 给用户提供一个.Net平台下,将Web测试自动化的便捷途径. 如何通过WatiN来进行自动化测 ...
- UML类图详解_聚合关系
结合UML关系,以看台和基金来介绍聚合关系 aggregation,是一种特殊的关联关系,既有关联关系的特质,还独有“整体 —— 部分(whole —— part)”的特质. 也就是说,用之前的关联关 ...
- CentOS sendmail安装及邮件域名配置
http://www.centoscn.com/CentosServer/lighttpd/2013/0726/650.html sendmail是Linux下优秀的邮件系统.在不做任何设定的情况下, ...
- Java 扫描包下所有类(包括jar包)
package com.MyUtils.file; [java] view plain copy import java.io.File; import java.io.FileFilter; imp ...
- boost中全局命名锁的使用
使用头文件相对位置为:boost/interprocess/sync/named_mutex.hpp 在程序中使用 boost::interprocess::named_mutex g_namedmu ...
- cf #363 b
B. One Bomb time limit per test 1 second memory limit per test 256 megabytes input standard input ou ...
- Java Stream 官方文档翻译
先立个flag https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html