深入聊聊MySQL中的事务特性和实现原理


本篇文章带大家聊聊mysql中的事务特性,介绍一下多版本并发控制mvcc实现原理,希望对大家有所帮助!

深入聊聊MySQL中的事务特性和实现原理

一、概念

事务 一般指的是逻辑上的一组操作,或者作为单个逻辑单元执行的一系列操作,一个事务中的所有操作会被封装成一个不可分割的执行单元,这个单元的所有操作要么全部执行成功,要么全部执行失败,只要其中任意一个操作执行失败,整个事务就会执行回滚操作。

二、事务的特性以及类型介绍

2.1 事务特性

image.png

原子性(atomicity)

事务的原子性指的是构成事务的所有操作要么全部执行成功,要么全部执行是失败。

一致性(consistency)

事务的一致性指的是事务执行之前和执行之后,数据始终处于一致的状态。

隔离性(isolation)

事务的隔离性指的是并发执行的两个事务之间互不干扰,也就是说,一个事务执行的过程中是无法看到其他事务运行过程的中间状态的。

?‍注意:MySQL是通过锁个MVCC机制来保证事务的隔离性。

持久性(duration)

事务的持久性指的是一旦事务被提交后,此事务对数据的更改操作会被持久化到数据库中,并且不会被回滚。

2.2 两种事务类型介绍

  • 本地事务
  • 分布式事务

本地事务

通常基于关系型数据库控制的事务可以称作为传统事务或者本地事务。

本地事务的执行流程

本地事务的执行流程图.png

  • 客户端开始事务操作之前,需要开启一个连接回话;

  • 开始回话之后,客户端发起开启事务的指令;

  • 事务开始后,客户端发送各种SQL语句处理数据;

  • 正常情况下,客户端会发起提交事务的指令,如果发生异常情况,客户端会发起回滚事务命令;

  • 上述流程完成后,关闭会话。

✔本地事务是有资源管理器在本地进行管理的。

本地事务的缺点在于:

  • 不具备分布式事务的处理能力
  • 一次事务过程只能连接一个支持事务的数据库,既不能用于多个事务性数据库。

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

并发事务带来的问题.png

更新丢失(脏写)

当两个会在两个以上的事务同时操作同一行数据,并给予最初选定的值更新该行数据时,视为事务之间是无法感知彼此的存在的,所以会出现最后的更新操作会覆盖之前其他事务完成的更新操作。

举个例子:

张三的账户为100元,当前有两个事务:事务1和事务2,事务1是将张三账户余额增加100元,事务2是将张三余额增加200,起初事务1和事务2同时读到张三的账户余额都是100元,然后事务1和事务2分别更新张三月,假设事务1先于事务2提交,但是最近两个事务都提交后张三的余额为300元(正常情况应该是400元),也就是说:后提交的事务2覆盖了事务1的更新操作,这就是所谓的更新丢失,更新丢失(脏写)本质上是写操作的冲突,然而解决脏写的方式是让每个事务串行方式执行,保证事务按照一定的顺序执行写操作。

image.png

脏读

一个事务读取到另一个事务未提交的数据。比如:事务1正在对张三的余额增加100元,在这个事务没提交之前,另一个事务2读取了正在修改的这条数据,如果没有事务的控制下,第二条事务就会读取到没有被提交的脏数据,并且对脏数据丛下一步的处理,此时就会产生未提交数据的依赖关系,通常这种现象被称为 脏读,也就是说:脏读是一个事务读取了另一个事务没提交的数据。

image.png

?脏读本质上是读写操作的冲突,解决方法是先写后读,也就是写完之后再读。

不可重复读

一个事务读取了某些数据,在一段时间后,这个事务再次读取之前读过的数据,此时发现读取的数据发生了变化,或者其中某些数据记录已经被删除,这种现象被称为:不可重复读,即同一个事务,使用同样的查询语句,在不同时刻读取到的结果不一致。

不可重复读的本质上也是读写操作冲突,解决方法是先读后写,也就是读完之后再写。

幻读

一个事务按照相同的查询条件重新读取之前读过的数据,此时发现其他事务插入了满足当前查询条件的新数据,数据结果集变多,这种现象称为幻读,即一个事务两次读取一个范围的数据记录,两次读到的结果不同。

一览妙笔 一览妙笔

自媒体、编剧、营销人员写作工具

一览妙笔 50 查看详情 一览妙笔

幻读的本质上也是读写操作冲突,解决方法是先读后写,也就是读完之后再写。

那到这里,很多小伙伴就有疑问,同样本质都是读写操作冲突,解决方法是先读后写,不可重复读和幻读到底有何区别?,我下面见简单解释一下:

  • 1️⃣ 不可重复读的重点在于更新和删除操作,而幻读的重点在于插入操作。

  • 2️⃣ MySQL使用锁机制实现事务的隔离级别时,在可重复读隔离级别中,SQL语句第一个读取到数据后,会将相应的数据加锁,使得其他事务无法修改和删除这些数据,通过锁的方式实现可重复读。但是这种方法无法对新数据的插入加锁,如果事务1读取了数据,或者修改和删除了数据,事务2还可以进行插入操作,导致事务1莫名其妙地多了一条之前没有的数据,这就是幻读。

  • 3️⃣ 所以,幻读是无法通过锁机制来避免,需要使用串行化的事务隔离级别,但是这种事务隔离级别会大大降低数据库的并发能力。

