MySQL锁和事务(一):InnoDB锁(MySQL 官方文档粗翻)
// 写在前面,实际上,数据库加锁的类型和范围受到多种因素的影响,例如数据库隔离等级,SQL语句,是否使用主键、索引等等。可以查看博文: http://www.cnblogs.com/zhaoyl/p/4121010.html 了解
这一章节讲述了InnoDB使用的锁类型。
- 共享锁(S)和独占锁(X)
- 意向锁
- 行锁(record lock,不知道叫 记录锁是不是更好,百度了一下有人叫行锁)
- 间隙锁(gap lock)
- Next-Key锁
- 插入意向锁
- AUTO-INC(自增长)锁
- 空间锁(Predicate Locks for Spatial Indexes)
共享锁和独占锁
InnoDB实现了两种标准的行级锁,一种是共享锁(S锁),一种是独占锁(X锁)。
- 共享锁允许事务读取一条记录。
- 独占锁允许事务更新或者删除一条记录的锁。
如果一个事务 T1 拥有记录 r 的共享锁,另外一个事务 T2 想要对行 r 加锁的请求会得到这样的处理:
- 如果 T2 想要加一个 S 锁,那么他能马上获得这个锁。结果就是,T1 和 T2 同时拥有 r 的共享锁。
- T2 想要获取的是 X 锁,那么这么请求会被阻塞。
如果一个事务 T1 拥有行 r 的 X 锁,另外一个事务 无论想获取 r 的什么锁都会被阻塞。事务 T2 必须要先等待 T1释放 r 上面的S锁。
意向锁
InnoDB 支持多粒度的锁,允许行锁和表锁共存。为了支持多粒度的锁,InnoDB引入了意向锁。意向锁是一个表级别的锁,表明一个事务在之后(requires later)要获取表中某些行的S锁或X锁。InnoDB中使用了两种意向锁(假设事务 T 已经向表 t 请求获取对应的意向锁)
- 意向共享锁(IS):事务 T 想要对表 t 中的一些行加上S锁。
- 意向排他锁(IX):事务 T 想要对这些行加上X锁。
例如
SELECT ... LOCK IN SHARE MODE
设置了 IS 锁,而
SELECT ... FOR UPDATE
设置了 IX 锁。
意向锁协议(The intention locking protocol)如下所示:
- 在一个事务获取表 t 中某一行的 S锁之前,他必须先获取 IS锁或者一个更重量级的锁(X等)
- 在一个事务获取一行的 X锁之前,他必须先获取表 t的 IX锁。
这些规则可以总结为下面的图表(横向表示一个事务已经获取了对应的锁,纵向表示另外一个锁想要获取对应的锁--这段话我自己加的):
| X | IX | S | IS | |
| X | 冲突 | 冲突 | 冲突 | 冲突 |
| IX | 冲突 | 不冲突 | 冲突 | 不冲突 |
| S | 冲突 | 冲突 | 不冲突 | 不冲突 |
| IS | 冲突 | 不冲突 | 不冲突 | 不冲突 |
当行上的锁与已经存在的锁不冲突(兼容)时,可以被事务请求获取,如果冲突话,就不行。事务必须等待冲突的锁被释放(才能获取想要的锁)。如果一个加锁请求与已存在的锁相互冲突,又一直得不到锁,可能是发生了死锁,或者出现了错误。
因此,意向锁不会阻塞除全表请求(例如,LOCK TABLES ...WAITE)之外其他请求。IX 和 IS锁的主要目的是表明 某个请求(someone)已经锁定了一行,或者将要锁定一行记录。
意向锁加锁过程中记录的事务数据类似于下面使用 SHOW ENGINE INNODB STATUS语句的 InnoDB 监控输出:
TABLE LOCK TABLE 'test.'t' trx id 10080 lock mode IX
行锁
行锁是一个加在索引记录上的锁,例如,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;会阻止其他任何事务插入,更新或者删除那些 t.c1 = 10的记录。
行锁总是在索引记录上面加锁,即使一张表没有任何索引,在这种情况下,InnoDB会创建一个隐藏的聚集索引,然后使用这个索引来加上行锁。
行锁加锁过程中记录的事务数据类似于下面使用 SHOW ENGINE INNODB STATUS语句的 InnoDB 监控输出:
RECORDS LOCKS space id 58 page no 3 n bits 72 index 'PRIMARY' of table 'test'.'t'
trx id 10078 lock_mode X locks rec but not gap
Record lock ,heap on 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 8000000a; asc ;;
1: len 6; hex 00000000274f; asc 'O;;
2: len 7; hex b60000019d0110; asc ;;
间隙锁
间隙锁是在索引记录的间隙上加的锁,或者在第一条索引记录之前、最后一条索引记录之后的区间上加的锁。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 AND 20 FOR UPDATE; 阻止所有其他的事务 插入一条 t.c1 = 15的记录,无论是否表中已经有一列的值是15(或者其他10-20之间的值),因为在这个范围内的间隙都已经被加上了锁。
间隙可能只包括一个索引值,也可能包括多个索引值,甚至不包含任何索引值。
使用唯一索引查找唯一一条记录的语句是不会使用到间隙锁的(这不包括查询条件仅包含一个唯一索引的一部分的语句)。例如,假如 id 列有一个唯一索引,下面的语句只会使用行锁加到 id = 100的行上面,而不会关心别的会话(session)是否在上述的间隙中插入数据。
SELECT * FROM child WHERE id = 100 ; (感觉应该加一个 FOR UPDATE 或者 IN SHARE MODE 或者 数据库隔离等级为 serializable)
如果 id 列没有索引或者不是唯一索引,这个语句会在上述的间隙上加锁。
值得提醒的是,不同的事务可以在间隙上拥有相互冲突的锁。例如,事务 A 可以某一个间隙上的共享锁(gap S-lock),同时另外一个事务可以在同一个间隙上拥有独占锁(gap X-lock)。原因在于如果一条索引记录被删除,其他事务拥有的对应间隙锁必须进行归并(强行翻译,不太明白,原文:The reason conflicting gap locks are allowed is that if a record is purged from an index, the gap locks held on the record by different transactions must be merged.)
间隙锁是 ”完全禁止性的“(强行翻译:purely inhibitive,看下文应该很好理解),意味着他们只会禁止其他的事务插入数据到间隙之中,而不会禁止别的事务获取同一区间的间隙锁。因此,间隙 X锁和间隙 S锁起到的效果是一样的。
间隙锁可以被明确的禁止。你可以将事务隔离等级设置为 READ COMMITTED 或者启用 innodb_locks_unsafe_for_binlog 系统变量(现在不建议使用 deprecated)。在这些情况下,间隙锁在查询和索引扫描中被禁用,只会在外键约束检查和重复索引检查时才会使用。
使用READ COMMITTED 隔离等级和 启用innodb_locks_unsafe_for_binlog系统变量也会造成一些额外的影响。在MySQL分析完 WHERE 条件之后,不匹配的行上面的行锁会被释放。对于 UPDATE 语句,InnoDB 进行一个”半一致性“读,它会返回最新提交的版本(的行记录)给MySQL,然后MySQL
确定哪些行匹配了 UPDATE 的 WHERE 条件。
Next-Key Locks
next-key 锁是行锁和在行锁之前的间隙上的间隙锁的联合。
InnoDB以这种形式实现行级锁,当他查找或扫描表索引的时候,遇到匹配的的索引记录,在上面加上对应的共享锁或者独占锁。因此,行级锁实际上是索引记录锁。next-key锁同是会影响索引记录之前的间隙。就是说,next-key lock就是一个索引记录锁加上一个在索引记录之前的间隙上的间隙锁。如果一个会话拥有记录 R 的索引上面的一个共享锁或独占锁,另外的会话无法立即在 R记录索引顺序之前的间隙上插入一条新的记录。
假设有一个索引包含值10,11,13和20。下列的间隔上都可能加上一个next-key lock,(符号表示不包含端点,]符号表示包含端点。
(negative infinity ,10]
(10,11]
(11,13]
(13,20]
(20,positive infinity)
在最后一个区间中,next-key lock锁定了索引中的最大值到一个“上确界”(一个虚假的索引记录,他的值比所有索引记录中所有值都要大)。上确界不是一个真实存在的索引记录,所以,事实上,这个nex-key lock只是锁定了最大索引值之后的区间。
默认情况下,InnoDB启用 REPEATABLE READ 事务隔离等级。在这种情况下,InnoDB在查找和扫描索引时会使用 nex-key lock,能避免 幻(影)行的出现。
next-key lock 加锁过程中记录的事务数据类似于下面使用 SHOW ENGINE INNODB STATUS语句的 InnoDB 监控输出:
RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t`
trx id 10080 lock_mode X
Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0
0: len 8; hex 73757072656d756d; asc supremum;;
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 8000000a; asc ;;
1: len 6; hex 00000000274f; asc 'O;;
2: len 7; hex b60000019d0110; asc ;;
插入意向锁
插入意向锁
AUTO-INC Locks(自增长锁)
自增长锁是特殊的表级锁,被那些插入带有AUTO_INCREMENT行的记录到表中时占用。一个最简单的例子,当一个事务在插入数据到表中时,其他任何的事务都等待,因此,第一个事务插入的行能够拥有连续的主键值。
innodb_autoinc_lock_mode配置选项控制了自增长锁使用的算法。他允许你在可预测的自增长值和最大化并发插入操作之间进行权衡。
空间索引的断言锁
InnoDB支持空间列上面的空间索引。
在处理包括空间索引的相关锁定操作时,next-key locking 在支持 REPEATABLE READ 和 SERIALIZABLE 事务隔离等级 上工作的不太好。在多维的数据上,没有一个绝对的顺序,因此,“下一个”键在哪里并不是很清楚。
为了支持带有 空间索引的隔离等级,InnoDB使用了断言锁。空间索引包含了 最小外接矩阵(minimum bounding rectangle = MBR)值,所以InnoDB 强制对索引一致性读的时候对查询语句中使用的MBR值上设置一个断言索引。其他的事务不能插入或者修改匹配这个查询条件的行。
MySQL锁和事务(一):InnoDB锁(MySQL 官方文档粗翻)的更多相关文章
- Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇)
Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇) 目录 Mysql优化(出自官方文档) - 第十二篇(优化锁操作篇) 1 Internal Locking Methods Row-Leve ...
- Mysql优化(出自官方文档) - 第十篇(优化InnoDB表篇)
Mysql优化(出自官方文档) - 第十篇(优化InnoDB表篇) 目录 Mysql优化(出自官方文档) - 第十篇(优化InnoDB表篇) 1 Optimizing Storage Layout f ...
- Mysql优化(出自官方文档) - 第七篇
Mysql优化(出自官方文档) - 第七篇 目录 Mysql优化(出自官方文档) - 第七篇 Optimizing Data Change Statements 1 Optimizing INSERT ...
- Mysql优化(出自官方文档) - 第五篇
目录 Mysql优化(出自官方文档) - 第五篇 1 GROUP BY Optimization 2 DISTINCT Optimization 3 LIMIT Query Optimization ...
- Mysql优化(出自官方文档) - 第三篇
目录 Mysql优化(出自官方文档) - 第三篇 1 Multi-Range Read Optimization(MRR) 2 Block Nested-Loop(BNL) and Batched K ...
- Mysql优化(出自官方文档) - 第八篇(索引优化系列)
目录 Mysql优化(出自官方文档) - 第八篇(索引优化系列) Optimization and Indexes 1 Foreign Key Optimization 2 Column Indexe ...
- Mysql优化(出自官方文档) - 第九篇(优化数据库结构篇)
目录 Mysql优化(出自官方文档) - 第九篇(优化数据库结构篇) 1 Optimizing Data Size 2 Optimizing MySQL Data Types 3 Optimizing ...
- 手把手教你看MySQL官方文档
前言: 在学习和使用MySQL的过程中,难免会遇到各种问题.不知道当你遇到相关问题时会怎么做,我在工作或写文章的过程中,遇到不懂或需要求证的问题时通常会去查阅官方文档.慢慢的,阅读文档也有了一些经验, ...
- Mysql优化(出自官方文档) - 第四篇
Mysql优化(出自官方文档) - 第四篇 目录 Mysql优化(出自官方文档) - 第四篇 1 Condition Filtering 2 Constant-Folding Optimization ...
随机推荐
- HTTPS 证书配置
HTTPS 证书配置 现在阿里云和腾讯云都支持申请 HTTPS 证书,这里不再提,有需要的可自行google解决方案. 本文主要介绍的是通过 letsencrypt 申请免费的HTTPS证书,并将其配 ...
- Java面试准备之探究集合
摘要:之前虽然对集合框架一些知识点作了总结,但是想想面试可能会问源码,于是又大致研究了一下集合框架的一些实现类的源码,在此整理一下. 一.集合框架 二.深究实现类 1.ArrayList源码实现 Ar ...
- Maven项目下update maven后Eclipse报错:java.lang.ClassNotFoundException: ContextLoaderL
Maven项目下update maven后Eclipse报错:java.lang.ClassNotFoundException: ContextLoaderL 严重: Error config ...
- 实现CA证书创建及客户端申请证书
author:JevonWei 版权声明:原创作品 CA证书的相关文件路径 openssl配置文件/etc/pki/tls/openssl.cnf /etc/pki/tls/openssl.cnf C ...
- H - transaction transaction transaction
https://vjudge.net/contest/184514#problem/H 题意: 一个商人为了赚钱,在城市之间倒卖商品.有n个城市,每个城市之间有且只有一条无向边连通.给出n个城市的货物 ...
- outlook 无法搜索邮件的解决方法
我的outlook版本是2007 SP3,英文版.一直有搜索不到邮件的问题,例如在搜索框输入发件人的名字,或者邮件中的词语,就是搜索不到邮件,即使那封邮件确实存在. 在网上搜索,Microsoft 的 ...
- 【Beta】 第三次Daily Scrum Meeting
一.本次会议为第三次meeting会议 二.时间:10:00AM-10:20AM 地点:禹州楼 三.会议站立式照片 四.今日任务安排 成员 昨日任务 今日任务 林晓芳 查询app提醒功能模块和用户登录 ...
- 201521123002 《Java程序设计》第3周学习总结
1. 本周学习总结 初学面向对象,会学习到很多碎片化的概念与知识.尝试学会使用思维导图将这些碎片化的概念.知识组织起来.请使用纸笔或者下面的工具画出本周学习到的知识点.截图或者拍照上传. 2. 书面作 ...
- 201521123064 《Java程序设计》第9周学习总结
1. 本章学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次作业题集异常 Q1:常用异常 题目5-1 1.1 截图你的提交结果(出现学号) 1.2 自己以前 ...
- foreach_and_函数
foreach(对集合每个元素的引用 in 集合){}例: int[] a = new int[5]{1,2,3,4,5,}; foreach(int b in a) { //b就是a中的每个元素 } ...