MySQL并发事务是怎么处理的?

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云数据库 Tair(兼容Redis),内存型 2GB
简介: 这篇内容探讨了数据库并发事务处理,特别是MySQL中的策略。文章指出并发编程常面临安全性和一致性的挑战,Java使用synchronized和Lock等机制,而MySQL通过事务隔离和MVCC(多版本并发控制)来解决。MVCC允许读事务无需等待写事务,通过保存数据的多个版本来避免冲突,提高并发性能。文章还分析了并发事务的三种情况,并解释了MVCC如何通过Read View选择可见数据版本。最后总结了事务隔离级别对并发处理的影响以及MVCC的关键作用。

前言

我们开发人员在进行并发编程时,总是会面临并发带来的安全性和一致性的挑战,为了解决这一问题,我们通常会采用同步机制和锁机制,例如Java中的synchronized关键字和Lock接口。

MySQL同样需要解决并发事务带来的复杂问题,上文简单介绍了MySQL通过事务隔离机制可以解决并发问题,本文将结合案例进行深入剖析,以便掌握其原理并学习其思想。

并发事务情况分析

如果读过之前的文章就会知道,每行数据的读写都是基于数据页操作的。那么在此基础上,并发事务可能存在以下几种情况:

  1. 并发事务读/读数据页中的某行数据。
  2. 并发事务读/写数据页中的某行数据。
  3. 并发事务写/写数据页中的某行数据。

如果没有并发控制的情况下,单纯的读操作是不会对数据造成什么影响。但是,一旦涉及到写操作,情况就会变得很复杂:如果此时有一个事务对某行数据进行写操作,其他事务能否对该行数据进行读取?

这个问题有以下几个情形:

  1. 如果可以,写事务进行回滚后,读事务的数据就不是最新状态了,一致性如何保证?
  2. 如果不可以,读事务是不是只能进行排队等待写事务的完成,性能如何保证?
  3. 如果不排队等待,又怎么保证读事务的数据是最新状态(一致性)?

各隔离级别如何处理并发事务?

到这里应该就看明白了。结合事务隔离级别:

不处理

第一个情形不就是“读未提交”的“脏读”,一致性保证不了一点

使用锁

第二个情形就是“串行化”,完全通过锁来处理并发事务。使用锁意味着需要竞争,而竞争失败就需要等待,等待就意味着消耗时间,消耗时间就意味着会影响整体并发处理能力。

对于MySQL这样的数据库,性能的高低会直接影响用户的去留,仅仅是“串行化”并发处理是远远不够的。

MVCC

所以,为了兼顾并发事务的一致性和性能问题(也就是第三个情形),就诞生MVCC,也是隔离级别“读已提交”和“可重复读”所运用到的技术。

什么是MVCC?

MVCC 全称 Multi-Version Concurrency Control(多版本并发控制),在数据库管理系统中通过保存数据的多个版本避免读写冲突,从而提高并发处理能力。

如何理解MVCC?

这里关注两个关键字:多版本读写冲突

结合上面的并发事务情况分析:

  1. 单纯的并发读操作不用做任何的并发处理。
  2. 并发写操作又避免不了锁机制。
  3. 并发读写如果不做控制可能会有“脏读”问题,如果使用“串行化”处理并发,又会影响整体性能。

所以只能在并发读写这里进行优化,所谓的避免读写冲突。

接下来就来看一下MVCC是如何在写事务处理的同时,保证读事务不需要排队等待就能获取到数据最新状态的。

MVCC的并发处理

数据的多版本

《MySQL是如何保证数据不丢失的》,每个DML操作在更新数据页之前,InnoDB会先将数据当前的状态记录在「Undo Log」中。

既然这样,那么读事务直接读取这里的数据不就好了?这样的话,写事务在处理过程中,读事务既不需要排队等待,又能读取到除当前写事务之外最新的数据状态,也避免了因写事务的回滚而造成的“脏读”问题。如下图。

在并发事务中如果有多个写事务,那么Undo Log是这样的:

图中的「事务ID」和「回滚指针」是行数据中包含的「隐藏字段」,在 Undo Log 中通过回滚指针进行串联的数据就是指MVCC的「多版本」。

(这里说明下,同时执行DML操作时还是会使用锁来控制的,不会减少对锁的竞争。所以图中有个先后顺序。)

选择数据的某个版本

那么读事务应该以哪个版本的数据为准?

针对这个问题,MVCC通过Read View机制来处理。

Read View是什么?

Read View是事务进行读操作时生成的一个读视图,记录当前活跃事务的ID,分别是:

  1. trx_list:Read View生成时刻正活跃的事务ID。
  2. up_limit_id:trx_list列表中事务ID最小的值。
  3. low_limit_id:已出现过的事务ID的最大值加1。

通过Read View可以判断在当前事务能看到哪个版本的数据。

判断逻辑是这样的:

  • 如果数据行记录的事务ID小于up_limit_id,表示该记录在当前事务开始之前就已经提交了,因此对当前事务是可见的。
  • 如果数据行记录的事务ID大于等于up_limit_id且小于low_limit_id,表示该记录正在被写事务操作,可以读取上个已提交的版本数据。
  • 如果数据行记录的事务ID大于等于low_limit_id,则该记录对当前事务不可见,因为它是在当前事务开始后产生的。

