MySQL 事务详解

在数据库管理系统中,事务是一个非常重要的概念,MySQL 也不例外。本文将详细介绍 MySQL 中的事务,包括事务的定义、四大特性、提交与回滚代码样例、并发问题以及隔离等级等方面的内容。

一、事务定义

事务是一个逻辑工作单元,它是一组数据库操作的集合,这些操作要么全部成功执行,要么全部不执行,以确保数据库的一致性和完整性。例如,在一个银行转账系统中,从一个账户扣款并向另一个账户存款,这两个操作必须作为一个事务来执行,要么都成功,要么都失败,以保证账户余额的正确性。

二、事务的四大特性(ACID)

1. 原子性(Atomicity)

原子性确保事务中的所有操作要么全部执行成功,要么全部回滚到事务开始之前的状态。就像一个原子,不可分割。例如,在一个购物网站上,用户下单时需要同时更新库存、生成订单记录和扣除用户余额等操作。这些操作必须一起成功完成,否则任何一个操作失败都要将整个事务回滚,保证数据的一致性,不会出现库存减少了但订单没生成或者余额扣除了但库存没更新的情况。

2. 一致性(Consistency)

一致性要求事务在执行前后,数据库必须从一个合法的状态转换到另一个合法的状态。例如,在一个库存管理系统中,事务开始前库存数量为 100,执行一个事务将 50 件商品出库,那么事务结束后库存数量应该变为 50,数据库的完整性约束(如主键约束、外键约束等)不能被破坏,始终保持数据的正确性和合法性。

3. 隔离性(Isolation)

隔离性指的是多个事务并发执行时,它们之间相互隔离,互不干扰。每个事务都感觉不到其他事务在同时进行,就好像每个事务都在独立的数据库环境中执行一样。例如,一个用户在查询自己的账户余额时,不应该看到其他用户正在进行的转账操作对余额的中间状态影响,而只能看到事务开始前的初始余额或者事务成功提交后的最终余额。

4. 持久性(Durability)

持久性意味着一旦事务成功提交,它对数据库所做的更改就会永久保存下来,即使系统发生故障也不会丢失。例如,在一个电商系统中,用户成功下单并支付后,订单信息和支付记录会被持久化保存到数据库中,不会因为服务器突然断电或者系统崩溃而丢失这些数据。

三、在 MySQL 中,事务提交与回滚代码样例

1. 事务提交示例

-- 开启事务
START TRANSACTION;-- 执行一系列数据库操作
INSERT INTO users (name, age) VALUES ('John', 30);
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
INSERT INTO transactions (amount, user_id) VALUES (100, 1);-- 提交事务
COMMIT;

在上述代码中,首先使用 START TRANSACTION 开启一个事务,然后执行了插入用户信息、更新账户余额和插入交易记录等操作。最后,如果所有操作都成功执行,使用 COMMIT 提交事务,将这些操作对数据库的更改永久保存。

2. 事务回滚示例

-- 开启事务
START TRANSACTION;-- 执行一系列数据库操作
INSERT INTO users (name, age) VALUES ('Tom', 25);
-- 假设这里出现了某种错误,比如违反了唯一性约束
UPDATE accounts SET balance = balance + 200 WHERE user_id = 2; -- 回滚事务
ROLLBACK;

在这个示例中,在执行插入用户信息后,更新账户余额时可能由于某种原因(如违反约束)导致操作失败。此时,使用 ROLLBACK 回滚事务,将数据库恢复到事务开始之前的状态,就好像这些操作从未执行过一样。

四、事务的并发问题

在多用户并发访问数据库的情况下,可能会出现以下事务并发问题:

1. 脏读

脏读是指一个事务读取到了另一个事务未提交的数据。例如,事务 A 修改了一条记录但还未提交,此时事务 B 读取了这条记录。如果事务 A 后来回滚了操作,那么事务 B 读取到的数据就是无效的,也就是“脏”数据。

2. 不可重复读

不可重复读是指在一个事务中多次读取同一数据集合,但是在这个过程中,另一个事务对该数据集合进行了修改,导致前后两次读取的结果不一致。例如,事务 A 读取了一条记录,然后事务 B 更新了这条记录并提交。接着事务 A 再次读取这条记录时,发现数据与第一次读取的不同,这种情况就叫做不可重复读。

3. 幻读

幻读是指一个事务在执行查询操作时,按照某个条件查询到了一些记录。然后另一个事务在该表中插入了一些符合该条件的新记录,并且提交了事务。当第一个事务再次按照相同条件查询时,会发现多了一些之前没有查询到的记录,就好像出现了“幻觉”一样。

五、事务的隔离等级

为了解决事务并发问题,MySQL 提供了四种隔离等级:

1. 读未提交(Read Uncommitted)

