mysql事务隔离级别介绍和个人看法

事务隔离级别

1.read uncommitted(读未提交)

  在Read Uncommitted级别,事务中的修改,即使没有提交,对其他的事务也是可见的.
事务可以读取未提交的数据,这也被称为脏读(Dirty Read). 这个级别会导致很多的问题,从性能上来说,read uncommitted不会比其他的级别好很多,但缺乏其他级别的好处,除非真的非常必要的理由,在实际应用中一般很少使用.

2.read committed (读已提交)

  大多数数据库的默认隔离级别都是read committed(但MySQL不是). read committed满足前面提到的隔离性的简单定义:一个事务开始时,只能"看见"已经提交的事务所作的修改.换句话,一个事务从开始到提交之前,所作的任何修改对其他事务都是不可见的.这个级别有时候也叫做不可重复读(nonrepeatable read),因为2次执行同样的查询,可能得到不同的结果.

读已提交的不可重复读再现和疑问
时间事务A事务B
设置隔离级别set session transaction isolation level repeatable read;set session transaction isolation level repeatable read;
T1开始事务(start transaction;)
T2开始事务(start transaction;)
T3查询账户余额100元
T4查询账户余额100元
T5取出10元,将余额改为90元
T6提交事务
T7查询账户余额90元(和T4读取的不一致)
如果需要手动实现一遍的话,可以参考这篇博客

突然在想"读到 90 不是挺好的么,实际就是 90 了啊…"
然后我百度了一下, 在v2ex里有个老哥发了一类似问题的帖子,觉得里边有几个人的回答可以解决我的疑问.
比如在执行, 所以还是需要考虑解决不可重复读的问题.

   BEGIN TRANSACTION
   UPDATE 表 1 SELECT FROM ....
   // 不可重复读
   UPDATE 表 2 SELECT FROM ...
   COMMIT
   
   表 1 和 表 2 不一致了

3.repeatable read (可重复读)

  repeatable read解决了脏读的问题.该级别保证了在同一个事务***多次***读取同样的记录的结果是一致的. 但是理论上,可重复读隔离级别还是无法解决里另一个幻读(Phantom read)的问题,
所谓幻读,指的是在当前事务在读取某个范围内的记录时,另一个事务又在该范围内查询一条新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom row)InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency control)解决了幻读的问题

可重复读 如果按照上面的表格再执行一遍会怎样?
时间事务A事务B
设置隔离级别set session transaction isolation level repeatable read;set session transaction isolation level repeatable read;
T1开始事务(start transaction;)
T2开始事务(start transaction;)
T3查询账户余额100元
T4查询账户余额100元
T5取出10元,将余额改为90元
T6提交事务
T7查询账户余额还是100元
T8如果此时事务A执行修改操作却能正确修改数据库,比如update X表 set money=money-10 where id=X;此时的余额会变成80元,好神奇哦

卧槽,居然还是100元,虽然解决了多次读取到的数据不一致的问题, 但是你这读取到的是旧的值啊. 如果用来

   BEGIN TRANSACTION
   UPDATE 表 1 SELECT FROM ....
   // 不可重复读
   UPDATE 表 2 SELECT FROM ...
   COMMIT
   
   表 1 和 表 2 不一致了

岂不是翻车了??? 所以有时候感觉如果不是 同 一 个 事 务 \color{red}{同一个事务} 多次读取的话,用read committed隔离级别就够了,反正这个级别也能实现行级锁,Oracle就是默认read committed隔离级别

4.serializable (可串行化)

  serializable是最高的隔离级别.它通过强制事务串行化执行,避免了前面说的幻读的问题,简单来说,serializable会在读取的每一行数据上都加锁,所以可能导致大的超时和锁的争用的问题.实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别.

隔离级别脏读可能性不可重复读可能性幻读可能性加锁读
read uncommittedyesyesyesno
read committednoyesyesno
repeatable readnonoyesno
serializablenononoyes

从<<高性能MySQL>>抄写的补充知识点

隐式和显式锁定

InnoDB采用的是两阶段锁定协议(two-phase locking protocol). 在事务执行过程中,随时都可以执行锁定,锁只有在commit和rollback的时候才会释放,并且所有的锁是同一时刻被释放.前面描述的锁定是隐式锁定,InnoDB会根据隔离级别在需要的时候进行加锁.
另外,InnoDB也支持通过特定的语句进行显式锁定,这些语句是不属于sql规范的

  • select …lock in share mode
  • select …for update

mysqlye 也支持lock tables和unlock tables语句,这些是在服务器层实现的,和存储引擎无关.他们有自己的用途,但并不能替代事务处理.如果应用需要用到的事务,还是应该选择事务性存储引擎.

经常可以发现,应用已经将表从Myisam转换到InnoDB,但还是显式地使用lock tables语句.但不但没有必要,还会影响性能,实际上InnoDB的行级锁工作得更好.

多版本并发控制(上班时间写的博客来不及手打了 粘贴个图,后期再手打)

在这里插入图片描述

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值