InnoDB中不同SQL语句设置的锁
锁定读(locking read)、更新(UPDATE)或删除(DELETE)通常会在SQL语句处理过程中扫描的每个索引记录上设置记录锁。语句中是否存在排除行的WHERE条件并不重要。InnoDB不记得确切的WHERE条件,而只知道哪个索引范围被扫描。这些锁通常是next-key锁,它还会阻止在记录之前插入“间隙”。然而,间隙锁(gap lock)可以被显式禁用,这会导致不使用next-key锁。
如果在检索中使用了二级索引,并且要设置的索引记录锁是排它的,则InnoDB也会检索相应的聚集索引记录并在它们上设置锁。
执行SQL语句时,如果没有找到可用的索引,MySQL必须扫描整个表来处理该语句,这样的话表的每一行都会被锁定,从而阻塞其他用户对表的所有插入。因此,创建良好的索引非常重要,这样可以避免扫描许多不必要的行。
InnoDB设置特定类型的锁,如下所示:
SELECT ... FROM 是一致读,读取数据库快照,除非将事务隔离级别设置为SERIALIZABLE,否则不设置锁。对于SERIALIZABLE级别,检索会在遇到的索引记录上设置共享的next-key锁。但是,对于使用唯一索引来搜索唯一行的语句,只需要一个索引记录锁。
对于 SELECT ... FOR UPDATE 或者 SELECT ... LOCK IN SHARE MODE ,对扫描的行加锁,并对不符合结果集中包含条件的行(例如,如果它们不满足WHERE子句中给出的条件)释放锁。
SELECT ... LOCK IN SHARE MODE 在所有遇到的索引记录上设置共享的next-key锁。但是,对于使用唯一索引来搜索唯一行的语句,只需要一个索引记录锁。
SELECT ... FOR UPDATE 在搜索遇到的每个记录上设置排它的next-key锁。但是,对于使用唯一索引来搜索唯一行的语句,仅需要索引记录锁定。
UPDATE ... WHERE ... 在搜索遇到的每个记录上设置排它的next-key锁。但是,对于使用唯一索引来搜索唯一行的语句,仅需要索引记录锁定。
DELETE FROM ... WHERE ... 在搜索遇到的每个记录上设置排它的next-key锁。但是,对于使用唯一索引来搜索唯一行的语句,仅需要索引记录锁定。
INSERT 在插入的行上设置排他锁。该锁是索引记录锁,不是next-key锁(即没有间隙锁),并且不会阻止其他会话插入到插入行之前的间隙中。
举个例子,假设有一张表t1,结构如下:
CREATE TABLE t1 (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;
再假设,有三个会话操作顺序如下:
Session 1:
START TRANSACTION;
INSERT INTO t1 VALUES(1);
Session 2:
START TRANSACTION;
INSERT INTO t1 VALUES(1);
Session 3:
START TRANSACTION;
INSERT INTO t1 VALUES(1);
Session 1:
ROLLBACK;
首先Session1获得i=1这一行的排它锁,接下来Session2和Session3由于主键重复只能请求获取该行的共享锁,由于行上已经有排它锁,因此Session2和Session3请求的共享锁不能被立即授予。再接着,Session1回滚,行上的排它锁被释放,于是Session2和Session3在该行上都持有共享锁,此时,死锁发生了,由于对方持有的共享锁,任何一方都不能获得该行的排它锁。
下面这组操作也是类似:
Session 1:
START TRANSACTION;
DELETE FROM t1 WHERE i = 1;
Session 2:
START TRANSACTION;
INSERT INTO t1 VALUES(1);
Session 3:
START TRANSACTION;
INSERT INTO t1 VALUES(1);
Session 1:
COMMIT;
和前面的情况类似,Session1提交以后,Session2和Session3请求该行上的共享锁被立即授予,此时它们再请求获取排它锁时就出现死锁了,因为共享锁被另一个事务持有。
补充: 聚集索引与辅助索引
clustered index (译:聚集索引、聚簇索引)
secondary index (译:二级索引、辅助索引)
每个InnoDB表都有一个特殊的索引,称为聚集索引,用于存储行数据。通常,聚集索引与主键是同义词。为了从查询、插入和其他数据库操作中获得最佳性能,必须了解InnoDB如何使用聚集索引来优化每个表的最常见的查找和DML操作。
Typically, the clustered index is synonymous with the primary key.
通常,“clustered index” 和 “primary key” 是一个意思。
当你在表上定义一个PRIMARY KEY时,InnoDB将它用作聚集索引。为创建的每个表定义一个主键。如果没有逻辑唯一的非空列或列集,请添加一个新的自动递增(auto-increment)列,其值将自动填充。
如果你没有为你的表定义一个PRIMARY KEY,则MySQL会在所有键列都不为NULL的情况下找到第一个唯一索引,并且InnoDB使用它作为聚集索引。
如果表没有主键或合适的唯一索引,InnoDB会在包含行ID值的合成列上内部生成一个名为GEN_CLUST_INDEX的隐藏聚集索引
通过聚集索引访问行非常快,因为索引搜索直接指向包含所有行数据的页。如果表很大,聚集索引体系结构通常节省磁盘I/O操作。
除了聚集索引之外的所有索引都称为二级索引。在InnoDB中,二级索引中的每条记录都包含该行的主键列,以及为二级索引指定的列。InnoDB使用此主键值在聚集索引中搜索行。
如果主键很长,则辅助索引将使用更多空间,因此具有主键较短是比较有利的。
With the exception of spatial indexes, InnoDB indexes are B-tree data structures. Index records are stored in the leaf pages of their B-tree or R-tree data structure. The default size of an index page is 16KB. Supported sizes are 64KB, 32KB, 16KB (default), 8KB, and 4KB.
InnoDB中不同SQL语句设置的锁的更多相关文章
- InnoDB 中不同SQL语句设置的锁
锁定读.UPDATE 或 DELETE 通常会给在SQL语句处理过程扫描到的每个索引记录上设置记录锁.语句中是否存在排除该行的WHERE条件并不重要.InnoDB不记得确切的WHERE条件,但只知道哪 ...
- MySQL innodb中各种SQL语句加锁分析
概要 Locking read( SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARE MODE),UPDATE以及DELETE语句通常会在他扫描的索引所 ...
- 14.3.3 Locks Set by Different SQL Statements in InnoDB 不同的SQL语句在InnoDB里的锁设置
14.3.3 Locks Set by Different SQL Statements in InnoDB 不同的SQL语句在InnoDB里的锁设置 locking read, 一个UPDATE,或 ...
- 在phpmyadmin中执行sql语句出现的错误:Unknown storage engine 'InnoDB'
在phpmyadmin中执行sql语句出现的错误:Unknown storage engine 'InnoDB' 解决方法:解决方法: 1.关闭MySQL数据库 2 ...
- 重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系
重新学习MySQL数据库9:Innodb中的事务隔离级别和锁的关系 Innodb中的事务隔离级别和锁的关系 前言: 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁 ...
- 【转载】Innodb中的事务隔离级别和锁的关系
前言 我们都知道事务的几种性质,数据库为了维护这些性质,尤其是一致性和隔离性,一般使用加锁这种方式.同时数据库又是个高并发的应用,同一时间会有大量的并发访问,如果加锁过度,会极大的降低并发处理能力.所 ...
- 在mybatis中写sql语句的一些体会
本文会使用一个案例,就mybatis的一些基础语法进行讲解.案例中使用到的数据库表和对象如下: article表:这个表存放的是文章的基础信息 -- ------------------------- ...
- [转]在EntityFramework6中执行SQL语句
本文转自:http://www.cnblogs.com/wujingtao/p/5412329.html 在上一节中我介绍了如何使用EF6对数据库实现CRDU以及事务,我们没有写一句SQL就完成了所有 ...
- 在EntityFramework6中执行SQL语句
在EntityFramework6中执行SQL语句 在上一节中我介绍了如何使用EF6对数据库实现CRDU以及事务,我们没有写一句SQL就完成了所有操作.这一节我来介绍一下如何使用在EF6中执行SQL语 ...
- C语言中嵌入式SQL语句
原文:[转载]C语言中嵌入式SQL语句 http://blog.csdn.net/cnlht/archive/2007/12/12/1930960.aspx原文地址 实验内容: 掌握SQL Serve ...
随机推荐
- JMS微服务架构 - 关于事务提交失败,自动重新提交的机制
用JMS编写的微服务,由调用端决定了各个微服务执行时,是否需要保持事务的一致性. 也就是RemoteClient在调用微服务方法前,先调用BeginTransaction明确后面所调用的微服务需要保持 ...
- Go-方法-method
- [转帖]/dev/random 和 /dev/urandom的一点备忘
https://www.cnblogs.com/ohmygirl/p/random.html 1. 基本介绍 /dev/random和/dev/urandom是Linux系统中提供的随机伪设备,这两 ...
- [转帖]clickhouse安装部署以及版本选取
https://www.cnblogs.com/MrYang-11-GetKnow/p/15818768.html 1. 系统要求 ClickHouse 可以在任何具有 x86_64.AArch64 ...
- [转帖]《Linux性能优化实战》笔记(六)—— Linux 软中断与对应故障分析方法
中断是系统用来响应硬件设备请求的一种机制,它会打断进程的正常调度和执行,然后调用内核中的中断处理程序来响应设备的请求. 一. 为什么要有中断 举个生活中的例子,让你感受一下中断的魅力.比如说你订了一份 ...
- [转帖]sqlplus与shell互相传值的几种情况
https://www.cnblogs.com/youngerger/p/9068888.html sqlplus与shell互相传值的几种情况 情况一:在shell中最简单的调用sqlplus $c ...
- [转帖]Debian9换源(阿里源)(Linux子系统)
http://www.taodudu.cc/news/show-5410026.html?action=onClick 默认你已经装好Linux子系统. Step 0: 换源核心就是把/etc/apt ...
- 【转帖】26.Java本地方法的理解(native方法)
目录 1.什么是本地方法? 2. 为什么要使用Native method? 1.什么是本地方法? 本地方法就是java代码里面写的native方法,它没有方法体.是为了调用C/C++代码而写的.在JN ...
- [转帖]陈巍谈芯:NLP里比BERT更优秀的XLNet长什么样?
https://zhuanlan.zhihu.com/p/447836322 目录 收起 一.XLNet的优势 1)独得AR与AE两大绝学 2)集成了Tansformer-XL 二.XLNet的结 ...
- 文盘Rust -- r2d2 实现redis连接池
作者:贾世闻 我们在开发应用后端系统的时候经常要和各种数据库.缓存等资源打交道.这一期,我们聊聊如何访问redis 并将资源池化. 在一个应用后端程序访问redis主要要做的工作有两个,单例和池化. ...