mysql的隔离级别以及悲观锁和乐观锁

隔离级别

  1. Read-Uncommitted(读未提交):会产生脏读的问题.比如事务A增加了一条数据,此时事务B正好读到了这笔数据,但是在事务B读到数据之后,事务A发生了异常,数据回滚了,那么最终这条数据是没有写入数据库的.而事务B读到了数据库不存在的数据,这就称之为:脏读.
    ps:新手的困惑解答,我个人当时对于上面的描述觉得很困惑的一点就是:为什么事务B能读到事务A未提交的数据,未提交不是没写进数据库吗?其实是这样的,提交是指事务整体的提交,一个事务通常包括多步对数据库的操作,举个例子:有一张学生表,字段是学好,姓名,性别.假设表中有两条数据,一条是: 001 张三 男002 李红 女,事务A需要做两步操作,第一步是添加一条记录003 赵四 男,第二部是将001 张三 男修改为 001 张三 女 .在事务A完成第一步,但是没完成第二步的时候,事务B执行了,事务B是查询整个表中的数据,此时事务B就查到了三条数据 :001 张三 男,002 李红 女,003 赵四 男.但是紧接着事务A在执行第二步的时候,因为种种原因发生了异常,这时候就会发生数据的回滚,整体回到事务A执行之前的状态,也就是添加的数据003 赵四 男会消失.(事务的原子性,此处看不懂的小伙伴可以百度一下Mysql事务的ACID四个特性).

  2. Read-Commited(读已提交):会产生不可重复读的问题.依旧举个例子:有一张学生表,表中有两条数据,001 张三 男,002 李红 女.假设事务A开启事务,然后执行两条查询语句,都是查询整张表的数据.执行第一条查询语句的时候,查到了两条数据001 张三 男,002 李红 女.此时有个事务B也对表进行操作,将001 张三 男修改为了001 赵四 男,并提交了数据.然后事务A执行第二条查询语句,此时查到的数据则变成了001 赵四 男,002 李红 女,然后事务A提交事务,并将查询结果展示给用户,用户就会发现两次读到的数据不一致.这就叫做不可重复读.产生不可重复读的原因就是事务A读取数据的时候,事务B对这些数据进行了删除或修改.

  3. Repeatable-Read(可重复读):刚刚我们解释了不可重复读产生的原因是事务A读取数据的时候,事务B同时对事务A读取的这些数据进行了删除或修改。如果我们可以让事务A读取数据的时候,其他事务不能对这些数据进行删除或修改,那么是不是就可以实现可重复读了?的确如此,实现可重复读就需要上锁,将事务A读取的数据进行上锁,被上锁的数据其他事务不能进行删除或修改。这种上锁的方式有两种,一种是悲观锁,一种是乐观锁。
    悲观锁:悲观锁依靠数据库的机制来实现,语法是:select … from table for update.被选中的数据就会被事务A上锁,此时其他事务无法对这些数据进行上锁,也无法对这些数据进行删除或修改的操作,只有事务A结束之后,这其他事务才能对这些数据进行删除或修改,但是上锁期间其他事务对这些数据的查询是允许的。那么事务A从开启事务进行上锁,到提交事务解除锁的期间,只要是同样的sql语句,不论查询多少次,查询到的结果都是一样的,这就叫做可重复读
    乐观锁:悲观锁是依靠数据库本身的机制来实现的,而且上锁,解除锁是很耗费资源的行为,加重数据库的负担.由此产生了乐观锁的概念,乐观锁并不是通过对特定数据的上锁行为来达到可重复读的效果的,而是通过MVCC(版本控制)CAS来完成可重复读效果。
    比如mysql的InnoDB数据库引擎的MVCC就是通过在一条数据后面加上两个隐藏字段来实现目的。一个字段是创建时间(事务ID),一个字段是删除时间(事务ID)。mysql中每开启一个事务,都会给这个事务分配一个自增的ID,所以没个事务的ID不会重复,而且是可以比较大小的。假设事务A的ID是3,事务A查询表中的数据,那么事务A只能查到创建时间ID≤3,而且删除时间ID≥3的记录。即事务A只能查到在A之前创建,而且在A之后删除的记录。实际并发中常用版本控制是通过加一个version字段来进行版本控制,假设卖一件商品,这个会给商品加一个version字段,每次交易之前会获取商品此时的version,交易时会验证获取的version是否等于交易时的version,如果相等,则可以交易,并且交易完成后会将version自增或自减(此处我们假设是自增1)。假设多个线程同时获取一个version为10,那么只会有一个最快的线程能够验证通过并完成交易,在这个线程完成交易后version会+1,其他线程之前获得的version和现在的version就相差1,不相等了,sql语句就无法执行了。这样就保证了只有一个成功,不会在并发时发生超卖的问题。
    CAS(Compare And Swap)算法也是实现乐观锁的一种方式,CAS有三个值,V 代表 内存值(内存中已存储的数据,等待被修改),A代表旧的期望值(来自于V),B代表新的修改值。
    假设此时的V是内存中储存的一个数字56,事务A需要把56修改为60,那么基于CAS,事务A会先获取此时V的值,并保存到A中,此时A就是56B就是60,将56修改为60之前,事务A会验证AV是否相等,如果AV相等,才会进行修改。假设在事务A修改的同时,另一个事务B也对56进行了修改,要将56修改为100,事务B比A块,所以事务A进行验证的时候发现V的值为100,而事务A的A保存的值为56,此时A不等于V,验证不通过,无法进行修改,会进行回旋,不断再次尝试验证,直到验证通过才会停止。
    由于CAS只验证值的大小,所以会产生经典的ABA问题,以上面的例子举例,在事务A操作之前,事务B先将56改为100,然后再改回56,此时事务A再验证,是可以通过的,就像V没变过一样。这在一定的情况下会产生问题。

  4. Serializable(可串行化)
    这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值