MySQL的锁

锁的类型

共享锁和排他锁
共享锁和排他锁是InnoDB中的行级锁
共享锁是为了当前事务读数据
排他锁是为了当前事务去修改某一行数据(update,insert,delete)
共享锁设置:select row from tablename where id=xxx LOCK IN SHARE MODE
排他锁设置:select row from tablename where id=xxx FOR UPDATE
意向锁
为什么要意向锁?
意向锁是为了能够使行级锁和表级锁能够共存
意向锁是表级锁,用来说明事务稍后会对表中的数据行加哪种类型的锁(共享锁,排他锁
能够提升效率,因为比如有一个表加了一个行级锁,比如排他锁,如果另外一个事务要读取或者修改表中的某些数据,则不需要一行一行的判断到底是哪一行加了锁,直接判断这个表有没有意向锁,有就阻塞
记录锁
记录锁是一个在索引记录之间的锁
一个间隙可能跨越单个索引值,多个索引值,或者甚至为空
对于使用唯一索引来搜索唯一行的语句,只加记录锁不加间隙锁(不包括组合唯一索引),更多可以看这个:链接
临键锁
插入意向锁
自增锁事务插入到有自增列的表中而获得的一种特殊的表级锁,如果一个事务正在向表中插入数据,那么任何其他事务必须等待,从而保证第一个事务插入的行是连续的自增值

锁的实现

innodb中行级锁是通过给索引加锁来实现的,没有索引的话,引擎会通过隐藏的聚簇索引来对记录进行加锁(表级锁)
为了效率,MySQL进行了优化,对于不满足条件的记录,会进行放锁,最终持有的是满足条件的记录上的锁,但是不满足条件的记录上面依旧会有加锁,放锁的动作,没有索引时,不满足条件的记录行会有加锁,解锁的耗时过程
主键索引:引擎会锁定对应主键的索引
非主键索引:会先锁定非主键索引,在锁定对应的主键索引

锁在事务隔离级别的应用

  1. 读未提交:select不加任何锁,会产生脏读,并发性最高
  2. 读提交:普通的select语句时快照读,除了在外键约束检查和重复键检查时会封锁区间,其他情况都只使用记录锁
  3. 可重复读:用MVCC来实现也行,普通的select语句是快照读,在唯一索引上面使用唯一的查询条件,使用记录锁;在唯一索引上使用范围查询条件,则使用间隙锁和临键锁
  4. 串行化:所有的select语句都会被隐式加锁,共享锁

快照读,当前读

理解这两个概念能够更好的理解MVCC并发控制
在MVCC中,读操作分成两种,快照读和当前读
快照读,读取的是记录的可见版本或者历史版本,不用加锁
当前读,读取的是记录的最新版本,当前读返回的记录,都会加上锁,从而保证其他事务不会在并发修改这条记录
MVCC只能在提交读和可重复读两个隔离级别下面工作
关于MVCC的具体内容可以看我写的同栏目的内容

快照读

正常的select语句就是快照读
快照读使得在可重复读隔离级别下一个普通的select语句也能做到可重复读

当前读

insert,update,delete以及显式的加锁的select语句是当前读
insert,update,delete执行的时候都会执行一个读取当前数据最新版本的过程

死锁

死锁的情况:有两个事务同时操作两个表,加锁的顺序不一致而产生的,比如事务A锁住a表,事务B锁住b表,当事务A要去锁b表 的时候发现被事务B锁住了,于是等待且不释放a表,当事务B要去锁a表的时候发现a表被事务A锁住了,于是产生了死锁
innodb中有专门发现检测死锁的机制,解决办法就是rollback到较小的事务,也就是数据量较小的
在可重复读隔离级别下,如果两个线程同时对相同条件用select。。。for update加排他锁,在没有符合条件的记录情况下,两个线程都会加锁成功,程序发现记录不存在,就试图插入一条新数据,两个线程都这么做,就会出现死锁,如果将隔离级别改成提交读,就可以避免问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值