事物的特性,隔离级别

一、事物

一个事务是一个完整的业务逻辑单元,不能再分,要么全部执行成功,要么全部失败。

比如:A给B转账100元,A的银行卡就会少100元,B的银行卡就会多100元,整个 过程要么全部执行成功,要么全部失败。

二、事务的四大特性

A:原子性。事务是最小的业务逻辑单元。

B:一致性。一个事务必须保证多条DML语句同时成功或失败。

C:隔离性。两个事务之间具有隔离性(隔离级别问题)

D:持久性。最终的数据必须持久化到硬盘中,一个事务才算最终完成。

三、数据库中事务的四种隔离级别

1)read_uncommitted(读未提交

可读取未提交事务的操作数据,最低的隔离级别,一般都没有用的。这种情况会出现脏读。
如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据。
解决了更新丢失,但还是可能会出现脏读

(2)read_committed(读已提交

一个事务等另一个事务提交之后才可进行读取,解决了脏读问题,但会出现不可重复读
如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
解决了更新丢失和脏读问题

(3)repeatable_read(可重复读

读取事务开启的时候不能对数据进行修改,解决了不可重复读问题,但是存在幻读问题;
可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。
解决了更新丢失、脏读、不可重复读、但是还会出现幻读

(4)serializable(序列化):是最高的事务隔离级别,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用;
提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用
解决了更新丢失、脏读、不可重复读、幻读(虚读)

四、如何合理选择隔离级别

可以根据需求设置数据库的事务的级别。“读未提交”一般没用,“读已提交”解决脏读但存在不可重复读,“可重复读”解决了脏读和不可重复读,但会出现幻读。串行化读,都可以解决,但是需要注意的是事务级别越高性能越低。

MySQL默认可重复读。

Oracle默认读已提交。

五、脏读、幻读、不可重复读

1、脏读

出现原因:一个事务读取到了缓存中另一个事务未提交的脏数据。

说明:当事务B对data进行了修改但是未提交事务,此时事务A对data进行读取,并使用事务B修改的数据做业务处理。

2、幻读

出现原因:一个事务在读取数据时,另一个事务插入了数据,导致上个事务第二次读取数据时,数据不一致。

说明:data 表有一条数据,事务A对data进行读取, 事务B对data进行数据新增 ,此时事务A读取只有一条数据,而最后实际data是有两条数据,就好象发生了幻觉一样情况成为幻读;

3、不可重复读

出现原因:读取数据的同时可以进行修改;

说明:事务A、事务B同时对data进行访问,事务A对data进行读取,事务B对data进行修改,当事务A第一次对data进行读取完后事务B提交,此时当事务A第二次读取该数据时的数据就与第一次读取的数据不同,这种情况称为不可重复读;

***说明:幻读和不可重复读都是在同一个事务中多次读取了其他事务已经提交的事务的数据导致每次读取的数据不一致,所不同的是不可重复读读取的是同一条数据,而幻读针对的是一批数据整体的统计(比如数据的个数)

事物的特性,隔离级别
以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低,像Serializeble这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况来,在MYSQL数据库中默认的隔离级别是Repeatable read(可重复读)。

在MYSQL数据库中,支持上面四种隔离级别,默认的为Repeatable read(可重复读);而在Oracle数据库中,只支持Serializeble(串行化)级别和Read committed(读已提交)这两种级别,其中默认的为Read committed级别

文章内容来自:
基础篇:https://zhuanlan.zhihu.com/p/112164279
升级篇:https://blog.csdn.net/zhouym_/article/details/90381606