大学学过,自己也看过,奈何总是遗忘,特别是隔离级别相关概念,
感觉这一块的知识掌握水平还处在背面试题阶段。。。
最近看过一篇文章,感觉这一块水还是很深的,有必要重新拾起,先简单整理下,后续再加深学习
目录
事务定义
一个最小的不可再分的工作单元 Transaction
为了避免操作数据库出现数据不一致问题
ACID
面试必问
- A: Atomicity 原子性
- C: Consistency 一致性
- I: Isolation 隔离性
- D: Durability 持久性
原子性:事务是一个不可分割的原子性操作,要么都执行,要么都不执行,不会只执行一般
一致性:事务中数据不可能凭空产生或者消失,前后保持一致;比如转账过程中,转账前后,双发金额总和不变
隔离性:事务与事务之间是隔离,防止事务间操作互相影响;隔离性又分为不同的隔离级别,见下文
持久性:事务执行完数据的修改是永久的(存入硬盘)
还记得最开始学习JDBC,我们要手动开启事务和提交事务,如果异常会自动rollback
mysql事务使用方式
1,用 BEGIN, ROLLBACK, COMMIT来实现
- BEGIN 开始一个事务
- ROLLBACK 事务回滚
- COMMIT 事务确认
2,直接用 SET 来改变 MySQL 的自动提交模式:
- SET AUTOCOMMIT=0 禁止自动提交
- SET AUTOCOMMIT=1 开启自动提交
隔离级别
根据上文ACID的定义,事务之间是有一定的隔离性
隔离性是等级的概念,等级高低事务之间的影响性不同
- 读未提交(Read uncommitted)
- 读提交(read committed)
- 可重复读(repeatable read)
- 串行化(Serializable)
读未提交是级别最低的隔离级别,串行化是最高隔离级别,不允许事务并行执行,完全串行,
不会造成任何数据不一致问题,也不是我们讨论的重点
隔离级别越高,虽然数据更安全,但是数据库的并发性就越差
因此既不会设置最低的隔离级别也不会设置最高的隔离级别
事务并发造成的数据不一致问题
- 脏读
读未提交的隔离级别下会造成脏读,顾名思义,读取到脏数据,什么是脏数据,就是读到另一个事务没有提交的数据
举个不恰当的例子,如果银行转账事务设置成读未提交,你欠了别人1万块钱,你开启事务,然后给别人转1万钱,然后打电话说你已经还他钱了,
然后他就去看自己的余额确实多了1万,然后你这边不提交事务,来波回滚…不就舒服了嘛
但是现实不可能这样的,你想到的漏洞,程序员早都想到了…
脏读就是读取了另一个事务未提交的事务,生产上不会用读未提交隔离级别
- 不可重复读
一个事务多次读取的数据出现不一致,由于另一个事务在并发的执行更新数据操作并提交事务
读提交下会出现这种情况
- 幻读
就像是幻觉一样,再次读取数据凭空多了一行数据或少了一行数据(说明屏蔽不了insert和update的影响)
个人认为不可重复读和幻读比较容易混淆,不可重复读是对某一行数据而言是否变化,而幻读是对于查询出来的所有数据是不是多了或者少了某一条
趁热打铁,贴上我从网上盗的一个对应表
大家可能发现了这和我们大学学的还是有点不一样的
就是可重复读的隔离级别,不会发生幻读(innodb)
mysql隔离级别
查看默认隔离界别:
select @@tx_isolation;
设置隔离级别:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
实验验证理论
开2个窗口,便于测试mysql事务的并发执行
创建一个表,并插入2条数据
create table person ( name varchar(20), age int );
insert into person(name,age) values("doinb",24),("xiaotian",20);
mysql> select * from person
-> ;
+----------+------+
| name | age |
+----------+------+
| doinb | 24 |
| xiaotian | 20 |
+----------+------+
2 rows in set (0.00 sec)
下面我们把各场景都模拟一下
读未提交:
读已提交:
不可重复读: (隔离级别依然是读提交,虽然解决了脏读的问题,但又有了新问题)
可重复读:
幻读:(隔离级别依然是可重复读)
这个验证了我们上面的那个表:可重复读并不会发生幻读(innodb)
加餐
转载请注明:汪明鑫的个人博客 » 事务和隔离级别知识整理
说点什么
3 评论 在 "事务和隔离级别知识整理"
楼主 mysql 默认隔离级别是repeable-read
是的,也可以自己设置隔离级别
不可重复读上面有个笔误,导致每次查询结果不一样。。。