内容简介:在mysql当中,关于innodb的锁类型总共可以分为四种,包含了行锁和表锁,分别是下面是各种锁之间的对应兼容情况(ps:在某一篇博客上看到,忘了是哪一篇,觉得好就截下来了嘻嘻):
在 mysql 当中,关于innodb的锁类型总共可以分为四种,包含了行锁和表锁,分别是
- 基本锁 - [ 共享锁(Shared Locks:S锁)和排它锁(Exclusive Locks:X锁)]
- 意向锁 - [ intention lock,分为意向共享锁(IS锁)和意向排他锁(IX锁)]
- 行锁 - [ record Locks、gap locks、next-key locks、Insert Intention Locks ]
- 自增锁 - [ auto-inc locks ]
下面是各种锁之间的对应兼容情况(ps:在某一篇博客上看到,忘了是哪一篇,觉得好就截下来了嘻嘻):
InnoDB三种行锁的算法:
- Record Lock:单个行记录上的锁,只锁定记录本身
- Gap Lock:间隙锁,锁定一个范围,但不包括记录本身。 目的是为了防止同一个事物的两次当前读,出现幻读的情况
- Next-Key Lock:1+2,锁定一个范围,并锁定记录本身。目的:解决幻读
共享锁
共享锁shared locks(S锁)也称读锁,允许其他事物再加S锁,不允许其他事物再加X锁
加锁方式:select...lock in share mode
注意:
- 对于使用共享锁的事务,其他事务只能读,不可写
- 如果执行了更新操作则会一直等待,直到当前事务commit或者rollback
- 如果当前事务也执行了其他事务处于等待的那条 sql 语句,当前事务将会执行成功,而其他事务会报死锁
- 并且允许其他事务加共享锁
排它锁
排它锁Exclusive Locks(X锁)也称写锁,不允许其他事务再加S锁或者X锁
加锁方式:select ... for update
→ for update:InnoDB默认是行级别的锁,当有明确指定的主键时,使用的是行锁;否则使用的是表锁。使用情况详细如下:
- 明确指定主键,并且由此记录,行级锁。例:select name,age from tb_user where id = '1' for update(id是主键)
- 明确指定主键/索引,若查无记录,无锁。例:select name,age from tb_user where id = '1' for update(id是主键,但不存在id = 1的数据)
- 无主键/索引,表级锁。例:select name,age from tb_user where age = 12 for update(age是普通字段)
- 主键/索引不明确,表级锁。例:select name,age from tb_user where age = 12,id = '1' for update(id是主键,age不是,但数据库有此数据)
注意:
- 对于排它锁的事务,其他事物可读,但不可进行更新操作
- for update仅使用与InnoDB,并且必须开启事务,在begin和commit之间才生效
- 当一个事务进行for update的时候,另一个事务也有for update时会一直等待,直到之前的事务commit或rollback或断开连接释放锁才拿到锁进行后面的操作(排它锁不能用于多个事务中)乐观锁
读取出数据,将此版本一同读出,之后更新,更新完并对版本加一。此时,将提交数据的版本与数据库对应表的记录的版本进行对比,如果提交的数据版本号大于数据库原有版本号,则予以更新,否则认为是过期数据。目的是为了用于解决并发问题。
例:A、B同时修改同一条数据,数据库原有金额是100元,A往数据库+100,B往数据库-50,正常结果是150,但由于并发,结果有可能是200,或者50
解决:A读取数据版本1,对金额+100,并修改数据版本为2,提交数据,此时数据版本为1,更新成功。B读取数据版本1,对金额-50,此时结果为50,并修改数据版本为2,提交数据,对比数据库原版本2,没有比原版本高,更新失败
间隙锁
间隙锁是在索引记录之间的间隙的锁定,或在最后一个索引记录之前或之后的间隙上的锁定
使用唯一索引搜索唯一一行的一句不需要间隙锁锁定(不包括搜索条件包含多列唯一索引的某些列的情况,查询出的多条记录,会发生间隙索引),详细例子如下:
- select id,name,age from tb_user where id = '1' (id是主键索引,由于搜索结果是唯一的一条记录,所以不会使用间隙锁)
- select id,name,age from tb_user where id = '1' and age = 13(id是主键索引、age是非索引字段,由于搜索结果可能不止一条记录,所以会使用间隙锁)
注意:
- 间隙锁只是阻止其他事物插入到间隙当中,并不阻止不同的事物在同一间隙上获得间隙锁。共享间隙锁具有与排他间隙锁相同的效果;
- 将隔离级别设置为read_commited或启用innodb_locks_unsafe_for_binlog系统变量(现已被弃用)可明确禁止使用间隙锁
MVCC(Snapshot read vs current read)
MVCC,基于多版本的并发控制协议,最典型的是读不加锁,读写不冲突,其包含两种读操作,即快照读(snapshot read)与当前读(current read)。
- 快照读:读取记录的可见版本,不加锁。
- 当前读:读取记录的最新版本,当前读返回的记录,都会加锁,保证其他事物不会再修改这条记录
那具体哪些操作为当前读,哪些操作又是快照读呢,让我们来看一下:
→ 快照读:简单的读操作,属于快照读,不加锁。(不过有些会有点小例外)
例:select * from tb_user where ?
→ 当前读:特殊的读操作,属于当前读,需要加锁。
-
select * from table where ? lock in share mode;
-
select * from table where ? for update;
-
insert into table values (…);
-
update table set ? where ?;
-
delete from table where ?;
所有以上的语句,都属于当前读,读取记录的最新版本。并且,读取之后,还需要保证其他并发事务不能修改当前记录,对读取记录加锁。其中,除了第一条语句,对读取记录加S锁 (共享锁)外,其他的操作,都加的是X锁 (排它锁)。
最后推荐一位大牛写的博客哈,里面写的很详细: hedengcheng.com/?p=771#_Toc…
以上所述就是小编给大家介绍的《MySQL锁系列之锁的种类和概念》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- MySQL锁系列(一)之锁的种类和概念
- 深度有趣 | 29 方言种类分类
- 非对称加密的原理及种类介绍
- 关于Python爬虫种类、法律、轮子的一二三
- jks pem cer pfx 不同种类的证书
- Flume的基本概念
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
阿里巴巴Java开发手册
杨冠宝 / 电子工业出版社 / 2018-1 / 35
《阿里巴巴Java开发手册》的愿景是码出高效,码出质量。它结合作者的开发经验和架构历程,提炼阿里巴巴集团技术团队的集体编程经验和软件设计智慧,浓缩成为立体的编程规范和最佳实践。众所周知,现代软件行业的高速发展对开发者的综合素质要求越来越高,因为不仅是编程相关的知识点,其他维度的知识点也会影响软件的最终交付质量,比如,数据库的表结构和索引设计缺陷可能带来软件的架构缺陷或性能风险;单元测试的失位导致集......一起来看看 《阿里巴巴Java开发手册》 这本书的介绍吧!