【MySQL】事务及隔离性

目录

一、什么是事务

(一)概念

(二)事务的四大属性

(三)事务的作用

(四)事务的提交方式

二、事务的启动、回滚与提交

(一)事务的启动、回滚与提交

(二)特殊情况

1、未 commit 事务,客户端崩溃,MySQL将自动回滚

2、commit 后,客户端崩溃,插入数据不受影响

3、手动开启事务不受自动提交事务影响

4、自动提交事务对单条 SQL 语句的影响

5、结论

三、事务的隔离级别

(二)事务的隔离级别

(三)四种隔离级别详解

1、读未提交

2、读已提交

3、可重复读

4、串行化


一、什么是事务

(一)概念

        MySQL 事务是指数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成,这些操作要么全部执行成功,要么全部不执行,是一个不可分割的工作单位。事务主要用于保证数据的一致性和完整性,特别是在需要多个操作同时成功或同时失败的场景中,比如银行转账、订单处理等。

(二)事务的四大属性

        事务的特性:

  • 原子性:事务中的所有操作要么全部完成,要么全部不完成,不会结束在中间某个状态;
  • 一致性:事务必须使数据库从一个一致性状态变换到另一个一致性状态;
  • 隔离性:多个事务并发执行时,一个事务的执行不会影响其他事务;
  • 持久性:一旦事务提交,其结果就是永久性的,即使系统崩溃也不会丢失。

(三)事务的作用

        事务的出现是为了简化程序开发时可能需要考虑的多种细节问题。例如:当银行账户 A 向银行账户 B 发起转账,首先需要现在 A 中扣除目标金额后再向B中添加目标金额,假如在扣除A账户的金额后出现了网络异常导致转账失败,这时的正常情况应该是账户A上返回了目标金额,事务的出现就使得该操作可以由 MySQL 自动完成而不需要程序员特殊处理。

(四)事务的提交方式

        事务的提交方式分为自动提交和手动提交。在先前学习MySQL语句时并没有对事务进行过特殊操作,这是因为 MySQL 默认设置自动提交。也就是每当执行一条语句后 MySQL自动将该语句进行事务的提交。

        查看事务自动提交方式:

//MySQl 默认打开自动提交
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.02 sec)
//设置自动提交事务关闭
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF   |
+---------------+-------+
1 row in set (0.00 sec)

二、事务的启动、回滚与提交

        为方便演示,需关闭事务自动提交、将事务的隔离级别设为最低并准备一个测试表:

//打开事务自动提交
mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)
//设置隔离级别(需重启终端)
mysql> set global transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)
//创建测试表
mysql> create table test(-> id int primary key,-> name varchar(20) not null,-> salary decimal(10,2) default 0.0-> );
Query OK, 0 rows affected (0.02 sec)

(一)事务的启动、回滚与提交

//手动开启事务 (手动开始事务后该事务不受自动提交影响)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
//保存点1
mysql> savepoint save1;
Query OK, 0 rows affected (0.00 sec)mysql> insert into test values(1,'张三',5000);
Query OK, 1 row affected (0.00 sec)
//保存点2
mysql> savepoint save2;
Query OK, 0 rows affected (0.00 sec)mysql> insert into test values(2,'李四',4500);
Query OK, 1 row affected (0.00 sec)
//此时有两条记录
mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
+----+--------+---------+
2 rows in set (0.00 sec)
//回滚至保存点2
mysql> rollback to save2;
Query OK, 0 rows affected (0.00 sec)
//此时变为一条记录
mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
+----+--------+---------+
1 row in set (0.00 sec)
//回滚至最开始
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
//无记录
mysql> select * from test;
Empty set (0.00 sec)

        由上述结果可以看出,手动开启事务后将不受自动提交的影响。以上便是手动开启事务以及回滚操作。

(二)特殊情况

        以下情况都是最低隔离级别下的操作(读未提交),为方便说明开启两个终端进行演示:

1、未 commit 事务,客户端崩溃,MySQL将自动回滚

//客户端A
mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> insert into test values(1, '张三', 5000);
Query OK, 1 row affected (0.00 sec)mysql> insert into test values(2, '李四', 4500);
Query OK, 1 row affected (0.00 sec)mysql> Aborted
[X@centos-414 ~]$ //客户端B
mysql> select * from test;
Empty set (0.00 sec)mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
+----+--------+---------+
1 row in set (0.00 sec)mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
+----+--------+---------+
2 rows in set (0.00 sec)mysql> select * from test;
Empty set (0.01 sec)