在这个隔离级别下,事务可以读取到其他事务未提交的数据,这会导致脏读问题。它的隔离性最低,但并发性最高,因为它对事务之间的隔离限制最少。在一些对数据一致性要求不高,且更注重并发性能的场景中可能会使用,但一般情况下不建议使用,因为脏读可能会导致数据的不一致性和错误的结果。

2. 读已提交(Read Committed)

读已提交隔离级别下,一个事务只能读取到其他事务已经提交的数据,解决了脏读问题。但是,它仍然可能会出现不可重复读的情况。例如,事务 A 在读取一条记录后,事务 B 对该记录进行了修改并提交,当事务 A 再次读取该记录时,会得到不同的结果。大多数数据库系统的默认隔离级别都是读已提交,它在保证一定数据一致性的同时,也提供了较好的并发性能。

3. 可重复读(Repeatable Read)

可重复读是 MySQL 的默认隔离级别。在这个级别下,事务在执行期间多次读取同一数据集合时,会得到相同的结果,解决了不可重复读问题。但是,它可能会出现幻读现象。例如,事务 A 按照某个条件查询到了一些记录,然后事务 B 插入了一些符合该条件的新记录并提交,当事务 A 再次按照相同条件查询时,会发现多了一些记录。为了解决幻读问题,MySQL 在可重复读隔离级别下通过多版本并发控制(MVCC)和间隙锁等机制来实现。

4. 串行化(Serializable)

串行化是最高的隔离级别,它通过强制事务串行执行,完全避免了事务并发问题,即脏读、不可重复读和幻读都不会出现。但是,这种隔离级别会严重影响数据库的并发性能,因为它相当于对事务进行了顺序执行,只有一个事务执行完后,另一个事务才能开始执行。在实际应用中,只有在对数据一致性要求非常高,且并发量较小的场景下才会考虑使用串行化隔离级别。

六、隔离级别与一致性的关系

不同的隔离级别对事务的一致性有着不同的影响。

读未提交隔离级别由于可能出现脏读,导致数据的一致性无法得到保证。一个事务读取到了其他未提交事务的“脏”数据,如果这些数据最终被回滚,那么就会产生不一致的结果。

读已提交隔离级别解决了脏读问题,保证了数据不会被读取到未提交的无效状态,从而在一定程度上提高了数据的一致性。但是,不可重复读的存在可能会使得在同一个事务中对同一数据的多次读取结果不一致,对于某些需要严格一致性的业务场景来说,这可能还是不够的。

可重复读隔离级别通过 MVCC 等机制解决了不可重复读问题,进一步增强了数据的一致性。在大多数情况下,能够满足业务对数据一致性的要求。然而,幻读问题的存在可能在一些特殊场景下影响数据的一致性,比如在需要精确统计符合某个条件的记录数量时。

串行化隔离级别完全避免了事务并发问题,提供了最强的一致性保证。但是,它是以牺牲并发性能为代价的。在实际应用中,需要根据业务的具体需求来权衡选择合适的隔离级别,以在保证数据一致性的前提下,尽可能提高数据库的并发处理能力。

总之,MySQL 中的事务是保证数据库数据一致性和完整性的重要机制。了解事务的四大特性、并发问题以及隔离等级等相关知识,对于正确使用和管理数据库至关重要。在开发应用程序时,需要根据实际业务场景合理选择事务隔离级别,以达到数据一致性和系统性能的最佳平衡。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/458863.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SpringCloud】07-分布式事务与Seata

1. 分布式事务 2. Seata 3. 安装seata 配置数据库 CREATE DATABASE IF NOT EXISTS seata /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTIONN */; USE seata;------------------------------- The script used when storeM…

加强版 第一节图像二值化定义

本节课介绍了图像又彩色图像转变为彩色图像转变为灰度图像转变为黑色图像的转化过程。 灰度图像-单通道-取值范围为0-255 二值图像-单通道-取值0(黑色)-255(白色) 二值分割 有五种分割方式 如图所示 第一种:大于…

RabbitMQ 高级特性——事务

文章目录 前言事务配置事务管理器加上Transactional注解 前言 前面我们学习了 RabbitMQ 的延迟队列,通过延迟队列可以实现生产者生产的消息不是立即被消费者消费。那么这篇文章我们将来学习 RabbitMQ 的事务。 事务 RabbitMQ 是基于 AMQP 协议实现的,…

「C/C++」C/C++标准库之#include <cmath>数学库

✨博客主页何曾参静谧的博客📌文章专栏「C/C」C/C程序设计📚全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasoli…

认识线程 — JavaEE

目录 认识线程(Thread) 1 线程是什么? 2 为什么要有线程 3 进程和线程的区别 区别一 区别二 区别三 区别四 4. Java的线程和操作系统线程的关系 认识线程(Thread) 1 线程是什么? 一个线程就是一个 "执行流"。…

Excel-多表数据查找匹配(VLOOKUP)

💖简介 Excel的VLOOKUP函数同样可以用来查找表格中的数据。VLOOKUP(垂直查找)是一个非常有用的函数,它可以在一个表格或数据表的一列中搜索特定的值,并返回与之在同一行上的另一列中的值。 📖环境 WPS …

