五分钟搞清楚MySQL事务隔离级别

2024-04-16 23:38

本文主要是介绍五分钟搞清楚MySQL事务隔离级别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章来源:https://www.jianshu.com/p/4e3edbedb9a8

好久没碰数据库了,只是想起自己当时在搞数据库的时候在事务隔离级别这块老是卡,似懂非懂的。现在想把这块整理出来,尽量用最简洁的语言描述出来,供新人参考。

首先创建一个表account。创建表的过程略过(由于InnoDB存储引擎支持事务,所以将表的存储引擎设置为InnoDB)。表的结构如下:

表结构

然后往表中插入两条数据,插入后结果如下:

数据

为了说明问题,我们打开两个控制台分别进行登录来模拟两个用户(暂且成为用户A和用户B吧),并设置当前MySQL会话的事务隔离级别。

一. read uncommitted(读取未提交数据)

具体用户A的操作如下:

set session transaction isolation level read uncommitted;
start transaction;
select * from account;

结果如下:

数据

用户B的操作如下:

set session transaction isolation level read uncommitted;
start transaction;
update account set account=account+200 where id = 1;

随后我们在A用户中查询数据,结果如下:

uncommittedA数据

结论一:

我们将事务隔离级别设置为read uncommitted,即便是事务没有commit,但是我们仍然能读到未提交的数据,这是所有隔离级别中最低的一种。

那么这么做有什么问题吗?

那就是我们在一个事务中可以随随便便读取到其他事务未提交的数据,这还是比较麻烦的,我们叫脏读。我不知道这个名字是怎么起的,为了增强大家的印象,可以这么想,这个事务好轻浮啊,饥渴到连别人没提交的东西都等不及,真脏,呸!

实际上我们的数据改变了吗?

答案是否定的,因为只有事务commit后才会更新到数据库。

二. read committed(可以读取其他事务提交的数据)---大多数数据库默认的隔离级别

同样的办法,我们将用户B所在的会话当前事务隔离级别设置为read commited。

在用户A所在的会话中我们执行下面操作:

update account set account=account-200 where id=1;
read committed

我们将id=1的用户account减200。然后查询,发现id=1的用户account变为800。

在B用户所在的会话中查询:

select * from account;

结果如下:

read committedB

我们会发现数据并没有变,还是1000。

接着在会话A中我们将事务提交:

commit;

在会话B中查询结果如下:

read committedB1

结论二:

当我们将当前会话的隔离级别设置为read committed的时候,当前会话只能读取到其他事务提交的数据,未提交的数据读不到。

那么这么做有什么问题吗?

那就是我们在会话B同一个事务中,读取到两次不同的结果。这就造成了不可重复读,就是两次读取的结果不同。这种现象叫不可重复读

三. repeatable read(可重读)---MySQL默认的隔离级别

现在有个需求,就是老板说在同一个事务中查询结果必须保持一致,如果你是数据库,你会怎么做?数据库是这么做的。

在会话B中我们当前事务隔离级别为repeatable read。具体操作如下:

set session transaction isolation level repeatable read;
start transaction;

接着在会话B中查询数据:

repeatablereadB1

我们在A用户所在会话中为表account添加一条数据:

insert into account(id,account) value(3,1000);
commit;

然后我们查询看数据插入是否成功:

repeatable readA

回到B用户所在的会话,我们查询结果:

repeatablereadB2

用户B在他所在的会话中想插入一条新数据id=3,value=1000。来我们操作下:

readpeatablereadB3
什么?竟然插不进去,说我数据重复?

用户B当然不服啊,因为查询到数据只有两条啊,为什么插入id=3说我数据重复了呢?

我再看一遍,莫非我眼花了?

repeatablereadB2

试想一下,在实际中用户A和用户B肯定是相互隔离的,彼此不知道操作什么。用户B碰到这种现象,肯定会炸毛的啊,明明不存在的数据,插入却说主键id=3数据重复了。

结论三:

当我们将当前会话的隔离级别设置为repeatable read的时候,当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。

有什么问题吗?

管他呢,老板的要求满足了。要一个事务中读取的数据一致(可重复读)。我只能这么做啊,打肿脸装胖子。数据已经发生改变,但是我还是要保持一致。但是,出现了用户B面对的问题,这种现象叫幻读(记得当时就在这个地方纠结好久,到底什么是幻读啊)。

