数据库MVCC如何解决可重复读问题?

 

今天我心情好,我决定给你的转账 100 万,最后的结果肯定是我的余额变为 0 元,你的余额多了 100 万元,是不是想到就很开心?

转账这一动作在程序里会涉及到一系列的操作,假设我向你转账 100 万的过程是有下面这几个步骤组成的:

                      

 

可以看到这个转账的过程涉及到了两次修改数据库的操作。

假设在执行第三步骤之后,服务器忽然掉电了,就会发生一个蛋疼的事情,我的账户扣了 100 万,但是钱并没有到你的账户上,也就是说这 100 万消失了!

要解决这个问题,就要保证转账业务里的所有数据库的操作是不可分割的,要么全部执行成功 ,要么全部失败,不允许出现中间状态的数据。

数据库中的「事务(Transaction」就能达到这样的效果。

我们在转账操作前先开启事务,等所有数据库操作执行完成后,才提交事务,对于已经提交的事务来说,该事务对数据库所做的修改将永久生效,如果中途发生发生中断或错误,那么该事务期间对数据库所做的修改将会被回滚到没执行该事务之前的状态。

没错,今天就来图解 MySQL 事务啦,开车!

作者:小林coding
链接:https://www.zhihu.com/question/333421386/answer/2630886782
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
 

事务有哪些特性?

事务是由 MySQL 的引擎来实现的,我们常见的 InnoDB 引擎它是支持事务的。

不过并不是所有的引擎都能支持事务,比如 MySQL 原生的 MyISAM 引擎就不支持事务,也正是这样,所以大多数 MySQL 的引擎都是用 InnoDB。

事务看起来感觉简单,但是要实现事务必须要遵守 4 个特性,分别如下:

  • 原子性(Atomicity):一个事务中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节,而且事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像这个事务从来没有执行过一样,就好比买一件商品,购买成功时,则给商家付了钱,商品到手;购买失败时,则商品在商家手中,消费者的钱也没花出去。
  • 一致性(Consistency):是指事务操作前和操作后,数据满足完整性约束,数据库保持一致性状态。比如,用户 A 和用户 B 在银行分别有 800 元和 600 元,总共 1400 元,用户 A 给用户 B 转账 200 元,分为两个步骤,从 A 的账户扣除 200 元和对 B 的账户增加 200 元。一致性就是要求上述步骤操作后,最后的结果是用户 A 还有 600 元,用户 B 有 800 元,总共 1400 元,而不会出现用户 A 扣除了 200 元,但用户 B 未增加的情况(该情况,用户 A 和 B 均为 600 元,总共 1200 元)。
  • 隔离性(Isolation):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致,因为多个事务同时使用相同的数据时,不会相互干扰,每个事务都有一个完整的数据空间,对其他并发事务是隔离的。也就是说,消费者购买商品这个事务,是不影响其他消费者购买的。
  • 持久性(Durability):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

InnoDB 引擎通过什么技术来保证事务的这四个特性的呢?

  • 持久性是通过 redo log (重做日志)来保证的;
  • 原子性是通过 undo log(回滚日志) 来保证的;
  • 隔离性是通过 MVCC(多版本并发控制) 或锁机制来保证的;
  • 一致性则是通过持久性+原子性+隔离性来保证;

这次将重点介绍事务的隔离性,这也是面试时最常问的知识的点。

为什么事务要有隔离性,我们就要知道​​​​​​​并发事务时会引发什么问题。

并行事务会引发什么问题?

MySQL 服务端是允许多个客户端连接的,这意味着 MySQL 会出现同时处理多个事务的情况。

那么在同时处理多个事务的时候,就可能出现脏读(dirty read)、不可重复读(non-repeatable read)、幻读(phantom read)的问题

接下来,通过举例子给大家说明,这些问题是如何发生的。

#脏读

如果一个事务「读到」了另一个「未提交事务修改过的数据」,就意味着发生了「脏读」现象。

举个栗子。

假设有 A 和 B 这两个事务同时在处理,事务 A 先开始从数据

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
MVCC(多版本并发控制)是一种用于解决并发读写冲突的机制。在MVCC中,数据库会为每个事务创建一个快照,该快照是事务开始时数据库中数据的一个副本。因此,在可重复读隔离级别下,MVCC通过使用快照读来解决可重复读问题。 在可重复读中,多个事务同时读取同一行数据时,MVCC会根据每个事务开始时的快照来提供一致性视图。这意味着,如果一个事务正在读取数据,并且另一个事务正在修改相同的数据,那么读取操作将返回事务开始时的数据快照,而不会受到其他事务的修改的影响。 具体来说,MVCC通过在每个数据行中保存多个版本的数据来实现可重复读。当一个事务开始时,它会创建一个读取快照,并且只能看到在该快照之前已经提交的数据版本。如果其他事务正在修改相同的数据行,那么这些修改将被保存在新的数据版本中,而不影响当前事务的读取操作。 因此,MVCC通过使用快照读和当前读的组合来实现可重复读。快照读提供了一致性的数据视图,而当前读则用于读取最新的数据,并在写操作之前读取数据。 总之,MVCC通过使用快照读和多个数据版本来解决可重复读问题,确保事务在读取数据时不会受到其他并发事务的修改的干扰。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [MySQL(五)—MVCC解决可重复读的幻读了吗?](https://blog.csdn.net/shang_0122/article/details/120298810)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [详解MySQL是如何解决幻读的](https://download.csdn.net/download/weixin_38730767/13699659)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

倾听铃的声

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

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

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

打赏作者

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

抵扣说明:

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

余额充值