✔MySQL是通过MVCC(多版本并发控制)机制来避免不可重复读和幻读的。

四、MySQL事务的隔离级别

image.png

使用下面的命令可以查询全局级别和会话级别的事务隔离级别:

# 默认数据库的事务隔离级别为:可重复读(REPEATABLE-READ)
SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;

image.png

五、多版本并发控制MVCC

Multi-Version Concurrency Control多版本并发控制,MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问。

MVCC比锁的优势

可以将MVCC看成行级别锁的一种妥协,它在许多情况下避免了使用锁,同时可以提供更小的开销。根据实现的不同,它可以允许非阻塞式读,在写操作进行时只锁定必要的记录。

MVCC的实现原理

MVCC的是通过保存数据澡某个时间点的快照来实现的,也就是说,不管事务执行多长的时间,每个事务看到的数据都是一致的。根据事务的开始时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。InnonDB主要通过为每一行记录添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。但是InnoDB并不存储这些事件发生时的 实际时间 ,相反它只存储这些事件发生时的系统 版本号(version) 。这是一个随着事务的创建而不断增长的数字。每个事务在事务开始时会记录它自己的系统版本号。每个查询必须去检查每行数据的版本号与事务的版本号是否相同。

《高性能MySQL》书籍中介绍到:

MVCC只在REPEATABLE READREAD COMMITTIED两个隔离级别下工作,其他两个隔离级别都和MVCC不兼容,因为READ UNCOMMITTED总是读取最新的数据行,而不符合当前事务版本数据行,而SERIALIZABLE串行化隔离级别则会对所有读取的行都加锁。

接下来举个例子说明在可重复读事务隔离级别下,MVCC机制是如何完成增删改查操作的。

  • 查询操作(SELECT)

在查询操作中,InnoDB存储引擎跟根据以下两个条件查询对应的行记录,只有满足对应条件才会被返回:

1️⃣ 只查找不晚于当前事务版本的数据行,也就是说,InnoDB存储引擎只会查找版本号小于或者等于当前事务版本的数据行,这些数据行要么在该事务开始前就存在,要么就是事务本身插入或者更新的行。
2️⃣ 对于数据删除,数据行删除的版本要么还没有被定义,要么大于当前事务的版本号,只有这样才能确保事务读到的行,在事务开始前并没有被删除。

举个例子,存在 事务A事务B 两个事务,事务A中存在两套相同的SELECT语句,事务B存在一条UPDATE语句,事务A 的第一条查询语句在事务B提交之前执行,第二条查询语句在 事务B 提交之后执行,事务A 如下所示:

-- 事务A操作
START TRANSACTION;
SELECT * FROM account WHERE id = 1;     //在事务B提交之前执行
SELECT * FROM account WHERE id = 1;     //在事务B提交之后执行
COMMIT;

事务B:

-- 事务B操作
START TRANSACTION;
UPDATE account SET balance = balance+100 WHERE id = 1;
COMMIT;

✔结论:如果没有使用MVCC机制,则事务A中的第一条SELECT语句读取的数据是修改前的数据,而第二条SELECT语句读取的是修改后的数据,两次读取的数据不一致,想想,那不就乱了吗?? 如果使用了MVCC机制,无论事务B如何修改数据,事务A的两条查询语句的到的结果始终是一致的。

  • 插入操作(SELECT)

在插入操作中,InnoDB会将新插入的每一条行记录的当前系统版本包保存为行版本号。

比如:向account表插入一条数据,同时MVCC的两个版本号分别为create_versiondelete_versioncreate_version代表创建行的版本号,delete_version代表删除行的版本号,另外还有一个事务ID字段,如下面所示:

INSERT INTO account(id, name, balance) values(1001, 'austin', 100);

对应的版本号信息如下表:

id name balance transaction_id create_version delete_version
1001 austin 100 1 1 未定义

可以看出,当向数据表新增记录时,需要设置保存行的版本号,而删除行的版本号未定义。

  • 更新操作(SELECT)

在更新操作中,InnoDB存储引擎会插入一行新记录,并保存当前系统的版本号为新记录行的版本号,同时保存当前系统的版本号到原来数据行作为删除标识。比如:将account数据表中id为1001的用户账户月增加100元,对应SQL如下:

UPDATE account SET balance = balance+100 WHERE id = 1001;

执行SQL, 在MVCC机制下的更新操作如下表所示:

id name balance transaction_id create_version delete_version
1001 austin 100 1 1 2
1001 austin 200 2 2 未定义

可以明显看出,执行更新操作时,MVCC机制是先将原来的数据复制一份,将balance字段增加100后,再讲create_version字段的值设置为当前系统的版本号,而delete_version字段的值未定义。