2、commit 后,客户端崩溃,插入数据不受影响

//客户端A
mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> insert into test values(1, '张三', 5000);
Query OK, 1 row affected (0.00 sec)mysql> insert into test values(2, '李四', 4500);
Query OK, 1 row affected (0.00 sec)mysql> commit;
Query OK, 0 rows affected (0.00 sec)mysql> Aborted//客户端B
mysql> select * from test;
Empty set (0.00 sec)mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
+----+--------+---------+
1 row in set (0.00 sec)mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
+----+--------+---------+
2 rows in set (0.00 sec)mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
+----+--------+---------+
2 rows in set (0.00 sec)

3、手动开启事务不受自动提交事务影响

//客户端A
mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> insert into test values(3, '王五', 5500);
Query OK, 1 row affected (0.00 sec)mysql> Aborted//客户端B
mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
+----+--------+---------+
2 rows in set (0.00 sec)mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
|  3 | 王五   | 5500.00 |
+----+--------+---------+
3 rows in set (0.00 sec)mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
+----+--------+---------+
2 rows in set (0.01 sec)

4、自动提交事务对单条 SQL 语句的影响

//客户端A
mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF   |
+---------------+-------+
1 row in set (0.00 sec)mysql> insert into test values(3, '王五', 5500);
Query OK, 1 row affected (0.00 sec)mysql> Aborted//客户端B
mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
+----+--------+---------+
2 rows in set (0.00 sec)mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
|  3 | 王五   | 5500.00 |
+----+--------+---------+
3 rows in set (0.00 sec)mysql> select * from test;
+----+--------+---------+
| id | name   | salary  |
+----+--------+---------+
|  1 | 张三   | 5000.00 |
|  2 | 李四   | 4500.00 |
+----+--------+---------+
2 rows in set (0.00 sec)

5、结论

  • 只要输入 begin 或者 start transaction,事务就必须通过 commit 提交才会持久化,与是否设置自动提交无关;
  • 对于 InnoDB 每一条 SQL 语言都默认封装成事务,自动提交。(select有特殊情况,因为 MySQL 有 MVCC );
  • 如果没有设置保存点,也可以回滚,只能回滚到事务的开始。直接使用 rollback(前提是事务还没有提交)
  • 如果一个事务被提交了则无法回退;
  • InnoDB 支持事务, MyISAM 不支持事务

三、事务的隔离级别

(一)什么是隔离性

        事务的隔离性是数据库事务的四大特性之一,它确保并发执行的多个事务相互独立,一个事务的操作不会被其他事务干扰,从而避免数据不一致问题。隔离性通过不同的隔离级别来控制事务之间的可见性和影响程度。

        查看隔离级别:

//查看全局隔离级别(一般默认为REPEATABLE-READ)
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-UNCOMMITTED      |
+-----------------------+
1 row in set, 1 warning (0.01 sec)
//查看此次会话隔离级别(一般开启MySQL客户端后该值由全局隔离级别进行初始化)
mysql> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED       |
+------------------------+
1 row in set, 1 warning (0.00 sec)
//查看此次会话隔离级别
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set, 1 warning (0.00 sec)

        在使用MySQL客户端时的隔离级别由会话隔离级别等级决定。

        设置隔离级别:

//设置会话隔离级别
mysql> set session transaction isolation level serializable;
Query OK, 0 rows affected (0.00 sec)mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-UNCOMMITTED      |
+-----------------------+
1 row in set, 1 warning (0.00 sec)mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| SERIALIZABLE   |
+----------------+
1 row in set, 1 warning (0.00 sec)

(二)事务的隔离级别

        SQL标准定义了四种隔离级别:

  1. 读未提交
    允许事务读取其他事务未提交的数据,可能出现脏读、不可重复读和幻读的情况;
  2. 读已提交
    只允许读取已提交的数据,避免脏读,但存在不可重复读和幻读的情况;
  3. 可重复读
    确保同一事务多次读取同一数据结果的一致性,可能会出现幻读的情况;
  4. 串行化
    最高隔离的级别,事务完全串行化,可避免所有并发问题,但性能低。