四. serializable(串行化)

同样,我们将用户B所在的会话的事务隔离级别设置为serializable并开启事务。

set session transaction isolation level serializable;
start transaction;

在用户B所在的会话中我们执行下面操作:

select * from account;

结果如下:

serializableA

那我们这个时候在用户A所在的会话中写数据呢?


readcommittedA1

我们发现用户A所在的会话陷入等待,如果超时(这个时间可以进行配置),会出现Lock wait time out提示:

readcommittedA2

如果在等待期间我们用户B所在的会话事务提交,那么用户A所在的事务的写操作将提示操作成功。

结论四:

当我们将当前会话的隔离级别设置为serializable的时候,其他会话对该表的写操作将被挂起。可以看到,这是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。



作者:伞U
链接:https://www.jianshu.com/p/4e3edbedb9a8
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这篇关于五分钟搞清楚MySQL事务隔离级别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/910227

相关文章

SQL BETWEEN 语句的基本用法详解

《SQLBETWEEN语句的基本用法详解》SQLBETWEEN语句是一个用于在SQL查询中指定查询条件的重要工具,它允许用户指定一个范围,用于筛选符合特定条件的记录,本文将详细介绍BETWEEN语... 目录概述BETWEEN 语句的基本用法BETWEEN 语句的示例示例 1:查询年龄在 20 到 30 岁

MySQL DQL从入门到精通

《MySQLDQL从入门到精通》通过DQL,我们可以从数据库中检索出所需的数据,进行各种复杂的数据分析和处理,本文将深入探讨MySQLDQL的各个方面,帮助你全面掌握这一重要技能,感兴趣的朋友跟随小... 目录一、DQL 基础:SELECT 语句入门二、数据过滤:WHERE 子句的使用三、结果排序:ORDE

MySQL MCP 服务器安装配置最佳实践

《MySQLMCP服务器安装配置最佳实践》本文介绍MySQLMCP服务器的安装配置方法,本文结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下... 目录mysql MCP 服务器安装配置指南简介功能特点安装方法数据库配置使用MCP Inspector进行调试开发指

mysql中insert into的基本用法和一些示例

《mysql中insertinto的基本用法和一些示例》INSERTINTO用于向MySQL表插入新行,支持单行/多行及部分列插入,下面给大家介绍mysql中insertinto的基本用法和一些示例... 目录基本语法插入单行数据插入多行数据插入部分列的数据插入默认值注意事项在mysql中,INSERT I

PostgreSQL 默认隔离级别的设置

《PostgreSQL默认隔离级别的设置》PostgreSQL的默认事务隔离级别是读已提交,这是其事务处理系统的基础行为模式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一 默认隔离级别概述1.1 默认设置1.2 各版本一致性二 读已提交的特性2.1 行为特征2.2

一文详解MySQL如何设置自动备份任务

《一文详解MySQL如何设置自动备份任务》设置自动备份任务可以确保你的数据库定期备份,防止数据丢失,下面我们就来详细介绍一下如何使用Bash脚本和Cron任务在Linux系统上设置MySQL数据库的自... 目录1. 编写备份脚本1.1 创建并编辑备份脚本1.2 给予脚本执行权限2. 设置 Cron 任务2

SQL Server修改数据库名及物理数据文件名操作步骤

《SQLServer修改数据库名及物理数据文件名操作步骤》在SQLServer中重命名数据库是一个常见的操作,但需要确保用户具有足够的权限来执行此操作,:本文主要介绍SQLServer修改数据... 目录一、背景介绍二、操作步骤2.1 设置为单用户模式(断开连接)2.2 修改数据库名称2.3 查找逻辑文件名

SQL Server数据库死锁处理超详细攻略

《SQLServer数据库死锁处理超详细攻略》SQLServer作为主流数据库管理系统,在高并发场景下可能面临死锁问题,影响系统性能和稳定性,这篇文章主要给大家介绍了关于SQLServer数据库死... 目录一、引言二、查询 Sqlserver 中造成死锁的 SPID三、用内置函数查询执行信息1. sp_w

canal实现mysql数据同步的详细过程

《canal实现mysql数据同步的详细过程》:本文主要介绍canal实现mysql数据同步的详细过程,本文通过实例图文相结合给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的... 目录1、canal下载2、mysql同步用户创建和授权3、canal admin安装和启动4、canal

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用