注意的是:原来的行会被复制到Undo Log中。

  • 删除操作(SELECT)

在删除操作中,InnoDB存储引擎会保存删除的每一个行记录当前的系统版本号,作为删除标识。比如:删除account数据表中id为1001的数据,SQL如下所示:

DELETE FROM account WHERE id = 1001;

对应MVCC机制下的删除操作如下表所示:

id name balance transaction_id create_version delete_version
1001 austin 200 3 2 3

可以看出,当删除数据表数据行时,MVCC机制会将当前系统的版本号写入删除数据行版本字段delete_version中,以此来表示当前数据行已经被删除。

六、总结

本文主要讲述了事务的特性、类型和本地事务和分布式事务的区别,通过不同的示例解释并发事务带来的更新丢失、脏读、不可重复读、幻读的问题,同时介绍了多版本并发控制MVCC的实现原理,如果文章对你有帮助,感谢点赞?+评论?+收藏❤,我是:?‍?austin流川枫,我们下期见!

【相关推荐:mysql视频教程】

以上就是深入聊聊MySQL中的事务特性和实现原理的详细内容,更多请关注其它相关文章!


# 事务  # 米业网站推广服务热线  # 雁塔区网站推广哪家强  # seo标题检查工具  # seo成功人员  # 读到  # 也就是说  # 解决方法  # 客户端  # 就会  # 都是  # 的是  # 指的是  # 所示  # 镜像  # mysql  # 公司网站建设拓扑图  # 绵阳网站优化推广服务  # 网站建设在哪申请  # 天津网站建设在线推广  # 做seo优势  # seo www.wywk.cn 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: 《红果免费短剧》下载观看方法  Win10截图远程协助 Win10远程桌面截屏法【场景应用】  芒果TV官网登录入口 芒果TV官方网站登录入口  iPhone16Plus参数配置如何调整声音_iPhone16Plus参数配置声音调整详细方法  POKI小游戏在线免费入口链接 POKI小游戏无下载秒玩玩  如何定制PrimeNG Sidebar的背景颜色  第五人格PC版怎么避免被封号_第五人格PC版防封号注意事项  mysql如何回滚事务_mysql ROLLBACK事务回滚方法  QQ网页版入口导航 QQ网页版在线访问通道  《edge浏览器》关闭翻译功能方法  j*a中赋值运算符是什么?  背部总是隐隐作痛怎么回事 背痛如何改善  sublime text 4如何安装_最新版sublime下载与汉化教程  美发店速赢秘籍  win11资源管理器标签页怎么用 Win11文件管理器多标签高效操作【新功能】  红手指专业版app注册教程  夸克浏览器资源嗅探怎么用 夸克浏览器网页资源下载技巧【教程】  Linux如何优化系统启动流程_Linux启动项优化方案  Google Cloud Functions 时区处理指南:理解与最佳实践  苹果iPhone14ProMax如何新建AppleID_iPhone14ProMax新建AppleID具体流程  聚水潭ERP后台管理系统登录 聚水潭ERP官方登录通道  苹果电脑如何快速查看电池状态 苹果电脑电池信息快捷方法  快手网页版官方访问 快手网页版页面在线打开  Excel如何快速合并单元格内容_Excel文本合并与函数操作技巧  Golang中的rune与byte类型区别是什么_Golang字符与字节处理详解  猫眼电影app如何设置电影上映提醒_猫眼电影上映提醒设置教程  yandex网页版直接登录 yandex官方入口平台访问方法  《下一站江湖2》独孤剑诀习得方法  微博网页版访问入口 微博网页版网页端使用指南  怎样设置开机后自动运行某个程序_Windows启动文件夹与任务计划【自动化】  使用TinyButStrong生成HTML并结合Dompdf创建PDF教程  跨语言测试实践:使用Python Selenium测试现有J*a Web项目  多多买菜门店端app订单查看方法  C++如何实现矩阵乘法_C++二维数组矩阵运算代码示例  lol小红书怎么|直播|?lol小红书|直播|是什么意思?  折叠屏手机充不进电是什么问题? 特殊结构带来的维修难点  在J*a里什么是行为抽象_抽象行为对代码复用的提升作用  MacBook Pro词典使用指南  搜狗浏览器如何查找页面中的文字 搜狗浏览器Ctrl+F页面搜索功能  SQL聚合查询、联接与筛选:GROUP BY 子句的正确使用与常见陷阱  《i莞家》修改昵称方法  sublime如何处理超大文件不卡顿 _sublime打开大日志文件技巧  微信朋友圈怎么设置三天可见 微信朋友圈设置指定天数可见步骤【教程】  Animex动漫社社登录官网 Animex动漫社资源社入口直达  在VS Code中进行数据科学和机器学习开发  画质怪兽120帧安卓和平精英免费版  百度浏览器无法安装扩展程序_百度浏览器插件安装失败原因解析  快递优选如何查优选物流_快递优选专属物流渠道查询与配送时效  c++如何实现观察者设计模式_c++行为型设计模式实战  《漫蛙manwa2》防走失网页版链接2025 

 2023-02-10

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.