深入聊聊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

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

不可重复读

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

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

幻读

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

钉钉 AI 助理 钉钉 AI 助理

钉钉AI助理汇集了钉钉AI产品能力,帮助企业迈入智能新时代。

钉钉 AI 助理 21 查看详情 钉钉 AI 助理

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

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

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

1001austin10011未定义

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

更新操作(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

1001austin1001121001austin20022未定义

可以明显看出,执行更新操作时,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

1001austin200323

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

六、总结

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

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

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/351201.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
《下一站江湖2》嵩室山入门晋升攻略
上一篇 2025年11月5日 22:23:26
字节跳动图像创作模型 Seedream 4.0 登顶国际评测排行榜
下一篇 2025年11月5日 22:23:30

相关推荐

  • 开源免费PHP工具 PHP开发效率提升利器

    推荐开源免费PHP开发工具以提升效率:VS Code、Sublime Text轻量高效,PhpStorm专业强大;调试用Xdebug、Kint、Ray;依赖管理选Composer;代码质量工具包括PHPStan、Psalm、PHP_CodeSniffer;数据库管理可用%ignore_a_1%MyA…

    2026年5月10日
    000
  • MySQL数据库不支持中文的解决办法

    接上一篇文章,在解决了mysql+flask环境配置问题之后,往数据库存中文字符串会报1366错误,提示不正确的字符。继而发现默认的mysql采用了latin1字符集,这种编码是不支持中文的。 如果想支持中文的话,需要设置一下mysql字符集。 众所周知utf-8是可以的,gbk也没问题,为了可扩展…

    用户投稿 2026年5月10日
    000
  • Go语言连接外部MySQL数据库:DSN配置与常见错误解析

    本文详细阐述了go语言使用`go-sql-driver/mysql`驱动连接外部mysql数据库的正确方法。重点介绍了数据源名称(dsn)的规范格式,特别是主机地址部分的配置,以避免常见的“getaddrinfow: the specified class was not found.”等网络解析错…

    2026年5月10日
    000
  • 后缀php怎么打开_php文件打开方式与运行环境搭建指南

    要打开PHP文件需根据用途选择方式:查看代码可用文本编辑器或IDE,运行则需服务器环境。推荐新手使用XAMPP、WAMP等集成环境,将文件放入htdocs目录后访问localhost;开发者可利用PHP内置服务器,命令行执行php -S localhost:8000运行;高级用户可手动配置Apach…

    2026年5月10日
    000
  • PHP动态网页数据库备份恢复_PHP动态网页MySQL数据库备份教程

    答案:PHP动态网页的MySQL数据库备份与恢复需通过定期导出SQL文件并安全存储来保障数据安全,核心方法包括使用mysqldump命令行工具实现高效灵活的自动化备份,利用phpMyAdmin图形化工具进行手动导出导入以降低操作门槛,以及通过PHP脚本调用系统命令将备份过程集成到应用中;恢复时可采用…

    2026年5月10日
    000
  • php登录怎么实现_php用户登录系统完整实现

    <blockquote>PHP用户登录系统的核心是安全验证与会话管理。首先创建POST提交的登录表单,避免敏感信息暴露;后端通过session_start()启动会话,使用trim()和htmlspecialchars()清理输入,防止XSS攻击;利用PDO预处理语句查询数据库,防止SQ…

    用户投稿 2026年5月10日
    000
  • 远程MySQL数据库连接指南:从本地PHP应用访问GCP实例数据库

    本文详细指导如何在本地php应用中连接到google cloud platform (gcp) 虚拟机实例上的远程mysql数据库。教程涵盖了数据库连接参数的配置、使用php pdo建立连接的方法、gcp环境下的网络配置要点,以及常见的安全和故障排除建议,旨在帮助开发者顺利实现跨环境的数据库通信。 …

    2026年5月10日
    000
  • 在PHP中实现MySQL数据插入时避免重复记录的策略

    本文将探讨在php应用中向mysql数据库插入数据时,如何有效避免重复记录的产生。针对当主键或唯一索引字段值已存在的情况,我们将介绍使用`insert ignore`语句的策略,以确保数据完整性并防止不必要的重复插入,从而简化数据管理逻辑。 引言:数据完整性与重复记录问题 在数据库管理中,数据完整性…

    2026年5月10日
    000
  • php实现哪些功能

    PHP是一种通用脚本语言,可用来实现广泛的功能,包括:动态Web开发:生成响应用户请求的动态 веб页面。内容管理系统(CMS):构建允许用户管理网站内容的CMS。电子商务:开发具有购物车、订单处理和支付网关集成的电子商务网站。服务器端编程:编写命令行脚本和工具。文件操作:创建、读取、写入和删除文件…

    2026年5月10日
    000
  • PHP 动态 SQL WHERE 子句构建:避免重复 AND 的策略

    本文探讨了在 php 中动态构建 sql 查询 `where` 子句时常见的“`where and`”语法错误及其解决方案。通过逐步构建条件字符串,确保第一个条件不带 `and`,后续条件正确使用 `and` 连接,从而生成符合 sql 规范的查询语句,提高代码的健壮性和可读性。 动态构建 SQL …

    2026年5月10日
    200
  • PHP中基于用户角色的页面访问控制实践

    本教程详细讲解如何在PHP应用程序中利用会话(Session)机制实现基于用户角色的页面访问控制。通过正确的session_start()调用、用户登录时的角色信息存储,以及在受保护页面进行严格的会话和角色类型检查,确保只有特定用户(如“manager”)才能访问指定页面,从而有效防止未经授权的访问…

    2026年5月10日
    100
  • php数据库触发器应用实例_php数据库自动化任务的处理

    通过MySQL触发器与PHP结合,可在数据变更时自动记录日志、校验数据及同步状态。首先创建user_log表并定义AFTER INSERT/UPDATE/DELETE触发器,记录users表的操作信息;随后使用PHP的PDO执行增删改操作,验证日志生成;接着创建BEFORE INSERT触发器限制非…

    2026年5月10日
    000
  • php数据库数据压缩处理_php数据库存储空间优化方法

    可通过启用MySQL行压缩、PHP层数据压缩、优化字段结构及分表归档策略减少存储占用。具体步骤:1. 使用InnoDB压缩表并设置KEY_BLOCK_SIZE;2. PHP中用gzcompress压缩大数据字段,存为BLOB;3. 选用更小数据类型如TINYINT,避免冗余TEXT;4. 将历史数据…

    2026年5月10日
    000
  • php数据整理怎么按日期字段分组汇总_php按日期分组统计与时间段合并技巧

    可使用SQL或PHP对数据按日期分组汇总。1、通过MySQL的DATE()、YEAR()、MONTH()函数在查询时按日、月、年分组统计;2、在PHP中遍历数组,以date(‘Y-m-d’)等格式化日期作为键进行归类;3、按周可使用date(‘o-W’…

    2026年5月10日
    000
  • php数据库如何实现全文搜索 php数据库搜索引擎的构建方法

    答案:在PHP项目中实现数据库全文搜索需利用MySQL的FULLTEXT索引功能,通过PDO预处理语句执行MATCH()…AGAINST()查询,结合PHP过滤用户输入以防止SQL注入;为提升体验可引入中文分词、权重排序、结果高亮等优化措施;数据量增长后可迁移至Elasticsearch…

    2026年5月10日
    000
  • php调用数据同步方案_php调用多数据库数据同步

    首先明确同步需求与模式,如单向、双向、定时或实时同步;接着使用PHP通过PDO连接多数据库,基于时间戳或增量ID同步变更数据,并记录同步状态;为提高可靠性,可引入消息队列、binlog解析、中间同步层及加锁机制;最后注意网络超时、分页处理、错误重试、日志记录与测试验证,确保数据一致性与系统稳定性。 …

    2026年5月10日
    000
  • php怎么安装_在云服务器上部署PHP环境的步骤

    答案:在云服务器上部署PHP环境需搭建LEMP栈(Linux+Nginx+MySQL+PHP-FPM),依次更新系统、安装Nginx、MariaDB、PHP-FPM及扩展,配置Nginx解析PHP并测试,最后通过权限控制、安全配置、防火墙和HTTPS等措施保障环境安全稳定。 在云服务器上部署PHP环…

    2026年5月10日
    000
  • 使用MySQL和PHP高效获取最热门数据条目:统计与排序实践

    本教程详细阐述如何利用mysql的聚合函数和php的mysqli扩展,高效地从数据库中查询并排序出最常出现的数据条目。文章将通过一个具体的案例,指导读者构建正确的sql查询,并结合php进行数据处理和调试,避免常见的sql语法错误和php运行时问题,从而准确获取按频率降序排列的热门数据。 在Web开…

    2026年5月10日
    000
  • SQL查询:精确判断事件过期,结合日期与时间列

    本文旨在解决数据库中事件过期判断不精确的问题,特别是当事件的过期日期和时间分别存储在不同列时。我们将探讨两种主流的sql查询策略:一种是利用逻辑运算符`or`和`and`进行分情况判断,另一种是通过合并日期和时间列为单一时间戳进行直接比较。文章将详细阐述每种方法的实现方式、适用场景及相关注意事项,确…

    2026年5月10日
    100
  • HTML表单如何实现白名单功能?怎样只允许授权用户?

    要实现%ignore_a_1%的白名单功能并确保只有授权用户操作,核心答案是必须依赖后端服务器进行严格的身份认证、会话管理、授权检查和数据验证,前端仅能提供用户体验层面的初步提示而不能保障安全;具体而言,首先通过用户身份认证(如用户名/密码或oauth)确认用户身份,服务器创建会话并返回标识符,后续…

    2026年5月10日
    700

发表回复

登录后才能评论
关注微信