事务系列(一):事务四大特性与隔离级别

数据库中事务有四大特性(简称ACID),如下:

1. 原子性(atomicity)
原子性指事务包含的所有操作要么全部成功,要么全部失败回滚。
2. 一致性(consistency)
一致性指一个事务执行之前和执行之后数据库都必须处于一致性状态。
加入数据库的状态满足所有完整性约束,就说数据库是一致的。
例如完整性约束a+b=10,如果一个事务改变了a,那么b也应随之改变。
3. 隔离性(isolation)
隔离性指当并发的事务是相互隔离的,即一个事务内部的操作及正在操作的数据必须封锁起来,不能被其他企图修改的事务看到。
隔离性可以通过不一样的配置达到不一样的隔离级别。
4. 持久性(durability)
持久性指对于任意已提交事务,系统必须保证该事务对数据库的改变不被丢失,即使数据库出现故障。

针对隔离性,可以通过修改配置使用不同的隔离级别,在介绍隔离级别之前,我们先来看看如果事务没有隔离性的属性,会出现什么问题。

问题一:脏读
脏读指一个事务读取了另一个未提交事务的数据。
当一个事务正在多次修改某次数据,而在这个事务中多次修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。例如A向B转账,如果B在只执行了第一条sql的时候查看账户,就会发现100块钱已经到账,但如果最后事务没有提交,整个事务回滚,最后B会发现钱并没有到账,如果B在刚才发现到账时取钱,就会导致最后B多出100快钱。

update account set money=money+100 where name=’B’;  (此时A通知B)
update account set money=money - 100 where name=’A’;

问题二:不可重复读
不可重复读指对于数据库中的某个数据,一个事务在事务范围内多次查询该数据,查询出来的结果不一致,这是由于另外的已提交事务修改了该数据。
例如事务A在读取某个数据,而事务B立马修改了该数据,事务A再次读取的时候就会读到修改后的数据。
不可重复读与脏读的区别是:脏读是读另一事务未提交的,不可重复读读的是另一事务已提交的。
问题三:幻读
幻读指在一个事务中,出现读取操作后,在另一个事务中出现了插入操作,导致返回的结果集发生了变化,出现了新插入的记录的情况。
事务A根据条件第一次查询得到N条数据,但此时事务B更改或者增加了M条符合事务A查询的条件的数据。这样当事务A再次查询的时候发现会有N + M条数据,产生了幻读。
幻读与不可重复读都是读取另一事务已经提交的数据,区别是不可重复读查询的是同一个数据项,而幻读针对的是一批数据整体(例如数据个数)。幻读是可重复读隔离级别下的一种现象,与不可重复读类似,但主要关注的是插入操作。

现在来看看mysql给我们提供的四种隔离级别

隔离级别 脏读 不可重复读 幻读
串行化(serializable) × × ×
可重复读(repeatable read) × ×
读已提交(read committed) ×
读未提交(read uncommitted)

幻读问题解决:
幻读的解决方案包括:提升事务的隔离级别、使用锁机制、使用MVCC多版本并发控制技术。

快照读:通过mvcc,RR的隔离级别解决了幻读问题,因为每次使用的都是同一个readview。
当前读:通过next-key锁(行锁+gap锁),RR隔离级别并不能解决幻读问题。

隔离级别最高的是S级别,最低的是RU级别,但是隔离级别越高,执行效率就越低,像S级别,就是以锁表的方式,使得其他线程只能在锁外等待,所以平时使用时选用何种级别可根据实际情况,mysql默认的是RR,oracle默认的是RC。
在数据库中,可通过select @@isolation;查询当前的数据库隔离级别。在代码中,可通过修改数据库连接事务配置,更改当前连接的事务隔离级别。

参考:MVCC详解,深入浅出简单易懂

你可能感兴趣的:(mysql,mysql)