数据库(MySQL)—— 事务

数据库(MySQL)—— 事务

  • 什么是事务
  • 事务操作
    • 未控制事务
    • 测试异常情况
  • 控制事务一
    • 查看/设置事务提交方式:
    • 提交事务
    • 回滚事务
  • 控制事务二
    • 开启事务
    • 提交事务
    • 回滚事务
  • 并发事务问题
    • 脏读(Dirty Read)
    • 不可重复读(Non-Repeatable Read)
    • 幻读(Phantom Read)
    • 丢失更新(Lost Update)
  • 并发事务问题演示及事务隔离级别

我们今天来学习MySQL中的事务:

什么是事务

MySQL中的事务(Transaction)是一个逻辑上不可分割的工作单元,由一系列数据库操作组成,这些操作要么全部成功执行,要么全部不执行。事务的主要目的是为了维护数据库的一致性和完整性,尤其是在多用户同时访问和修改数据的并发环境下。

事务具备以下四个关键特性,即ACID特性:

  1. 原子性(Atomicity):事务是一个原子操作,事务中的所有操作要么全部完成,要么完全不起作用。如果事务中任何一部分操作失败,整个事务都会被回滚,仿佛从未发生过。
  2. 一致性(Consistency):事务执行前后,数据库从一种合法的状态转换到另一种合法的状态。即使在事务执行期间出现错误,数据库也应该保持一致的状态,不因事务失败而残留部分结果。
  3. 隔离性(Isolation):并发执行的事务之间互不干扰,一个事务内部的操作对其他事务是不可见的,直到该事务完成并提交。MySQL通过不同的事务隔离级别来实现这一特性,如读未提交(READ UNCOMMITTED)、读已提交(READ COMMITTED)、可重复读(REPEATABLE READ)和串行化(SERIALIZABLE)。
  4. 持久性(Durability):一旦事务被提交,它对数据库的更改应该是永久性的,即使系统发生故障也不会丢失。这意味着事务的结果会被稳定地存储在数据库中。

在MySQL中,特别是使用InnoDB存储引擎时,可以通过BEGIN或START TRANSACTION语句显式地开始一个事务,使用COMMIT语句提交事务,以确认所有更改,或者使用ROLLBACK语句回滚事务,取消所有在事务中做出的更改。此外,还可以通过设置事务的隔离级别来调整不同事务之间的可见性,以适应不同的应用场景需求。

举个例子:
张三给李四转账1000块钱,张三银行账户的钱减少1000,而李四银行账户的钱要增加1000。 这一组操作就必须在一个事务的范围内,要么都成功,要么都失败。
在这里插入图片描述正常情况: 转账这个操作, 需要分为以下这么三步来完成 , 三步完成之后, 张三减少1000, 而李四增加1000, 转账成功:
在这里插入图片描述异常情况: 转账这个操作, 也是分为以下这么三步来完成 , 在执行第三步是报错了, 这样就导致张三减少1000块钱, 而李四的金额没变, 这样就造成了数据的不一致, 就出现问题了。
在这里插入图片描述为了解决上述的问题,就需要通过数据的事务来完成,我们只需要在业务逻辑执行之前开启事务,执行完毕后提交事务。如果执行过程中报错,则回滚事务,把数据恢复到事务开始之前的状态:
在这里插入图片描述

注意: 默认MySQL的事务是自动提交的,也就是说,当执行完一条DML语句时,MySQL会立即隐式的提交事务。

事务操作

数据准备:

drop table if exists account;create table account(
id int primary key AUTO_INCREMENT comment 'ID',
name varchar(10) comment '姓名',
money double(10,2) comment '余额'
) comment '账户表';insert into account(name, money) VALUES ('张三',2000), ('李四',2000);

未控制事务

测试正常情况:

-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';

在这里插入图片描述

测试异常情况

我们把数据都恢复到2000:

update account set money = 2000;

然后再次一次性执行下面的SQL语句:

-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
出错了....
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';

在这里插入图片描述
(“出错了…” 这句话不符合SQL语法,执行就会报错)

检查最终的数据情况, 发现数据在操作前后不一致了:
在这里插入图片描述

控制事务一

查看/设置事务提交方式:

SELECT @@autocommit ;
SET @@autocommit = 0 ;

在MySQL中,SELECT @@autocommit;SET @@autocommit = 0; 是用来查看和设置当前会话的自动提交状态的命令。

  • SELECT @@autocommit;
    这条命令用于查询当前会话的自动提交(autocommit)设置。@@autocommit是一个系统变量,表示是否启用自动提交模式。如果返回值为1,意味着自动提交是开启的,即每次执行完一条SQL语句后,改动会立即保存到数据库中,成为永久性的变更。如果返回值为0,则表示自动提交是关闭的,你需要手动控制事务的提交与回滚。
    在这里插入图片描述
  • SET @@autocommit = 0;
    这条命令用于设置当前会话的自动提交模式为关闭状态。将@@autocommit的值设为0后,意味着在该会话中执行的SQL语句不会自动提交,直到你显式执行COMMIT命令才将事务中的更改永久保存。这样可以让你在一系列操作之间保持数据的一致性,便于实现事务的原子性、一致性、隔离性和持久性(ACID特性)。在需要手动控制事务边界的应用场景中非常有用。
    在这里插入图片描述

