五分钟后,你将真正理解MySQL事务隔离级别!

什么是事务?
事务是一组原子性的SQL操作,所有操作必须全部成功完成,如果其中有任何一个操作因为崩溃或其他原因无法执行,那么所有的操作都不会被执行。也就是说,事务内的操作,要么全部执行成功,要么全部执行失败。
事务的结束有两种,当事务中的所有操作全部成功执行时,事务提交。如果其中一个操作失败,将发生回滚操作,撤消之前到事务开始时的所有操作。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
事务的特性
一个运行良好的事务处理系统,还需要具备四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持续性(Durability)。这四个特性简称为ACID特性。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
原子性(Atomicity)
一个事务必须被视为一个不可分割的最小逻辑工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚。对于一个事务来说,不可能只执行其中的一部分操作,而不执行其中的另外一部分操作,这就是事务的原子性。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
一致性(Consistency)
事务执行的结果必须是从一个一致性的状态转换到另外一个一致性的状态。当数据库只包含成功事务提交的结果时,就说数据库处于一致性状态。如果事务因为崩溃或其他原因尚未完成,被迫中断最终事务没有提交,那么事务中所做的修改也不会保存到数据库中。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
隔离性(Isolation)
通常来说,一个事务的执行不能其它事务干扰。也就是说,一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行的各个事务之间不能互相干扰。后面我们将要讲解隔离级别(Isolation Level)的时候,会发现为什么我们要说“通常来说”是隔离的。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
持续性(Durability)
事务一旦提交,它对数据库中的数据的修改就应该是永久性的。此时即使系统崩溃,修改的数据也不会丢失。不过,实际上持久性也分很多不同的级别,有些持久性策略能够提供非常强的安全保障,而有些则未必。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
事务隔离级别
在SQL标准中定义了四种隔离级别,每一种级别都定义了一个事务所做的修改,在另外一个事务内和事务间,哪些是可见的,哪些是不可见的。低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
未提交读(Read Uncommitted)
在未提交读级别中,事务中的修改即使没有提交,对其他事务也是可见的。读取到了事务没有提交的数据,就被成为脏读(Dirty Read)。事务没有提交的数据是很“脏”的,被读取到会引起很多问题。从性能角度上看,未提交读级别不会比其他级别好很多,但缺乏其他级别的好处,所以在实际应用中很少被用到。
为加上深对未提交读级别的理解,让我们看一个脏读的例子,首先设置事务隔离级别为未提交读:
mysql> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)
再检验一下事务隔离级别:
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set, 1 warning (0.00 sec)
左右分别为两个用户,左边是用户A,右边是用户B,时间线从上至下:
#用户A:查询user表,有一条OneMoreStudy的记录
mysql> select * from user;
+----+--------------+
| id | name |
+----+--------------+
| 1 | OneMoreStudy |
+----+--------------+
1 row in set (0.00 sec)
#用户B:开始事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
#用户B:更新user表的一条记录
mysql> update user set name = 'OMS' where id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
#用户A:查询user表,有一条OMS的记录,脏读
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 1 | OMS |
+----+------+
1 row in set (0.00 sec)
#用户B:提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
提交读(Read Committed)
在提交读级别中,一个事务开始时,只能查询到其他的事务已经提交的修改。也就是说,一个事务从开始到提交之前,任何的修改对其他的事务都是不可见的。提交读级别基本满足了事务的隔离性。
不过,在同一事务中两次查询之间,有其他事务的修改被提交,那么两次查询到结果可能不相同,这就是不可重复读。
为了更好的理解不可重复读,让我们看一个例子,首先设置事务隔离级别为提交读:
mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
再检验一下事务隔离级别:
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set, 1 warning (0.00 sec)
左右分别为两个用户,左边是用户A,右边是用户B,时间线从上至下:
#用户A:开始事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
#用户A:查询user表,有一条OneMoreStudy的记录
mysql> select * from user;
+----+--------------+
| id | name |
+----+--------------+
| 1 | OneMoreStudy |
+----+--------------+
1 row in set (0.00 sec)
#用户B:更新user表的一条记录
mysql> update user set name = 'OMS' where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
#用户A:查询user表,有一条OMS的记录,不可重复读
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 1 | OMS |
+----+------+
1 row in set (0.00 sec)
#用户A:提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
可重复读(Repeatable Read)
在可重复读级别中,保证了在同一个事务中多次读取同样记录的结果是一致的。即使多次读取之间有其他事务对其结果做了修改,同一个事务中多次读取的结果也是一致的。可重复读级别也是MySQL的默认事务隔离级别。
不过,当一个事务在读过某个范围内的记录时,其他事务又在这个范围内插入了新的记录,当之前的事务再一次读取这个范围的记录时,不会读取到新插入的那条记录,这被称为幻读。
为了更好的理解幻读,让我们看一个例子,首先把事务隔离级别设置为可重复读:
mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
再检验一下事务隔离级别:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)
左右分别为两个用户,左边是用户A,右边是用户B,时间线从上至下:
#用户A:开始事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
#用户A:查询user表,有一条记录
mysql> select * from user;
+----+--------------+
| id | name |
+----+--------------+
| 1 | OneMoreStudy |
+----+--------------+
1 row in set (0.00 sec)
#用户B:插入一条数据
mysql> insert into user (name) value ('OneMoreStudy');
Query OK, 1 row affected (0.01 sec)
#用户A:查询user表,还是一条记录,幻读
mysql> select * from user;
+----+--------------+
| id | name |
+----+--------------+
| 1 | OneMoreStudy |
+----+--------------+
1 row in set (0.00 sec)
#用户A:提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
#用户A:查询user表,两条记录
mysql> select * from user;
+----+--------------+
| id | name |
+----+--------------+
| 1 | OneMoreStudy |
| 2 | OneMoreStudy |
+----+--------------+
2 rows in set (0.00 sec)
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
可串行化(Serializable)
在可串行化级别中,强制事务串行执行,是最高的隔离级别。在这个级别中,虽然避免了上面提到的幻读,但是会在读取的每一行上加锁,可能导致大量的超时和锁竞争问题,所以在实际应用中很少被用到。除非,非常需要确保数据一致性并且不要求高并发,可以采用可串行化级别。
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
总结
本文首先简单介绍了事务及其ACID特性,然后着重讲解了事务的四种隔离级别:
- 未提交读:事务中的修改即使没有提交,对其他事务也是可见的。
- 提交读:事务开始时,只能查询到其他的事务已经提交的修改。
- 可重复读:保证在同一个事务中多次读取同样记录的结果是一致的。
- 可串行化:强制事务串行执行。
| 隔离级别 | 脏读 | 不可重复读 | 幻读 |
|---|---|---|---|
| 未提交读 | 可能 | 可能 | 可能 |
| 提交读 | 不可能 | 可能 | 可能 |
| 可重复读 | 不可能 | 不可能 | 可能 |
| 可串行化 | 不可能 | 不可能 | 不可能 |
欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。
五分钟后,你将真正理解MySQL事务隔离级别!的更多相关文章
- [51CTO]新说MySQL事务隔离级别!
新说MySQL事务隔离级别! 事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!本文所讲大部分内容,皆有官网作为佐证,因此对本文内 ...
- 查询mysql事务隔离级别
查询mysql事务隔离级别 查询mysql事务隔离级别 分类: DB2011-11-26 13:12 2517人阅读 评论(0) 收藏 举报 mysqlsessionjava 1.查看当前会话隔离 ...
- MySQL事务隔离级别测试实例
https://www.cnblogs.com/huanongying/p/7021555.html MySQL事务隔离级别 事务隔离级别 脏读 不可重复读 幻读 读未提交(read-uncommit ...
- Mysql事务-隔离级别
MYSQL事务-隔离级别 事务是什么? 事务简言之就是一组SQL执行要么全部成功,要么全部失败.MYSQL的事务在存储引擎层实现. 事务都有ACID特性: 原子性(Atomicity):一个事务必须被 ...
- MySQL事务隔离级别 解决并发问题
MySQL事务隔离级别 1. 脏读: 骗钱的手段, 两个窗口或线程分别调用数据库转账表,转账后未提交,对方查看到账后,rollback,实际钱没转. 演示方法: mysql默认的事务隔离级别为repe ...
- mysql事务隔离级别、脏读、幻读
Mysql事务隔离级别本身很重要,再加上可能是因为各大公司面试必问的缘故,在博客中出现的概率非常高,但不幸的是,中国的技术博客要么是转载,要么是照抄,质量参差不齐,好多结论都是错的,对于心怀好奇之心想 ...
- mysql事务隔离级别与设置
mysql数据库,当且仅当引擎是InnoDB,才支持事务: 1.隔离级别 事务的隔离级别分为:未提交读(read uncommitted).已提交读(read committed).可重复读(repe ...
- MySQL事务隔离级别(二)
搞清楚MySQL事务隔离级别 首先创建一个表 account.创建表的过程略过(由于 InnoDB 存储引擎支持事务,所以将表的存储引擎设置为 InnoDB).表的结构如下: 为了说明问题,我们打开两 ...
- MySQL事务隔离级别(一)
本文实验的测试环境:Windows 10+cmd+MySQL5.6.36+InnoDB 一.事务的基本要素(ACID) 1.原子性(Atomicity):事务开始后所有操作,要么全部做完,要么全部不做 ...
随机推荐
- MySQL 相关规约(v1.0) (转)
0)前言 a. 基本规约 [强制]表存储引擎必须使用InnoDB(针对主库一般是强制要求的) [强制]表字符集默认使用utf8,必要时候使用utf8mb4(个人踩坑:emoji表情存储问题)•说明:• ...
- python 安装虚拟环境virtualenv
1.sudo apt install virtualenv 安装失败 2.sudo apt-get update 更新失败 提示: E: 仓库 “http://mirrors.aliyun.com/u ...
- 废旧手机利用之装一个Linux系统
开篇: 在废旧手机变废为宝的路上一直没有停下,做过电脑遥控器,家居监控器,给电脑扩展屏幕以及跟着大佬学过智能机器人,但是都是一时兴趣,除了家具监控器目前正在使用之外其他也没有使用了. 最近在学习Lin ...
- pc端的弹性布局适配方案
方案及原理:使用rem单位,通过window.onresize来监听浏览器窗口,获取窗口宽度,并改变跟字体大小来达到弹性适配效果. function adaptor(){ //为了便于计算,这里以19 ...
- 异想家Win7系统安装的软件与配置
C盘推荐一个硬盘,256G以上,安装好驱动,激活Win7,备份一次系统(纯净)! 1.Mac.Linux时间同步(双系统时配置): 开始->运行->CMD,打开命令行程序(以管理员方式打开 ...
- 2016 CCPC-Final-Wash(优先队列+贪心)
Wash Mr.Panda is about to engage in his favourite activity doing laundry! He’s brought ...
- JDK源码之Double类&Float类分析
一 概述 Double 类是基本类型double的包装类,fainl修饰,在对象中包装了一个基本类型double的值.Double继承了Number抽象类,具有了转化为基本double类型的功能. 此 ...
- Java面试技巧—如何自我介绍
在企业面试环节中“自我介绍”这个老生常谈的话题就不用多说什么了,面试官必定会问的.那么如何在自我介绍的时候就能够打动面试官,吸引面试官对面试者的兴趣?如何进行自我介绍比较好?有没有什么方式方法呢?当然 ...
- 网络收发与Nginx事件间的对应关系
主机A可以想象是家里面的一台笔记本,也就是客户端,主机B可以想象成服务器上跑着nginx 主机A发送一个http的get请求到主机B经历了哪些请求. 在数据流: 应用层发送了一个get请求,传输层中, ...
- 聊聊CMDB的前世今生
CMDB,Configuration Management DataBase,配置管理数据库,是与 IT 系统所有组件相关的信息库,它包含 IT 基础架构配置项的详细信息. 传统运维思路下的CMDB, ...