(这里说明下,事务ID是递增的。

案例说明

接下来,通过一张图具体看一下Read View怎么判断的。

图中有4个并发事务,并且在同一时刻开启了事务。

  1. 查询1是事务tx03在事务tx01已修改未提交时进行查询,事务tx02的update还未开始执行,所以当前数据的事务ID=tx01,活跃的事务ID为[tx01、tx02、tx03、tx04],按照Read View的逻辑:
  • tx01 不小于 up_limit_id(tx01),所以当前行记录age=19不可见。
  • tx01 大于等于 up_limit_id(tx01) 且小于 low_limit_id(tx05),可以读取上个已提交(XXX)的数据,也就是age=18。
  1. 查询2是事务tx03在事务tx01已提交,事务tx02已修改未提交时进行查询,所以当前数据的事务ID=tx02,活跃的事务ID为[tx02、tx03、tx04],按照Read View的逻辑:
  • tx02 不小于 up_limit_id(tx02),所以当前行记录age=20不可见。
  • tx02 大于等于 up_limit_id(tx02) 且小于 low_limit_id(tx05),可以读取上个已提交(tx01)的数据,也就是age=19。
  1. 查询3是事务tx04在事务tx02已提交时进行查询,所以当前数据的事务ID=tx02,由于是可重复读,所以在事务开始就生成了活跃的事务ID[tx01、tx02、tx03、tx04],按照Read View的逻辑:
  • tx02 不小于 up_limit_id(tx01),所以当前行记录age=20不可见。
  • tx02 大于等于 up_limit_id(tx01) 且小于 low_limit_id(tx05),可以读取上个已提交(XXX)的数据,也就是age=18。

各位可以按照这个逻辑,自行设置场景进行代入验证。

总结

基于上述,有以下总结:

  1. MySQL通过事务隔离、锁机制、MVCC处理并发事务。
  2. 事务隔离“读未提交”不做并发处理,不保证数据一致性。
  3. 事务隔离“串行化”通过锁机制进行并发处理,并发性能低下。
  4. 事务隔离“读已提交”和“可重复读”通过MVCC进行并发处理,并发性能高。
  5. MVCC是通过Undo Log(多版本)结合Read View(快照)实现了无锁读并解决了一致性问题。


转载来源:https://juejin.cn/post/7346036731727511578

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
14天前
|
存储 关系型数据库 MySQL
MySQL MVCC全面解读:掌握并发控制的核心机制
【10月更文挑战第15天】 在数据库管理系统中,MySQL的InnoDB存储引擎采用了一种称为MVCC(Multi-Version Concurrency Control,多版本并发控制)的技术来处理事务的并发访问。MVCC不仅提高了数据库的并发性能,还保证了事务的隔离性。本文将深入探讨MySQL中的MVCC机制,为你在面试中遇到的相关问题提供全面的解答。
52 2
|
23天前
|
缓存 关系型数据库 MySQL
MySQL并发支撑底层Buffer Pool机制详解
【10月更文挑战第18天】在数据库系统中,磁盘IO操作是性能瓶颈之一。为了提高数据访问速度,减少磁盘IO,MySQL引入了缓存机制。其中,Buffer Pool是InnoDB存储引擎中用于缓存磁盘上的数据页和索引页的内存区域。通过缓存频繁访问的数据和索引,Buffer Pool能够显著提高数据库的读写性能。
70 2
|
1月前
|
SQL 关系型数据库 MySQL
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
案例剖析:MySQL唯一索引并发插入导致死锁!
|
20天前
|
存储 SQL 关系型数据库
MySQL的事务隔离级别
【10月更文挑战第17天】MySQL的事务隔离级别
94 43
|
14天前
|
存储 关系型数据库 MySQL
MySQL MVCC深度解析:掌握并发控制的艺术
【10月更文挑战第23天】 在数据库领域,MVCC(Multi-Version Concurrency Control,多版本并发控制)是一种重要的并发控制机制,它允许多个事务并发执行而不产生冲突。MySQL作为广泛使用的数据库系统,其InnoDB存储引擎就采用了MVCC来处理事务。本文将深入探讨MySQL中的MVCC机制,帮助你在面试中自信应对相关问题。
35 3
|
1月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1613 14
|
21天前
|
存储 关系型数据库 MySQL
优化 MySQL 的锁机制以提高并发性能
【10月更文挑战第16天】优化 MySQL 锁机制需要综合考虑多个因素,根据具体的应用场景和需求进行针对性的调整。通过不断地优化和改进,可以提高数据库的并发性能,提升系统的整体效率。
30 1
|
25天前
|
SQL 关系型数据库 MySQL
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
尼恩,一位40岁的资深架构师,通过其丰富的经验和深厚的技術功底,为众多读者提供了宝贵的面试指导和技术分享。在他的读者交流群中,许多小伙伴获得了来自一线互联网企业的面试机会,并成功应对了诸如事务ACID特性实现、MVCC等相关面试题。尼恩特别整理了这些常见面试题的系统化解答,形成了《MVCC 学习圣经:一次穿透MYSQL MVCC》PDF文档,旨在帮助大家在面试中展示出扎实的技术功底,提高面试成功率。此外,他还编写了《尼恩Java面试宝典》等资料,涵盖了大量面试题和答案,帮助读者全面提升技术面试的表现。这些资料不仅内容详实,而且持续更新,是求职者备战技术面试的宝贵资源。
阿里面试:MYSQL 事务ACID,底层原理是什么? 具体是如何实现的?
|
2月前
|
存储 Oracle 关系型数据库
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
从基本特性、技术选型、字段类型、事务提交方式、SQL语句、分页方法等方面对比Oracle和MySQL的区别。
448 18
Oracle和MySQL有哪些区别?从基本特性、技术选型、字段类型、事务、语句等角度详细对比Oracle和MySQL
|
1月前
|
SQL 关系型数据库 MySQL
MySQL 是怎么做并发控制的?
本文以 MySQL 8.0.35 的代码为例,尝试对 MySQL 中的并发访问控制进行一个整体的介绍。

相关产品

  • 云数据库 RDS MySQL 版
  • 推荐镜像

    更多
    下一篇
    无影云桌面