提交事务

此时我们又把数据恢复到2000,又执行那三条语句:
在这里插入图片描述我们查看结果发生变化了,但是这只是针对当前会话,如果我们重新开一个会话,就会发现数据没有发生变化,这里我用Navicat重开一个会话:
在这里插入图片描述
但是如果我执行commit,提交之后:
在这里插入图片描述
再在Navicat中查询结果:
在这里插入图片描述

所以我们设置提交模式为非自动的时候,如果我们想要我们的提交彻底生效,要记得执行commit

回滚事务

如果我在事务的流程当中出错了:
在这里插入图片描述
可以执行ROLLBACK操作,使数据回到开始前的状态:
在这里插入图片描述

控制事务二

开启事务

START TRANSACTIONBEGIN ; 1

提交事务

COMMIT;

回滚事务

ROLLBACK;

举个例子:

-- 开启事务
start transaction;-- 1. 查询张三余额
select * from account where name = '张三';
-- 2. 张三的余额减少1000
update account set money = money - 1000 where name = '张三';
-- 3. 李四的余额增加1000
update account set money = money + 1000 where name = '李四';
-- 如果正常执行完毕, 则提交事务
commit;-- 如果执行过程中报错, 则回滚事务
-- rollback;

在这里插入图片描述

并发事务问题

并发事务问题是数据库管理系统中常见的挑战,特别是在多用户环境下,不同的事务可能同时对相同的数据进行读取或修改,从而引发以下几种典型的问题:

  1. 脏读(Dirty Read):事务A读取了事务B尚未提交的数据,如果事务B随后进行了回滚,那么事务A读取到的就是无效的“脏”数据。
  2. 不可重复读(Non-Repeatable Read):在同一个事务内,两次相同的查询返回了不同的结果,这是因为在两次查询之间,有其他事务提交了对该数据的修改或删除操作。
  3. 幻读(Phantom Read):在一个事务内,第一次查询时没有特定条件的某些行,但是在同一事务内的第二次查询时,由于其他事务插入了新行,这些新行就仿佛“幻影”一样出现了。
  4. 丢失更新(Lost Update):两个事务同时读取同一条数据,然后基于原始数据进行修改并提交,如果数据库系统没有适当的并发控制机制,后提交的事务可能会覆盖前一个事务的更改,导致前一个事务的更新丢失。

脏读(Dirty Read)

场景:事务A正在更新一条记录但尚未提交,事务B在此时读取了事务A更改但未提交的数据。

  • 事务A:

    BEGIN;
    UPDATE accounts SET salary = salary - 100 WHERE id = 1; -- 减少张三账户100元,但没提交
    
  • 事务B (同时进行):

    SELECT salary FROM accounts WHERE id = 1; -- 查询张三账户余额,看到减少了100元
    
  • 假设:事务A因为某种原因执行了ROLLBACK。

  • 结果:事务B读取到了实际上未生效的“脏”数据(减少了100元的余额),而最终张三的账户余额并未发生变化。

不可重复读(Non-Repeatable Read)

场景:在同一个事务内,两次查询返回了不同的结果,因为中间有其他事务提交了修改。

  • 事务A:

    BEGIN;
    SELECT salary FROM accounts WHERE id = 1; -- 第一次查询张三余额为500元
    
  • 事务B (并发执行,并提交):

    UPDATE accounts SET salary = salary + 100 WHERE id = 1; -- 给张三账户加100元并提交
    
  • 事务A 继续:

    SELECT salary FROM accounts WHERE id = 1; -- 第二次查询张三余额变为600元
    
  • 结果:事务A在同一个事务内两次查询同一数据得到不同结果,违反了可重复读原则。

幻读(Phantom Read)

场景:在一个事务内,两次相同的查询因其他事务插入新行而返回不同的行数。

  • 事务A:

    BEGIN;
    SELECT * FROM orders WHERE customer_id = 1; -- 初始查询客户1的订单有5个
    
  • 事务B (并发执行,并提交):

    INSERT INTO orders(customer_id, order_date) VALUES(1, CURDATE()); -- 给客户1新增一个订单并提交
    
  • 事务A 继续:

    SELECT * FROM orders WHERE customer_id = 1; -- 再次查询客户1的订单,现在有6个
    
  • 结果:事务A第二次查询时出现了额外的“幻影”行,即原本不存在但在查询过程中被其他事务插入的记录。

