MySQL事务与锁机制

MySQL的事务特性都知道ACDI么,原子性,一致性,隔离性,持久性,那么今天来聊一下如何保证事务特性。

1.事务并发的三大问题?

1.1 脏读

什么是脏读?举个例子

上图展示了事务A执行了查询操作,查询了id为1的数据,此时事务B执行了update的语句,但没有提交事务,此时事务A再次查询发现结果和之前查询的数据不一样,而事务B的update语句此时不一定成功也有可能会被回滚,所以没有真正写入磁盘里,这种就是读取了脏数据也叫脏读。

1.2 不可重复读

什么又是不可重复读呢?举个例子

事务A里执行了查询id为1的数据,此时事务B执行了update语句并提交了事务,那么实例A再次进行查询的时候就会查询到修改之后的数据,因为update的事务已经提交,所以说这个叫不可重复读。不可重复读针对修改和删除,因为已经进行修改或删除所以叫不可重复读。

1.3 幻读

事务A执行了年龄范围查询,查询到了一条数据,此时事务B插入了一条数据并提交事务,事务A此时再查询发现多出了一个id为2的数据,那么这种行为就是幻读,那么在这里对比一下,不可重复读也是事务提交,幻读也是事务提交那么它两有啥区别?不可重复读是修改数据的时候才叫不可重复读,当insert新增语句导致前后数据不一样出现的这个问题就是幻读。幻读针对insert语句。

总结:事务并发的三大问题都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。

2.事务的隔离性

2.1 Read uncommitted(读未提交)

对应上面讲过的脏读问题,select进行查询可以查询没有提交事务的数据,所以一定能产生脏读,不可重复读和幻读问题。

2.2  Read committed(读已提交)

其他事务增删改操作已提交事务,我这个事务再查询,发现数据变了,因为事务是提交过的,不存在失败回滚操作,所以能够解决脏读,但是解决不了不可重复读和幻读。

2.3 Repeatable read(重复读)

在读取事务开启时,不允许修改操作。那自然而然就解决不可重复读的问题,也能解决脏读问题,但是解决不了幻读操作。

2.4 Serializable(序列化)

事务串行化顺序执行(加了锁,只能一个一个等待锁释放)可以避免脏读、不可重复读、幻读,但是这种事务级别效率低下,比较耗数据库性能,一般不使用。

oracle只支持已提交读和串行化,mysql中都支持,注意可重复读innoDB中可以解决幻读问题,而不需要用串行化来解决数据一致性。

这里提一句:一个事务持有的锁什么时候会释放呢?

其实要么提交(commit),要么回滚(rollback),还有一种打开一个客户端然后开启事务,执行update语句以后关掉那个窗口,那么因为线程已经不运行了,所以这时锁也被释放掉了

3.事务的隔离解决方案

第一种:在读取数据前对其加锁,阻止其他事务对数据进行修改--Lock Based Concurrency Comtrol (LBCC)

第二种:生成一个数据请求时间点的一致性数据快照(snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取--Mulit Version Concurrencu Control(MVCC)。

先讲下第一种,之后我了解第二种方式会进行补充。

3.1 表锁与行锁

表锁:顾名思义就是表级别上的锁

行锁:就是行级锁

区别是什么?

在锁定粒度上:表锁粒度大于行锁

在加锁效率上:表锁效率大于行锁

在冲突概率上:表锁冲突一定大于行锁

在并发性能上:表锁并发性小于行锁

来个小问题把:MyISAM和InnoDB分别支持什么粒度的锁?

答:MyISAM支持表级别的锁,InnoDB既能支持行级锁也能支持表级锁。

4. InnoDB锁的类型

锁的模式:

4.1 共享锁(Shared Locks)

共享锁(行锁)(S锁):又称为读锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不恩能够修改;

加锁方式如:select * from student where id=1 LOCK IN SHARE MODE;  

释放锁:commit/rollback;

4.2 排它锁(Exclusive Locks)

排它锁(行锁)(X锁):又称为写锁,排它锁不能与其他锁共存,如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的锁(共享锁、排它锁)。

加锁方式:

自动:delete/updete/insert 默认加上X锁

手动:select * from where id=1 FOR UPDATE

4.3 意向共享锁(表锁):(Intention Shared Locks)

意向锁是由数据引擎自己维护的,用户无法手动操作意向锁

意向共享锁(IS锁):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁。

4.4 意向排它锁(表锁):(Intention  Exclusive Locks)

意向排它锁(IX锁):表示事务准备给数据行加入排它锁,说明事务再一个数据行加排它锁之前必须先取得该表的IX锁。

思考:为什么需要(表级别)的意向锁?

一个事务要成功锁住一张表的前提是没有其他任何事务已经锁定了其中的任意一行,那么我怎么知道事务是否锁定了么,需要一个一个扫描么,那么数据量大怎么办?如果一个事务加上了共享锁,那么这个表或行数据一定有一个意向共享锁,如果一个事务加上了排他锁,这个表一定有意向排他锁,所以这个意向锁就是用来标识是否加锁,之后进行判断的

锁的作用:解决资源竞争的问题。

思考:锁到底锁住了什么?是一行数据还是一个字段呢?

5.MySQL的锁到底锁住了什么?

mysql锁住的其实是索引

三种情况

第一种不加索引的情况:MySQL没有主键索引会采用默认的rowid来充当主键,连主键索引都没有使用的话就会整个的扫描,然后扫描的过程就把rowid全部加上锁。

第二种是加主键索引的情况:那么就会锁住主键索引那一行的数据。

第三种情况既有主键索引又有辅助索引的话:既有主键索引又有辅助索引,最后还是会锁定主键索引所在的那一行数据。为什么?

看下图,假如你有name这个普通索引,它还是会根据name这个普通索引找到id为7的数据,再回到主键索引里去找那么锁的还是这个主键索引的行

锁说完了,说一下锁的算法把

6.InnoDB锁的算法

Record(记录):主键值存在的就叫Record,如id=1,id=4,id=7

记录锁(Record Lock):锁定记录,使用条件:唯一性索引(唯一/主键)等值查询,精准匹配

间隙(Gap):基于Record划分的的数据不存在的区间就叫间隙。那么有n个Record会有多少个间隙?n+1个

间隙锁(Gap Lock):锁定的是一个范围,使用条件:记录不存在

它会锁住你要查询的不存在的区间范围,Gap锁会阻塞插入,不会排斥查询

临键(Next-Key):数据不存在的区间加上右边的Record组合起来就是左开右闭的区间。’(’或’)’是开区间,表示不包括此数值,比如(0,6)就是只是0-6之间的数,不包含0和6。’[’或’]’是闭区间表示包括此数值。如(0,6)包含0和6的数字。

临键锁:锁定范围加记录,InnoDB默认使用的锁。使用条件:范围查询,包含记录和区间。

所以InnoDB中可重复读解决了幻读的问题就是通过间隙锁,也可以说是临键锁,因为临键锁包含了间隙锁。

以上就是根据青山老师视频学习整理的学习笔记。希望可以帮助你

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值