my40_MySQL锁概述之意向锁
本文在锁概述的基础上,通常实验举例,详细地介绍了意向锁的原理。
锁范围
全局锁(global lock)
表锁(table lock)
行锁 (row lock)
ROW LOCK的粒度
LOCK_REC_NOG_GAP, record lock with out gap lock
LOCK_GAP, gap lock
LOCK_ORDINARY , next key lock = record lock + gap lock
锁等待与死锁
锁等待 事务提交或等待超时;死锁,是一个死循环。死锁中必有锁等待。
表锁
5.5以后在server层实现表锁
innodb中有IS/IX表级锁,以及自增锁(auto-inc)
读锁
加读锁后,只能对表读,不能对表写;允许多个会话同时读;其他会话可以加共享读锁
lock table table_name read
写锁
lock table table_name write
持有锁的会话可写可读
其他会话访问表或请求加锁都会被阻塞,直到锁释放
强调:写锁会阻塞查询,连快照锁都会阻塞,绝对的排它锁。
释放锁
unlock tables;
lock table 锁不能相互嵌套,一个事务开始就意味着另外一个事务结束
显式开启一个事务,因为事务中不能支持表锁,所以事务开始则表锁断开
Kill或连接断开
innodb锁
默认为行锁
在索引上加锁来实现行锁
如果没有索引,那么升级为全表记录锁,最终效果等同于表锁;但表锁只需要在根节点上加锁,而不是对所有记录加锁,所以代价要小一些
锁类型
共享锁
排他锁/独占锁
意向锁,innodb特有,加在表级别上的锁
共享锁与独占锁均用于事务当中,随事务的结束而解除。
共享锁(share lock)
又称读锁,读取操作创建的锁。
一旦上锁,任何事务(包括当前事务)无法对其修改,其他事务可以并发读取数据,也可在对此数据再加共享锁
语法:SELECT ... LOCK IN SHARE MODE;
排他锁(exclusive lock)
又称写锁,如果事务对数据A加上排他锁后,则其他事务不可并发读取数据,也不能再对A加任何类型的锁。获得排他锁的事务既能读数据,又能修改数据。
语法:SELECT ... FOR UPDATE
这里的“其他事务不可并发读取数据”,指的是不可以加共享锁,即不可以以lock in share mode的方式读取数据,比如
会话一
- mysql> select * from test for update;
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 1 | 1 | 0 |
- | 2 | 3 | 1 |
- | 3 | 4 | 2 |
- | 5 | 5 | 3 |
- | 7 | 7 | 4 |
- | 10 | 9 | 5 |
- +----+------+------+
- 6 rows in set (0.00 sec)
会话二:
- mysql> select * from test lock in share mode;
- ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
直接查询完全可以
- mysql> select * from test;
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 1 | 1 | 0 |
- | 2 | 3 | 1 |
- | 3 | 4 | 2 |
- | 5 | 5 | 3 |
- | 7 | 7 | 4 |
- | 10 | 9 | 5 |
- +----+------+------+
- 6 rows in set (0.00 sec)
这是因为直接查询走的是一致性快照读,读的是MVCC版本控制下的快照,不加锁;换句话说,排他锁排斥的“读”,是指S锁下的读,或者说是当前读
意向锁
InnoDB的表级锁,其设计目的主要是为了在一个事务中揭示下一步将要被请求的锁的类型。
InnoDB中的两个表锁:
意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁
意向排他锁(IX):类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。
意向锁是InnoDB自动加的,不需要用户干预。
意向锁是表级锁
事务要获取表A某些行的S锁必须要获取表A的IS锁
事务要获取表A某些行的X锁必须要获取表A的IX锁
上表描述几种锁之间的的关系,其中AI是自增锁,表主健自增用到。
会话一锁定了全表
会话二,结果集为空时不加锁
意向锁的目的在于提高innodb性能,会话一锁定的是全表,那么会话二一看全表已被锁定,则不再去看每行是否锁定
会话二先判断表上有没有表锁,如果没有表级锁,则开始判断有没有行级锁
会话一:不锁定全表的S锁
会话二:立即执行,不被锁;v1上有索引
v1字段上有索引,v2字段上没有索引;有索引时,优先按有索引的规则来,当字段上没有索引时,S锁,X锁走意向锁的逻辑;
会话一
- mysql> begin;select * from test where v1 >4 lock in share mode;
- Query OK, 0 rows affected (0.00 sec)
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 5 | 5 | 3 |
- | 7 | 7 | 4 |
- | 10 | 9 | 5 |
- +----+------+------+
- 3 rows in set (0.00 sec)
- mysql> rollback;
- Query OK, 0 rows affected (0.00 sec)
- mysql> begin;select * from test where v2 >4 lock in share mode;
- Query OK, 0 rows affected (0.00 sec)
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 10 | 9 | 5 |
- +----+------+------+
- 1 row in set (0.00 sec)
会话二:
- mysql> begin;select * from test where v1 < 2 for update;
- Query OK, 0 rows affected (0.00 sec)
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 1 | 1 | 0 |
- +----+------+------+
- 1 row in set (0.00 sec)
- mysql> rollback;
- Query OK, 0 rows affected (0.00 sec)
- mysql>
- mysql>
- mysql> begin;select * from test where v2 < 2 for update;
- Query OK, 0 rows affected (0.00 sec)
- ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
- mysql>
如果不是S锁,而是快照读的话,不会走意向锁的逻辑,因为快照读不加锁(不管是RC还是RR隔离级别);
会话一
- mysql> begin;select * from test where v2 >4;
- Query OK, 0 rows affected (0.00 sec)
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 10 | 9 | 5 |
- +----+------+------+
- 1 row in set (0.00 sec)
会话二:立即执行,没有锁等待
- mysql> begin;select * from test where v2 < 2 for update;
- Query OK, 0 rows affected (0.00 sec)
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 1 | 1 | 0 |
- | 2 | 3 | 1 |
- +----+------+------+
- 2 rows in set (0.00 sec)
对于无索引的情况,更新任何一条记录,都会对该表加锁,这时意向锁将非常有用;但这个场景有个例外-->“半一致性读”
半一致性读的条件:
5.7及以下版本时,需要innodb_locks_unsafe_for_binlog 开启或事务隔离级别为RC,语言类型为update
8.0版本,语言类型为update,事务隔离级别为RC;innodb_locks_unsafe_for_binlog 参数被废弃。
8.0中半一致性读测试
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
会话一
- mysql> begin;select * from test where v2 >4 for update;
- Query OK, 0 rows affected (0.00 sec)
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 10 | 9 | 5 |
- +----+------+------+
- 1 row in set (8.77 sec)
会话二:显式开始一个事务被阻塞,直接使用update语句不被阻塞;注意v2字段上无索引
- mysql> begin;select * from test where v2 < 2 for update;
- Query OK, 0 rows affected (0.00 sec)
- ^C^C -- query aborted
- ERROR 1317 (70100): Query execution was interrupted
- mysql> select * from test;
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 1 | 1 | 0 |
- | 2 | 3 | 1 |
- | 3 | 4 | 2 |
- | 5 | 5 | 3 |
- | 7 | 7 | 4 |
- | 10 | 9 | 5 |
- +----+------+------+
- 6 rows in set (0.00 sec)
- mysql> update test set v2 = 1 where v2 < 2;
- Query OK, 1 row affected (0.00 sec)
- Rows matched: 2 Changed: 1 Warnings: 0
- mysql> exit
8.0的RR隔离级别
mysql> set global transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
会话一:X锁测试
- mysql> begin;select * from test where v2 >4 for update;
- Query OK, 0 rows affected (0.00 sec)
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 10 | 9 | 5 |
- +----+------+------+
- 1 row in set (0.00 sec)
会话二:
- mysql> update test set v2 = 1 where v2 < 2;
- ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
8.0中半一致读的条件:RC及以下隔离级别,update语句
对于RR隔离级别,无索引的情况下,S锁,X锁,走意向锁的逻辑
会话一:S锁测试
- mysql> begin;select * from test where v2 >4 lock in share mode;
- Query OK, 0 rows affected (0.00 sec)
- +----+------+------+
- | id | v1 | v2 |
- +----+------+------+
- | 10 | 9 | 5 |
- +----+------+------+
- 1 row in set (0.00 sec)
会话二:
- mysql> update test set v2 = 1 where v2 < 2;
- ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
所以意向锁的关键在于是否是S锁与X锁;如果是RC隔离级别,需要注意一下“半一致性读”
S锁会先有全表上加IS,X锁会先在全表上加IX;IS与IX互斥,IX与IX及IS互斥;
对于经常使用的RR隔离级别,对于无索引字段,意向锁减少了后来锁判断行记录上是否有锁的时间
my40_MySQL锁概述之意向锁的更多相关文章
- 01 MySQL锁概述
锁是计算机协调多个进程或线程并发访问某一资源的机制.在数据库中,除传统的计算资源(如CPU.RAM.I/O 等)的争用以外,数据也是一种供许多用户共享的资源.如何保证数据并发访问的一致性.有效性是所有 ...
- [Re:从零开始的分布式] 0.x——分布式锁概述
为什么需要分布式锁 Martin Kleppmann是英国剑桥大学的分布式系统的研究员,Martin认为一般我们使用分布式锁有两个场景: 效率:使用分布式锁可以避免不同节点重复相同的工作,这些工作会浪 ...
- 《Mysql 锁 - 概述》
一:锁类型(加锁范围区分类型) - MySQL里面的锁可以分为:全局锁.表级锁.行级锁. 二:全局锁 - 作用 - 对整个数据库实例加锁. - 加锁方式 - MySQL提供加全局读锁的方法:Flus ...
- (8)MySQL进阶篇SQL优化(InnoDB锁-共享锁、排他锁与意向锁)
1.锁的分类 锁(Locking)是数据库在并发访问时保证数据一致性和完整性的主要机制.之前MyISAM锁章节已经讲过锁分类,而InnoDB锁按照粒度分为锁定整个表的表级锁(table-level l ...
- (转)SQL SERVER的锁机制(一)——概述(锁的种类与范围)
锁定:通俗的讲就是加锁.锁定是 Microsoft SQL Server 数据库引擎用来同步多个用户同时对同一个数据块的访问的一种机制. 定义:当有事务操作时,数据库引擎会要求不同类型的锁定,如相关数 ...
- SQL SERVER的锁机制(一)——概述(锁的种类与范围)
锁定:通俗的讲就是加锁.锁定是 Microsoft SQL Server 数据库引擎用来同步多个用户同时对同一个数据块的访问的一种机制. 定义:当有事务操作时,数据库引擎会要求不同类型的锁定,如相关数 ...
- InnoDB的锁机制浅析(二)—探索InnoDB中的锁(Record锁/Gap锁/Next-key锁/插入意向锁)
Record锁/Gap锁/Next-key锁/插入意向锁 文章总共分为五个部分: InnoDB的锁机制浅析(一)-基本概念/兼容矩阵 InnoDB的锁机制浅析(二)-探索InnoDB中的锁(Recor ...
- sql锁的类型介绍:悲观锁,乐观锁,行锁,表锁,页锁,共享锁,排他锁,意向锁
1 悲观锁,乐观锁 悲观锁:顾名思义,很悲观,就是每次拿数据的时候都认为别的线程会修改数据,所以在每次拿的时候都会给数据上锁.上锁之后,当别的线程想要拿数据时,就会阻塞,直到给数据上锁的线程将事务提交 ...
- MySQL详解--锁
http://blog.csdn.net/xifeijian/article/details/20313977 2014-03-06 23:45 66484人阅读 评论(17) 收藏 举报 分类: ...
随机推荐
- 模块化开发 | es6模块暴露与引入
CommonJS模块开发 CommonJS定义 每个文件就一个模块,有自己的作用域.在一个文件里面定义的变量.函数.类,都是私有的,对其他文件不可见. 私有作用域不会污染全局作用域. 模块可加载多次, ...
- #web开发# 知道cookie hostonly属性的请举手。
Cookie常见姿势.疑难梳理 目前w3c定义浏览器存放每个cookie需要包含以下字段: cookie属性 基本描述 举例 备注 name=value cookie键值对 id=a3fWa expi ...
- SpringCloud升级之路2020.0.x版-31. FeignClient 实现断路器以及线程隔离限流的思路
本系列代码地址:https://github.com/JoJoTec/spring-cloud-parent 在前面一节,我们实现了 FeignClient 粘合 resilience4j 的 Ret ...
- mybatis中<![CDATA[]]>和转义字符
在使用mybatis 时我们sql是写在xml 映射文件中,如果写的sql中有一些特殊的字符的话,在解析xml文件的时候会被转义,但我们不希望他被转义,所以我们要使用<![CDATA[ ]]&g ...
- java更开源-安全可靠国产系统背景下的应有.NET Core的一席之地
"安可"背景下的中国软件开发 在中美当前背景下的安全可靠国产系统(简称安可),安可产业要实现技术自主可控,需要在四个层面逐步实现:基础硬件设施,如芯片.服务器.存储.交换机.路由器 ...
- Java 8 新特性 用 Collectors 对 List 去重
场景:有一个实体的List集合,需要根据实体中的某个字段对List去重 Collectors.collectingAndThen方法:将流中的数据通过Collector计算,计算的结果再通过Funct ...
- C#窗体学习
//进度条控件 private void button1_Click(object sender, EventArgs e) { int i; ...
- [gym102832J]Abstract Painting
考虑每一个圆即对应于区间$[x_{i}-r_{i},x_{i}+r_{i}]$,可以看作对于每一个区间,要求所有右端点严格比其小的区间不严格包含左端点 用$f_{i}$表示仅考虑右端点不超过$i$的区 ...
- [atARC102F]Revenge of BBuBBBlesort
定义以$i$为中心(交换$p_{i-1}$和$p_{i+1}$)的操作为操作$i$ 结论1:若执行过操作$i$,则之后任意时刻都无法执行操作$i-1$或操作$i+1$ 当执行操作$i$后,必然有$p_ ...
- [cf1392I]Kevin and Grid
令$v$为点数(有公共点的格子中存在红/蓝色).$e$为边数(有公共边的格子中存在红/蓝色).$f$为以此法(即仅考虑这些点和边)所分割出的区域数(包括外面).$s$为连通块个数,将欧拉定理简单扩展, ...