(三)四种隔离级别详解

1、读未提交

        在多个并行的会话中启动事务,一个事务在改动数据库哪怕没有commit提交,其他事务也是能够实时的看到它修改的数据。一个事务在执行中,读到另一个执行中事务的更新(或其他操作)但是未commit的数据,这种不合理的现象叫做脏读(dirty read)。

        上图可以看出,即使左端事务没有进行提交操作,但右端事务仍可以看到表的操作,这就是脏读。

2、读已提交

        事务A在commit提交事务之前,所做的修改是不会被其他事务看到的,一旦事务A发起commit之后,其他事务就能看到事务A对数据的修改。这就造成了其他事务在不同的时间点select查看数据库时,会查到不同的数据。这种现象叫不可重复读

        上图可知,只要事务的操作被提交,那么其他事务可以查看到该事务的插入操作,这就会导致其他事务对同一表的查询结果可能会发生变化,这就是不可重复读。

3、可重复读

        可重复读是MySQL默认的隔离级别。

        上图可知,即使事务的操作被提交,其他事务仍然无法查看到该事务对表的操作,只要其他事务也提交以后才能查看到其他事务对表的操作。

4、串行化

        串行化就是对所有事务进行加锁,事务的执行(一般对查询操作不进行加锁)全部挨个排队,这就导致了效率低下问题。

        开启事务A和事务B,两个事务同时select读取将使用共享锁,不会串行化;事务A中有更新等操作,会阻塞A,直到事务B提交。如果事务A阻塞时间过长,将会由于锁等待超时退出当前事务。

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

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

相关文章

视觉分析明火检测助力山东化工厂火情防控

视觉分析技术赋能化工厂火情防控:从山东事故看明火与烟雾检测的应用价值 一、背景:山东化工事故中的火情防控痛点 近期,山东高密友道化学有限公司、淄博润兴化工科技有限公司等企业接连发生爆炸事故,暴露出传统火情防控手段的局…

【小程序】微信小程序备案失败,有请DeepSeek闪亮出场,看TA如何快速给出解决方案

🌹欢迎来到《小5讲堂》🌹 🌹这是《小程序》系列文章,每篇文章将以博主理解的角度展开讲解。🌹 🌹温馨提示:博主能力有限,理解水平有限,若有不对之处望指正!&a…

Oracle正则表达式学习

目录 一、正则表达简介 二、REGEXP_LIKE(x,匹配项) 三、REGEXP_INSTR 四、REGEXP_SUBSTR 五、REGEXP_REPLACE 一、正则表达简介 相关网址: https://cloud.tencent.com/developer/article/1456428 https://www.cnblogs.com/lxl57610/p/8227599.html https://…

vscode 代理模式(agent mode),简单尝试一下。

1. 起因, 目的: agent mode, 很流行,名气很大。简单试试效果,确实很强。agent mode, 取代人工,确实是前进了一大步。 2. 先看效果 效果对比,左边是 普通的AI 生成的, 右边是 代理…

贝锐蒲公英工业路由器R300A海外版:支持多国4G频段,全球组网

为更好地满足全球部署和企业出海项目的多样化需求,贝锐蒲公英异地组网工业路由器R300A海外版全新上市,并已正式上架速卖通!无论是跨国分支机构协同办公,还是海外工厂设备远程运维,R300A海外版都能为企业提供灵活、高性…

自然图像数据集

目录 CIFAR-10 数据集CIFAR-100 数据集AFHQ 数据集FFHQ 数据集 CIFAR-10 数据集 简介: CIFAR-10 是一个经典的图像分类数据集,广泛用于机器学习领域的计算机视觉算法基准测试。它包含60000幅32x32的彩色图像,分为10个类,每类6000…

【AI面试秘籍】| 第25期:RAG的关键痛点及解决方案深度解析

今天我们来聊聊大模型领域一个非常火热的技术——RAG(Retrieval Augmented Generation)。RAG通过引入外部知识库,有效地缓解了大型语言模型(LLM)在处理知识密集型任务时可能出现的幻觉、知识过时等问题。然而&#xff…

精英-探索双群协同优化(Elite-Exploration Dual Swarm Cooperative Optimization, EEDSCO)