丢失更新(Lost Update)

场景:两个事务同时修改同一数据,后提交的事务覆盖了前一个事务的更改。

  • 事务A:

    BEGIN;
    SELECT salary FROM accounts WHERE id = 1; -- 张三余额为500元
    
  • 事务B (几乎同时开始,并提交快):

    BEGIN;
    SELECT salary FROM accounts WHERE id = 1; -- 也看到张三余额为500元
    UPDATE accounts SET salary = salary + 100 WHERE id = 1; -- 增加100元并提交
    
  • 事务A 继续, 未知事务B已更新:

    UPDATE accounts SET salary = salary - 100 WHERE id = 1; -- 减少100元并提交,基于旧值操作
    
  • 结果:尽管事务B给张三增加了100元,但事务A的减操作基于事务B之前的数据,最终张三的账户余额没有变化,事务B的更新被事务A无意中“丢失”了。

为了解决这些问题,数据库系统提供了不同的事务隔离级别,分别是:

  • 读未提交(Read Uncommitted):最低的隔离级别,允许脏读、不可重复读和幻读。
  • 读已提交(Read Committed):只允许不可重复读和幻读,禁止脏读。
  • 可重复读(Repeatable Read):MySQL的InnoDB默认隔离级别,禁止脏读和不可重复读,但可能出现幻读。
  • 串行化(Serializable):最高的隔离级别,通过完全锁定读取和更新的行,避免了脏读、不可重复读和幻读,但可能导致大量锁竞争,影响性能。

并发事务问题演示及事务隔离级别

在这里插入图片描述图中打钩的表示在此模式下,该问题可能发生,打叉表示可防止此问题发生。

SELECT @@TRANSACTION_ISOLATION;

在这里插入图片描述
这里我们要看脏读,首先要把事务的隔离级别设置为Read uncommitted,设置事务隔离级别用下面的代码:

SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL { READ UNCOMMITTED |
READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

session是设置当前对话,global是全局。

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

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

相关文章

python在Django中,模板加载器(Template Loaders)是负责查找和加载模板文件的组件

在Django中,模板加载器(Template Loaders)是负责查找和加载模板文件的组件。Django默认使用django.template.loaders.filesystem.Loader和django.template.loaders.app_directories.Loader这两个加载器,它们分别用于从文件系统和D…

数据结构练习题---环形链表详解

链表成环,在力扣中有这样的两道题目 https://leetcode.cn/problems/linked-list-cycle/ https://leetcode.cn/problems/linked-list-cycle-ii/description/ 这道题的经典解法是利用快慢指针,如果链表是一个环形链表,那么快指针(fast)和慢指…

关于MS-DOS时代的回忆

目录 一、MS-DOS是什么? 二、MS-DOS的主要功能有哪些? 三、MS-DOS的怎么运行的? 四、微软开源MS-DOS源代码 五、高手与漂亮女同学 一、MS-DOS是什么? MS-DOS(Microsoft Disk Operating System)是微软公…

最基本的c++代码

#include <iostream> #include <string> using namespace std; void james_kobe(); std::string bas() {string name;cout << "请输入您的目的地" << endl;cin >> name;cin.get(); // 消耗掉输入的换行符return name; }std::string ca…

在Nacos中,如何注册和发现服务实例?

在Nacos中注册与发现服务实例 在微服务架构中&#xff0c;服务注册与发现是一个核心组件&#xff0c;它使得服务提供者能够注册自己的服务信息&#xff0c;服务消费者能够发现并调用所需的服务。Nacos&#xff0c;作为阿里巴巴开源的一个更易于构建云原生应用的动态服务发现、…

【SHADER】Shader实例学习2:Loading Wheel

简介 shader代码来自github上一个项目&#xff0c;compose libraries&#xff0c;但是链接找不到了。。。&#xff0c;代码很简洁&#xff0c;但是里面的技巧适合我这种初学者领会。 Shader代码 const float PI 3.14159265359;// 按角度旋转。&#xff08;安卓的坐标由于从…

工作问题记录React(持续更新中)

一、backdrop-filter:blur(20px); 毛玻璃效果&#xff0c;在安卓机上有兼容问题&#xff0c;添加兼容前缀也无效&#xff1b; 解决方案&#xff1a;让设计师调整渐变&#xff0c;不要使用该属性! 复制代码 background: radial-gradient(33% 33% at 100% 5%, #e9e5e5 0%, rgba…

C++类定义时成员变量初始化

在C11中允许在类定义时对成员变量初始化。 class A { public:A() { }void show(){cout << "m_a " << m_a << endl;cout << "m_b " << m_b << endl;} private:int m_a 10;//类定义时初始化int m_b; //没有初始化…

Microsoft 365 for Mac(Office 365)v16.84正式激活版

office 365 for mac包括Word、Excel、PowerPoint、Outlook、OneNote、OneDrive和Teams的更新。Office提供了跨应用程序的功能&#xff0c;帮助用户在更短的时间内创建令人惊叹的内容&#xff0c;您可以在这里创作、沟通、协作并完成重要工作。 Microsoft 365 for Mac(Office 36…

Delta lake with Java--liquid clustering

网上说liquid clustering还是实验阶段&#xff0c;python和scala有对应的函数&#xff0c;java没有&#xff0c;只能用sql语句来建表&#xff0c;尝试了两天&#xff0c;遇到很奇怪的情况&#xff0c;先上代码&#xff1a; import io.delta.tables.DeltaTable; import org.apa…

Debian系统的开机启动和进程看护

1.推荐的做法 - systemctl systemctl&#xff0c;这种做法需要事先编辑一个.service的脚本放在/etc/systemd/system&#xff0c;这里有一个例子&#xff1a; [Unit] DescriptionGuide Rtsp Server - using mediamtx Afternetwork.target[Service] Typesimple WorkingDirecto…

HTML_CSS学习:浮动

一、浮动简介 相关代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>浮动_简介</title><style>div{width: 600px;height: 400px;background-color: #1c80d9;}img{float:…

Rust入门篇:你好,世界

文章目录 前言编写程序编译运行最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;欢迎回来 对于我们大多数人接触一门新的编程语言时&#xff0c;第一个任务一般是编写一个控制台输出hello world的程序 我们这篇博客也是如此&#xff0c;让我们一起使用rust去和世界打个招…

智慧旅游引领旅游行业创新发展:借助智能科技的力量,实现旅游资源的优化配置和高效利用,推动旅游行业的转型升级和可持续发展

目录 一、引言 二、智慧旅游的定义与特点 1、信息化程度高 2、智能化服务丰富 3、互动性强 4、个性化服务突出 5、可持续性发展 三、智慧旅游在旅游行业创新发展中的作用 &#xff08;一&#xff09;优化旅游资源配置 &#xff08;二&#xff09;提升旅游服务质量 &…

VMware虚拟机下载安装教程【超详细】

推荐大佬文章&#xff1a;VMware下载安装教程(超详细)-CSDN博客 目录 一、VMware下载 二、VMware安装 一、VMware下载 1、进入VMware官网 2、点击“Products”&#xff0c;向下滑动 --> 选择“Workstation Pro” 3、向下滑动&#xff0c;找到并选择“Download VMware Wo…

智慧文旅展现文化新风貌,科技助力旅行品质升级:借助智慧技术,文旅产业焕发新生机,为旅行者带来更高品质的文化体验之旅

一、引言 在数字化、智能化的浪潮下&#xff0c;文旅产业正迎来前所未有的发展机遇。智慧文旅作为文旅产业与信息技术深度融合的产物&#xff0c;不仅为旅行者带来了全新的文化体验&#xff0c;也为文旅产业注入了新的活力。本文旨在探讨智慧文旅如何借助智慧技术展现文化新风…

pyinstaller打包pytorch和transformers程序

记录使用pyinstaller打包含有pytorch和transformers库的程序时遇到的问题和解决方法。 环境和版本信息 操作系统&#xff1a;Windows 11 Python&#xff1a;3.10.12 pyinstaller&#xff1a;5.13.0 torch&#xff1a;2.2.2 transformers&#xff1a;4.40.1 打包过程和问…

LLaMA详细解读

LLaMA 是目前为止&#xff0c;效果最好的开源 LLM 之一。精读 LLaMA 的论文及代码&#xff0c;可以很好的了解 LLM 的内部原理。本文对 LLaMA 论文进行了介绍&#xff0c;同时附上了关键部分的代码&#xff0c;并对代码做了注释。 摘要 LLaMA是一个系列模型&#xff0c;模型参…

深入理解 Java 并发:AbstractQueuedSynchronizer 源码分析

序言 在多线程编程中&#xff0c;同步机制是保障线程安全和协调线程之间操作顺序的重要手段。AQS 作为 Java 中同步机制的基础框架&#xff0c;为开发者提供了一个灵活且高效的同步工具。本文将通过对 AQS 源码的分析&#xff0c;解读 AQS 的核心实现原理&#xff0c;并深入探…

使用FastGPT+OneAPI在本地使用Llama3

FastGPT 是一个基于 LLM 大语言模型的知识库问答系统&#xff0c;提供开箱即用的数据处理、模型调用等能力。同时可以通过 Flow 可视化进行工作流编排&#xff0c;从而实现复杂的问答场景&#xff01;他的重要特点就是工作流编排。 工作流编排&#xff1a;基于 Flow 模块的工作…