五分钟后,你将真正理解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):事务开始后所有操作,要么全部做完,要么全部不做 ...
随机推荐
- Redis(六):list/lpush/lrange/lpop 命令源码解析
上一篇讲了hash数据类型的相关实现方法,没有茅塞顿开也至少知道redis如何搞事情的了吧. 本篇咱们继续来看redis中的数据类型的实现: list 相关操作实现. 同样,我们以使用者的角度,开始理 ...
- MyBatis5——Mybatis整合log4j、延迟加载
开启日志:Log4j (1)加入jar包 (2)在conf.xml中配置开启日志: <settings> <!-- 开启日志,并指定要使用的具体日志为log4j -- ...
- JAVA WebSocket 使用时需要注意的地方
最近在做一个项目,需要用WebSocket与另外一个平台建立通讯,来获取项目业务需要的实时数据,因此项目一启动,后台就要与另外一个平台建立WebSocket连接并且要保证他们的之间有且只有一条持续畅通 ...
- 团队第一次作业(By七个小矮人)
一.团队简介 1.团队名称:七个小矮人 2.团队成员列表 201731024137 马驰(队长) 201731021227 于丁 201731024114 杨汶桐 201731024125 李朋珂 2 ...
- SpringMVC 中的异常处理
目录 1.搭建编码分析 2.编写异常类 3.编写自定义异常处理器 4.在springmvc.xml中配置异常处理器 5.编写Error.jsp.index.jsp页面 6.编写collector代码模 ...
- Ubuntu 获取 root 用户权限并以 root权限登录
操作步骤: 1.打开终端,使用 sudo passwd root 命令进行 Ubuntu 中密码的重置 2.切换到 /usr/share/lightdm/lightdm.conf.d 目 ...
- code review工具之codebrag安装使用
code review之codebrag安装使用 1.说明 codebrag是一款审核代码的工具,安装部署很简单.现在网上有很多代码审核工具,收费的开源的一大堆,开源的比较好的是Facebook的ph ...
- mybatis入门案例分析
mybatis入门案例分析 一.设计模式分析 public class MybatisTest { public static void main(String[] args) throws Exce ...
- orcle导入大数据文件
0,创建ctl文件 内容为 OPTIONS (skip=0) LOAD DATA CHARACTERSET 'UTF8' INFILE 'F:\anhui_data\20180814\shangh ...
- Nginx之keepalived高可用工具
1.创建两台虚拟机,分别为主机和从机,区别两台虚拟机的IP地址 2. 将keepalived上传到linux系统当中 3. cd /usr/local目录 4. tar -zxvf keepalive ...