R语言机器学习算法实战系列(十二)线性判别分析分类算法 (Linear Discriminant Analysis)

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍LDA的原理LDA的步骤教程下载数据加载R包导入数据数据预处理数据描述数据切割构建模型预测测试数据评估模型模型准确性混淆矩阵模型评估指标ROC CurvePRC Curve保存模型总结优点:缺…

【大数据学习 | kafka】producer的参数与结构

1. producer的结构 producer:生产者 它由三个部分组成 interceptor:拦截器,能拦截到数据,处理完毕以后发送给下游,它和过滤器不同并不是丢弃数据,而是将数据处理完毕再次发送出去,这个默认是不…

【c++篇】:探索c++中的std::string类--掌握字符串处理的精髓

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨文章所属专栏:c篇–CSDN博客 文章目录 前言一.std::string对象的创建二.std::string对象的访问三.std::str…

读取有空格的string对象(getline)

文章目录 读取有空格的string对象1.使用标准库中的iostream来写2.**使用getline读取一整行** 读取有空格的string对象 1.使用标准库中的iostream来写 #include<iostream> using namespace std; int main() {string s;cin >> s;cout << s << endl;ret…

探索Python安全字符串处理的奥秘:MarkupSafe库揭秘

文章目录 探索Python安全字符串处理的奥秘&#xff1a;MarkupSafe库揭秘第一部分&#xff1a;背景介绍第二部分&#xff1a;MarkupSafe是什么&#xff1f;第三部分&#xff1a;如何安装MarkupSafe&#xff1f;第四部分&#xff1a;MarkupSafe的简单使用方法1. 使用escape函数2.…

Tomcat安装与使用

Tomcat优点 1、开源免费&#xff1a;是一个免费、开源的Web服务器&#xff0c;可以在任何环境下自由使用&#xff0c;无需支付任何费用。 2、轻量级&#xff1a;是一个轻量级的Web服务器&#xff0c;其核心仅有几百K&#xff0c;启动速度非常快。 3、易于安装和配置&#xff1a…

【笔记】LLM位置编码之标准位置编码

标准位置编码 起源原理证明&#xff1a;对于任何固定的偏移量 k k k&#xff0c; P E p o s k PE_{posk} PEposk​可以表示为 P E p o s PE_{pos} PEpos​的线性函数。计算 P E p o s k 与 P E p o s PE_{posk} 与PE_{pos} PEposk​与PEpos​的内积结论 通俗理解缺点 起源 由…

深度学习之降维和聚类

1 降维和聚类 1.1 图解为什么会产生维数灾难 ​ 假如数据集包含10张照片&#xff0c;照片中包含三角形和圆两种形状。现在来设计一个分类器进行训练&#xff0c;让这个分类器对其他的照片进行正确分类&#xff08;假设三角形和圆的总数是无限大&#xff09;&#xff0c;简单的…

Typora一款极简Markdown文档编辑器和阅读器,实时预览,序列号生成!免费!最新可用!

文章目录 一、Typora下载和安装二、Typora序列号生成 Typora是一款Markdown编辑器和阅读器&#xff0c;风格极简&#xff0c;实时预览&#xff0c;所见即所得&#xff0c;支持MacOS、Windows、Linux操作系统&#xff0c;有图片和文字、代码块、数学公式、图表、目录大纲、文件管…

异常处理与调试:如何编写稳健的代码(8/10)

目录 异常处理与调试&#xff1a;如何编写稳健的代码&#xff08;8/10&#xff09; 介绍 异常概述 常见的异常类型 使用 try...except 处理异常 基本结构 示例&#xff1a;读取文件内容 捕获多个异常 自定义异常 示例&#xff1a;自定义异常类 调试代码 使用 print…

AI跟踪报道第62期-本周AI新闻: 微软推出Copilot的AI Agent和Computer Control

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

重写(外壳不变)

重写&#xff1a;是子类对父类非静态、非private修饰、非final修饰、非构造方法等的实现过程进行重新编写返回值和形参都不能改变。 重写的好处&#xff1a;子类可以根据需要&#xff0c;定义专属于自己的行为。&#xff08;子类能够根据需要实现父类的方法&#xff09; 方法…

封装echarts组件,即插即用(附源码)

前言&#xff1a;最近一个项目刚收工&#xff0c;分享一个常用的封装echarts的组件。 一、直接上组件代码 <template><el-card class"echart-card" shadow"hover"><template v-slot:header><div class"card-header">&…

JS面试八股文(三)

&#x1f60a;文章目录 21.说一下事件循环22.ajax是什么&#xff1f;怎么实现&#xff1f;23.get和post有什么区别&#xff1f;24.Promise的内部原理是什么&#xff1f;它的缺点是什么&#xff1f;25.Promise和async await的区别是什么&#xff1f;26.浏览器的存储方式有哪些&a…