mysql如何实现可重复读的?数据库并发事务带来的问题

并发事务带来的问题

并发事务会带来哪些问题?

  • 脏读: 一个事务读取另外一个事务尚未提交的数据。因为未提交,所以可能随时撤回或者修改,导致了根据这个数据进行的一些操作可能是不正确的。这种情况被称为脏读。

  • 幻读: 在同一个事务里多次查询结果集不一致,多了或者少了等。比如第一次查询得到一个list,另外一个事务在进行新增或者删除,导致,进行第二次查询时得到的list比第一次多或者少等,这种情况被称为幻读。

  • 不可重复读: 在同一个事务中,同一条记录,多次查询结果不一致。比如一条记录第一次查询时某个值,但同时另一个事务在修改这条记录,导致进行第二次查询这条记录时与上一次的值不一致。

  • 丢失修改: 一个事务中读取了某个记录,并修改了记录,但是尚未提交,另外一个事务此时也读取到了同样的记录,同样的值,做了另外的修改,前一个事务先提交后一个事务再提交,但是前一个事务修改的值被后一个事务覆盖了,导致它做的修改丢失。比如,事务1读取count=20,让它减2,但是还没有把结果提交,这个时候另一个事务2也读取了count=20,让他减1,当事务1和2先后提交后,count=19,导致事务1做的修改并没有生效。

事务隔离级别

为了解决多个事务并发会引发的问题。数据库系统提供了四种事务隔离级别供用户选择。

  • 读未提交(Read uncommitted) :允许脏读,也就是可能读取到其他会话中未提交事务修改的数据(基本不会设置这种隔离级别)
  • 读已提交(Read committed) :只能读取到已经提交的数据。Oracle,postgresql等多数数据库默认都是该级别
  • 可重复读(Repeatable read) :可重复读,在同一个事务内的查询都是事务开始时刻一致的,不管查询多少次都是同一条记录。(mysql默认隔离级别)
  • 串行读(Serializable) :完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞。
隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
读未提交(Read uncommitted)可能可能可能
读已提交(Read committed)不可能可能可能
可重复读(Repeatable read)不可能不可能可能
可串行化(Serializable )不可能不可能不可能

mysql如何实现可重复读的?

事务的隔离级别中,可重复读(Repeatable read,简称RR)它是如何实现的呢?

多版本并发控制(MVCC) 是通过保存数据在某个时间点的快照来实现并发控制的。也就是说,不管事务执行多长时间,事务内部看到的数据是不受其它事务影响的,根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。

以MySQL 中 InnoDB引擎为例,它会在每行数据后添加两个额外的隐藏的值来实现MVCC(在有主键的情况下实际添加的隐藏列有3个,但是与MVCC有关的只有2个),这两个值一个记录这行数据被创建时的事务版本号(DB_TRX_ID),另外一个记录这行数据被删除的版本号(DB_ROLL_PT,也有称为回滚指针)。

每一个事务都有一个版本号,每创建一次事务,事务的版本号就会递增,在可重读Repeatable reads事务隔离级别下:

  • SELECT时,读取数据中创建时的事务版本号<=当前事务版本号,删除版本号为空或>当前事务版本号
  • INSERT时,保存当前事务版本号为行的创建版本号
  • DELETE时,保存当前事务版本号为行的删除版本号
  • UPDATE时,插入一条新纪录,保存当前事务版本号为行的创建版本号,同时将当前事务的版本号保存到原来行的删除版本号中

多版本并发控制 的思想就是保存数据的历史版本,通过对数据行的多个版本管理来实现数据库的并发控制。这样我们就可以通过比较版本号决定数据是否显示出来,读取数据的时候不需要加锁也可以保证事务的隔离效果。 所以对不可重复读 的问题,在RR级别下,假设某条记录第一次读时为100,这个时候有另外的事务修改了它为80(实际上是插入了一条新记录,保存新的创建版本号),然而针对当前事务,它的创建版本号是不变的,所以再次查询的时候它的值是不变的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云哲-吉吉2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值