如何建网站快捷方式,做相册的网站,浙江华纳建设有限公司网站,网络宣传平台前言#xff1a;
在当今互联网时代#xff0c;数据库扮演着数据存储和管理的关键角色。对于大型Web应用程序和企业级系统而言#xff0c;高效地处理并发访问和事务管理是至关重要的。多版本并发控制#xff08;MVCC#xff09;是一种数据库事务处理的技术#xff0c;旨…前言
在当今互联网时代数据库扮演着数据存储和管理的关键角色。对于大型Web应用程序和企业级系统而言高效地处理并发访问和事务管理是至关重要的。多版本并发控制MVCC是一种数据库事务处理的技术旨在提高并发性和数据一致性而MySQL是其中一个广泛采用MVCC的数据库管理系统。
在本文中我们将深入探讨MVCC的概念、原理和实现方式特别关注MySQL中MVCC的实现。我们将探讨MVCC是如何克服传统数据库锁定机制的局限性从而实现更高的并发性和更好的数据一致性。通过深入了解MVCC读者将能够更好地理解MySQL的工作原理并能够优化数据库设计和性能调优。
目录
前言
当前读
快照读
MVCC:
实现原理
RC隔离级别下
RR隔离级别下
总结 本片的数据库表的属性如果没有特殊说明那默认就是innoDBRR 在介绍MVCC之前我们要先介绍两个概念
当前读
读取的是当前记录的最新版本读取的时候还需要保证其他并发事务不能修改当前记录会对当前记录加锁。对于我们日常的select......lock in share modeselect......for updateupdateinsertdelete都是一种当前读。
快照读
读取的是数据的可见版本有可能是历史数据不加锁是非阻塞读。常见隔离级别下的select:
RC:每一次select都生成一个快照读。RR:开启一个事务之后只有第一个select语句才会生成一张快照此后读的都是快照中的数据直到事务提交。Serializable:快照读退化为当前读。
我们用一个例子来看一下以下为我们模拟的表数据数据库默认使用InnoDB隔离级别为RR: 我们同时开启两个MySQL客户端来对这张表进行操作 先尝试读取数据这种能读取到表中最新数据的模式就叫做当前读。现在我们来看看什么是快照读
1.创建两个MySQL客户端都开启事务并且在第一个MySQL客户端中做一次SQL查询。 2.在第二个MySQL客户端中对id为1的用户姓名进行修改并且提交当前事务。 3.重新在第一个MySQL客户端中查询。 我们会发现第一个MySQL客户端中读取的数据竟然是老数据。这是为什么呢
原因很简单之前我们讲过MySQL的innoDB引擎在RR的隔离级别下当我们开启事务的时候只有第一次Select是当前读读取完之后会生成一张快照此后这个事务中后续的所有相同的select语句读的都是第一次Select所生成的快照。
当我们提交第一个MySQL客户端的时候之后再尝试select * from emp 会发生什么呢 我们可以发现此时就可以读取到正常的数据了。也就是说在InnoDB中select....... in share mode语句就是当前读。 MVCC: MVCCMulti-Version Concurrency Control多版本并发控制是一种用于数据库管理系统中实现并发控制的技术。它允许多个事务同时对数据库进行读写操作而不会导致数据不一致或丢失。
MVCC 的核心思想是在数据库中维护多个数据版本并根据事务的隔离级别来决定哪个版本对特定事务是可见的。快照读就为MVCC提供了一个非阻塞读的功能MVCC的具体实现还需要依赖数据库中的三个隐式字段undo log 日志readView
实现原理
1.记录中的隐藏字段当我们尝试创建一张表之后InnoDB会自动为我们加上两个字段
DB_TRX_ID最近一次修改或删除记录的事务IDDB_ROLL_PTR回滚指针指向记录的上一个版本DB_ROW_ID隐藏主键如果表结构没有主键将会生成该隐藏字段
2.undo log 日志:
Undo 日志记录了对数据的修改操作包括插入、更新、删除等。Undo 日志中记录了修改前的数据值以及撤销操作所需的信息以便在事务回滚或 MVCC 中使用。当事务提交的时候相关的Undo log 日志就被标记为可回收状态可以在之后的操作中被回收 如果是insert语句那么Undo log日志只需要在回滚的时候需要当事务提交之后会被立即删除。 如果是update,delete的时候产生的undo log日志不仅在回滚的时候需要在产生快照读的时候也需要因此其不会被立即删除。undo log 中残留的旧版本数据可供其他并发事务进行快照读 3.undo log 版本链
本图来自黑马程序员偷懒了没画如有侵权请联系我立即删除 4.readview
readview是快照读SQL执行时候MVCC提取数据的依据记录并且维护当前事务活跃的事务(未提交)的id。
ReadView包含了四个核心字段
字段含义m_min_trx_id最小活跃事务IDmax_try_id预分配事务ID其实是当前最大事务ID1因为事务是自增的m_ids当前活跃的事务ID集合creator_trx_idReadView创建者的事务ID
那么基于readView其实就已经决定了哪些事务可以访问undo的哪些数据版本 InnoDB不同的隔离级别生成ReadView的实际不同
READ COMMITTED : 在事务每一次执行快照读的时候生成ReadView。REPEATABLE READ仅在事务中第一次执行快照读的时候生成ReadView后续一致复用该ReadView。
我们来口述以下在这两种不同的隔离级别下具体读取的是哪一个版本的快照
RC隔离级别下 其实就是去做比较将undo log 中的DB_TRX_ID套入比较规则中只要一个比较符合规则那么就可以进行读取该版本的数据。
经过一个一个的尝试我们可以发现DB_TRX_ID2的时候 符合比较规则2trx_idmin_trx_id。
因此我们事务5中第一次查询id为30的记录的时候实际上读的是DB_TRX_ID2的快照读。
其实这四个比较看起来比较唬人其实很好理解RC是读已提交也就是说我们的事务5在读取的时候要么读取在自己之前已经提交了事务的版本数据要么读取自己修改的数据。那我们返回表中看只有事务2在表5第一条语句之前提交了事务因此我们事务5可以读事务2的数据版本。 因此我们可以看到RC可以防止脏读因为它用的数据版本就是一个已经提交了事务的数据版本自然不可能读到其他事务还没有提交的数据。 RR隔离级别下 RR隔离级别下单个事务中一直复用的是该事务第一次查询版本快照。在当前案例中事务5一直复用的就是自己第一次查询id等于30的数据记录。 因此我们可以看到RR可以防止重复读这是因为事务一直使用的是自己第一次产生的readviewreadview一样那么匹配到的历史数据版本就一样如果我们一直读取的都是一个历史版本数据自然不可能出现两次读取结果不一致的情况了。 总结 MVCC 是数据库系统中一种重要的并发控制机制它通过在数据库中维护多个版本的数据来支持事务的并发执行并提供了一致性读取和隔离性的保证。在 MVCC 中每个事务都可以看到一个独立的数据版本这使得读操作不会被写操作所阻塞从而提高了数据库的并发性能。
MVCC 的实现主要依赖于两个关键组件Undo 日志和版本链。Undo 日志记录了事务执行过程中对数据所做的修改操作用于在事务回滚或撤销时恢复数据到之前的状态。而版本链则是指数据库中维护的多个数据版本之间的关系包括当前版本、已提交版本和未提交版本等。
如果我的内容对你有帮助请点赞评论收藏。创作不易大家的支持就是我坚持下去的动力