五分钟后,你将真正理解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):事务开始后所有操作,要么全部做完,要么全部不做 ... 
随机推荐
- 基于python的感知机
			一. 1.感知机可以描述为一个线性方程,用python的伪代码可表示为: sum(weight_i * x_i) + bias -> activation #activation表示激活函数,x ... 
- 有关PyCharm安装库失败的问题的解决方法
			最近因为要使用Python的缘故,安装了python IDE+pycharm,如此安装的原因是因为Pycharn 并不像anaconda一样拥有相对完整的依赖库和开发包,可以直接运行python,但因 ... 
- 浅谈JS异步(asychrouous)
			一.概念 (1)asychronous 异步 是JS这种单线程语言解决多任务的一种方法,将耗时的任务(io)设定为异步工作,先交给浏览器负责相关功能的线程来实现耗时的部分工作,按顺序放入任务队列中,等 ... 
- 根据范围爬TMS规则瓦片
			因为需要简单写了一个下载地图的爬虫,代码如下: #coding=utf-8 import urllib.request import os import socket import zlib impo ... 
- Word Embeddings: Encoding Lexical Semantics(译文)
			词向量:编码词汇级别的信息 url:http://pytorch.org/tutorials/beginner/nlp/word_embeddings_tutorial.html?highlight= ... 
- 【Nginx入门系列】第四章 通过域名匹配虚拟主机,不修改端口
			域名访问原理 我们在显示生活中,我们怎样通过一个域名来访问到我们所需要的网站呢? 例如www.baidu.com,我们在浏览器输入百度网址会先发送请求到DNS服务器,DNS会通过我们的域名解析百度对应 ... 
- 通过openjdk源码分析ObjectMonitor底层实现
			通过openjdk源码分析ObjectMonitor底层实现 Hotspot JDK只是部分开源,将底层的调用C++的native方法的具体实现屏蔽了,而openjdk则将这部分也开源了,接下来我们通 ... 
- Arduino系列之LCD1602模块使用方法(一)
			下面我将简单介绍LCD1602模块的使用方法: 1602液晶显示器(1602 Liquid Crystal Display,此后简称1602 LCD)是一种常见的字符液晶显示器,因其能显示16*2个字 ... 
- js实现表单的提交
			<form action="" method="post" name="form"> <tr> ... 
- 【动手学pytorch】softmax回归
			一.什么是softmax? 有一个数组S,其元素为Si ,那么vi 的softmax值,就是该元素的指数与所有元素指数和的比值.具体公式表示为: softmax回归本质上也是一种对数据的估计 二.交叉 ... 