一种多群体智能优化算法,其核心思想是通过两个分工明确的群体——精英群和探索群——协同工作,平衡算法的全局探索与局部开发能力,从而提高收敛精度并避免早熟收敛。 一 核心概念 在传统优化算法(如粒子群优化、遗传算法&#xf…

Transformer相关

问题汇总 Transformer的结构自注意力机制(Self-Attention)多头自注意力前馈神经网络(Feed-Forward Network, FFN)位置编码编码器(Encoder)和解码器(Decoder)Multi-Query Attention(多查询注意力机制)Grouped-query Attention(分组查询注意力机制)FlashAttention与注…

【位运算】两整数之和(medium)

两整数之和(medium) 题⽬描述:解法(位运算):代码复杂度分析 题⽬链接: 371. 两整数之和 题⽬描述: 给你两个整数 a 和 b ,不使⽤ 运算符 和 - ,计算并返回两…

现代密码学入门 | 现代密码学核心特点介绍

在当今互联互通的世界中,数字数据在全球范围内不断流动,安全通信和数据保护的需求从未如此迫切。现代密码学作为数字防御的先锋,提供了一系列复杂的技术和算法,以保护信息免受窥探和恶意行为的侵害。 现代密码学是从其古典前身—…

Redis分布式锁深度解析与最佳实践

1 2 Redis分布式锁实现方式确实是经典问题,下面我将系统性地分析这个方案及其演进过程,并给出生产级的解决方案。 一、基础方案及其缺陷 1. 初始实现方式 SETNX lock_key unique_value # 尝试获取锁 EXPIRE lock_key 30 # 设置过期时间 …

Hive自定义函数案例(UDF、UDAF、UDTF)

目录 前提条件 背景 概念及适用场景 UDF(User-Defined Function) 概念 适用场景 UDAF(User-Defined Aggregate Function) 概念 适用场景 UDTF(User-Defined Table-Generating Function) 概念 适…

Go语言的原子操作

当我们想要对某个变量并发安全的修改,除了使用官方提供的mutex,还可以使用sync/atomic包的原子操作,它能够保证对变量的读取或修改期间不被其他的协程所影响。 Golang提供的原子操作都是非侵入式的,由标准库sync/atmoic包提供&am…

QNAP MEMOS 域名访问 SSL(Lucky)

注意:下述是通过ssh、docker-compose方式安装docker的,不是直接在container station中安装的哈!!! 一、编辑docker-compose.yml文件 用“#”号标识的,在保存文件的时候建议去掉,不然有时候会出…

C#实现远程锁屏

前言 这是一次提前下班没有锁屏进而引发的一次思考后的产物,思考的主要场景是当人离开电脑后,怎么能控制电脑锁屏,避免屏幕上的聊天记录被曝光。 首先想到通过系统的电源计划设置闲置超时时间熄屏,这可能是最接近场景的解决方案&a…

[Protobuf]常见数据类型以及使用注意事项

[Protobuf]常见数据类型以及使用注意事项 水墨不写bug 文章目录 一、基本数据类型1、字段2、字段的修饰规则 二、自定义数据类型1、message类型2、enum类型3、Any类型4、oneof类型5、map类型 三、小工具1.hexdump2.decode 四、注意事项 一、基本数据类型 protobuf 支持多种基础…

JS分支和循环

程序的执行顺序 在程序开发中&#xff0c;程序有三种不同的执行顺序 1.顺序执行 2.分支执行 3.循环执行 程序的代码块 <script>//一个代码块{var num11var num22var num3num1num2}//一个休想var info{name:"chen",age:18} 1.if分支语句&#xff08;单分支语句&…

Android 开发 Kotlin 全局大喇叭与广播机制

在 Android 开发中&#xff0c;广播机制就像一个神通广大的 “消息快递员”&#xff0c;承担着在不同组件间传递信息的重任。Kotlin 语言的简洁优雅更使其在广播机制的应用中大放异彩。今天&#xff0c;就让我们一同深入探索 Android 开发中 Kotlin 全局大喇叭与广播机制的奥秘…

rabbitmq AI复习

RabbitMq rabbitmq &#x1f9d1;‍&#x1f4bb; User 帮我复习rabbitmq相关知识&#xff0c;我是一个经验丰富的程序员 &#x1f916; Assistant 好的&#xff01;很高兴能通过这种方式帮你复习或学习 RabbitMQ 的知识。按照你说的流程&#xff0c;我们从完全零基础开始&…