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 ...
随机推荐
- SQL优化工具
SQL优化工具 什么是索引? 打个比方,我们在使用MySQL用作查询的时候就好比查字典,索引就好比字典的偏旁部首页.如果没有索引我们查询一个文字就需要一页页的翻,显然这种方式效率很低.如果我们对某一字 ...
- CSS基础用法
[CSS常用选择器] 标签选择器 写法: HTML标签名{}作用: 可以选中页面中,所有与选择器同名的HTML标签. 类选择器(class选择器)写法: .class名{}调用: 在需要调用选择器样式 ...
- Java泛型:泛型类,泛型接口和泛型方法
转自: https://segmentfault.com/a/1190000002646193 泛型的产生很多缘由是因为 容器类 的创建 泛型类 容器类应该算得上最具重用性的类库之一.先来看一个没有 ...
- oracle得到日期对应的星期
详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp56 select to_char(sysdate,'ww') fro ...
- JavaScript事件循环(Event Loop)机制
JavaScript 是单线程单并发语言 什么是单线程 主程序只有一个线程,即同一时间片断内其只能执行单个任务. 为什么选择单线程? JavaScript的主要用途是与用户互动,以及操作DOM.这决定 ...
- [js高手之路]gulp教程-从入门到项目中快速上手使用
在这之前,我已经分享过一个webpack的全系列,相对于webpack, gulp使用和配置起来非常的简单. gulp是什么? gulp 是基于 node 实现 Web 前端自动化开发的工具,利用它能 ...
- 我的hibernate学习记录(二)
通过上一篇文章我的hibernate学习记录(一)基本上的入门了hibernate,但是,里面还有还多东西是通过迷迷糊糊的记忆,或者说copy直接弄进去的,所以这篇文章就需要对上篇的一些文件.对象进行 ...
- window.requestAnimationFrame() ,做逐帧动画,你值得拥有
window.requestAnimationFrame() 方法告诉浏览器您希望执行动画,并请求浏览器调用指定的函数在下一次重绘之前更新动画.该方法使用一个回调函数作为参数,这个回调函数会在浏览器重 ...
- 标题:a++和++a的区别
以前我也是老搞不懂a++和++a的区别, 后来看了很多资料, 终于总结出来一条规律, 小白专用! 看完这个例子就懂了: 例1:$a = 8, 求 ++a + a++ - --a + a-- + ++a ...
- Python中os和shutil模块实用方法集锦
Python中os和shutil模块实用方法集锦 类型:转载 时间:2014-05-13 这篇文章主要介绍了Python中os和shutil模块实用方法集锦,需要的朋友可以参考下 复制代码代码如下: ...