外贸网站源码带支付,网络营销案例分析,wordpress 调用链接,高新公司网站建设电话1.为什么需要MVCC在并发场景下#xff0c;读写操作会面临严重的冲突问题#xff1a;1.读操作如果遇到写操作#xff0c;要么“读到未提交的脏数据”#xff0c;要么“被写操作阻塞#xff08;等待锁释放#xff09;”#xff1b;2.写操作如果遇到读操作#xff0c;要么…1.为什么需要MVCC在并发场景下读写操作会面临严重的冲突问题1.读操作如果遇到写操作要么“读到未提交的脏数据”要么“被写操作阻塞等待锁释放”2.写操作如果遇到读操作要么“覆盖读操作需要的数据”要么“被读操作阻塞”MVCC通过“多版本”解决了这个问题写操作会生成新的数据版本读操作读取旧的版本不影响写两者不干扰。2.什么是MVCCMySQL的MVCCMulti-Version Concurrency Control多版本并发控制是InnoDB存储引擎实现高并发读写的核心操作。核心思想为数据库中的每条记录维护多个版本通过“版本链”和“可间性判断规则”让不同实物在并发访问时能够看到符合自己隔离级别的数据版本从而避免读写冲突读不阻塞写写不阻塞读同事保证事务隔离性。3.MVCC的核心组成MVCC的实现依赖三个关键组件隐藏列版本标识Undo Log版本存储Read View可见性判断。3.1 隐藏列记录的“版本身份证”InnoDB为表中的每条记录添加了三个隐藏字段用于记录标识的版本信息DB_TRX_ID记录最后一次修改该记录的事务ID6字节。每次事务对记录执行insert/update/delete时都会将自己的事务ID写入该字段。DB_ROLL_PTR回滚指针7字节。指向该记录的“上个版本”在Undo Log中的位置通过它可以串联所有的历史版本形成“版本链”。DB_ROW_ID记录的唯一标识6字节。如果表没有定义主键或唯一索引InnoDB会用它作为默认聚簇索引一般用不到可忽略。3.2 Undo Log版本的“历史记录馆”Undo Log回滚日志是InnoDB用于存储“记录旧版本”的空间。当视为修改记录时旧版本的数据不会被直接删除而是被写入Undo Log供后序“回滚”或“其他事务读取”使用。与隐藏列相结合形成“版本链”记录的“版本链”形成的过程如下初始插入一条数据时DB_TRX_ID是插入事务的IDDB_ROLL_PTR为null无历史版本新数据无历史版本。当事务A事务ID110修改该记录时InnoDB会先将旧版本数据写入Undo Log然后更新记录的DB_TRX_ID110并将DB_ROLL_PTR指向Undo Log中的旧版本。之后事务B事务ID220再次修改该记录时会将“事务A修改后的版本”写入Undo Log更新DB_TRX_ID220DB_ROLL_PTR指向事务A版本再Undo Log的位置。最终通过DB_ROLL_PTR串联的Undo Log记录形成了改记录的“版本链”最新版本在表中历史版本在Undo Log中。
一条记录的版本链结构简化
当前记录表中datanameHajiHang,age21|DB_TRX_ID220|DB_ROLL_PTR——Undo Log中的版本1Undo LogUndo Log中的版本1事务A修改后的版本datanameHajiHang,age20|DB_TRX_ID110|DB_ROLL_PTR——Undo Log中的版本0Undo Log中的版本0初始插入版本datanameHajiHang,age19|DB_TRX_ID55|DB_ROLL_PTR——null
3.3 Read View版本的“可见性过滤器”有了版本链后事务如何判断“哪个版本的数据对自己可见”这就需要Read View读试图它是一个“可见性判断规则集合”用于确定当前事务能够看到版本链中的那个版本。Read View包含4个核心变量生成时确定m_ids生成Read View时当前所有“活跃事务”已启动但未提交的事务ID集合无序min_trx_idm_ids中的最小事务ID当前活跃事务中最早启动的那个max_trx_id生成Read View时“下一个将要分配的事务ID”并非m_ids中的最大值而是一个预分配的自增IDcreator_trx_id当前生成Read View的事务自己的ID4.可见性判断规则核心设记录的版本对应的事务ID为trx_id根据trx_id和Read View的变量对比如果trx_id creator_trx_id该版本是当前事务自己修改的可见自己改的自己当然可以看到如果trx_id min_trx_id该版本对应的事务在“当前Read View生成前”就已提交因为它的ID比所有活跃事务的最小ID还小可见。如果trx_id max_trx_id该版本对应的事务在“当前Read View生成后”才启动ID超过预分配的最大ID不可见还没提交或刚启动。如果min_trx_id trx_id max_trx_id若trx_id在m_ids活跃事务集合中说明该事务在Read View生成时还没提交不可见若trx_id不在m_ids中说明该事务在Read View生成前已提交可见5.MVCC与隔离级别的关系MVCC的核心作用是实现隔离级别ACID中的“I”隔离性。InnoDB通过“Read View的生成时机”和“版本链”在不同隔离级别下表现出不同的行为隔离级别MVCC行为Read View生成时机解决的问题Read Uncommitted读未提交不使用MVCC直接读取最新的版本可能读到未提交的脏数据脏读Read Committed读已提交每次执行select时重新生成Read View避免脏读只看到已提交的版本但是可能出现“不可重复读”两次查询Read View不同Repeatable Read可重复读仅在事务第一次select生成Read View之后复用避免不可重复读两次查询用同一个Read View版本一致但可能出现“幻读”通过间隙锁解决Serializable串行化不依赖MVCC直接通过加锁读加共享锁写加排它锁实现完全串行化无并发问题性能低6.补充不同隔离级别涉及到的并发问题不同隔离级别会产生不同的并发问题核心问题包括脏读不可重复读幻读。脏读指的是一个事务读取到另一个为提交事务修改的数据。事务A在修改name并未提交事务B读取到了name后事务A又进行修改并提交/或直接回滚导入事务B读取到了一个临时无效的数据不可重复读指的是同一事务内多次读取同一数据结果因其他已提交事务的修改而不同。事务A第一次读取nameHajiHang事务B执行了修改操作将name改成了Hajimi事务A再次读取name发现不是HajiHang了幻读指的是同一事务内多次执行相同的查询操作通常是范围查询时结果集行数因其他一提交事务的插入/删除而变化事务A查询score90的人发现有5条数据之后事务B插入一个90的数据事务A再次查询score90发现结果集变为6条