一、开篇简介
事务的作用我就不再提及了, 相信看到这篇文章的基本上都会知道事务的概念。本篇文章首先会介绍一下事务的特性、四种隔离级别以及对应的实战测试,希望帮读者加深事务的理解。
二、事务的ACID特性
原子性(atomicity)
一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部成功,要么全部失败
一致性(consistency)
数据库永远是从一个一致性状态转向另一个一致性状态,举个例子就是银行进行转账,倘若事务失败,无论如何都要保证银行中所有的钱的数量不会变化,也就是说数据不会被事务破坏。
隔离性(isolation)
一般来说,事务所做的修改会在最终提交之前,对其他事务不可见。后面的隔离级别也是针对隔离性这个特性。
持久性(durability)
一般来说,一旦事务提交,数据就会被永久保存到数据库中。
三、事务隔离级别
RU(read uncommited)
顾名思义,可以读没有提交的数据,这种行为也成为脏读,真正的开发中会很少使用。
RC(read commited)
读已提交的事务,一个事务在开始的时候只能看见已经提交的事务,也就是说一个事物在提交之前,对其他事务不可见。但是这种是无法防止在一个事务中重复读的,比如A事务第一次查询数据B=200,接着B事务修改B=300并提交,这样A事务第二次查询B=300,这种就是不可重复读。
RR(repeatable read)
可重复读,保证了同一个事务多次读取同样的结果是一致的。但是这种隔离级别仍然无法解决幻读的问题。幻读:当某个事务A在读取某个范围内的记录时,另一个事务B又在该范围内插入了新的记录,当A再次查询这个范围的记录,会出现幻行的情况。
Serializable(串行化)
这种是强行给每个事务加锁,达到事务完全串行的结果,并发性极差,一般不考虑
隔离级别 | 脏读可能 | 不可重复读 | 幻读 |
---|---|---|---|
RU | YES | YES | YES |
RC | NO | YES | YES |
RR | NO | NO | YES |
Serialize | NO | NO | NO |
TIPS :在任何隔离级别下,对数据的写都是会加锁的
四、隔离级别实战
先创建一个表 transaction_test作为测试使用:
CREATE TABLE `transaction_test` (
`id` int(11) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- RU(未提交读)
这里开启两个窗口作为两个session会话,并设置会RU级别:
然后用session A 插入一条数据
insert into transaction_test (id,name) values (1,'A');
在 session B中可以马上查看到插入的数据。
再演示一下写时锁行的情况
可以看到这时session B正处于锁定状态,因为session A还没有提交。
- RC(读已提交)
首先让sesseion A 插入一条记录。
insert into transaction_test (id,name) values (2,'A');
由于没有提交,所以B不会看到这条记录,一旦A提交后,由于隔离级别不能防止不可重复读,所以当A提交后,B再次查询会多出一条记录。
- RR(不可重复读)
不可重复读是mysql默认隔离级别,可以重复一下上一次的实验。A插入一条记录,就算A提交后,B查询的记录依然不会变。
TIPS:大家要是做实验的时候需要将 autocommit 设置为0,防止自动提交
第四种隔离方式这里就不再做实验测试了
感谢您的阅读