最近去一家公司面试被问到数据库的事物特性和隔离级别,回答的非常戳,是时候应该复习一波的时候!
一、数据库事物ACID特性
数据库事物:
是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,要么完全地不执行。一个逻辑工作单元要成为事务,必须满足所谓的ACID(原子性、一致性、隔离性和持久性)属性。事务是数据库运行中的逻辑工作单位,由DBMS中的事务管理子系统负责事务的处理。(摘自百度百科)
原子性(Atomicity):
一个事物是一个不可分割的最小工作单元,整个事物中的操作结果要么全部成功提交至数据库,要么全部失败回滚,对于一个事物来说,不可能只其中一半部分操作成功保存至数据库,一半部分操作失败。
一致性(Consistency):
一致性是指事物必须保证数据库总是从一个一致性的状态转换到另一个一致性的状态。一致性容易和持久性混淆,一致性举个栗子:假设用户A和用户B两者的钱工是10000,那么不管A和B之间如何转账,事物结束后两个用户的钱总和还是10000,这就是事物的一致性。
隔离性(Isolation):
隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。
持久性(Durability):
持久性是指一个事物一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便在数据库系统遇到故障的情况下也不嗯呢该丢失提交后的数据。
二、事物的隔离性级别
1、隔离级别解决的问题:
脏读:指一个事物处理过程中读取了另一个事物中未提交的的数据。
不可重复读:指在对于一个数据库中的数据,一个事物范围内多次查询却返回了不同的数据值,这是由于在查询间隔中被另一个事物修改了数据并提交了。不可重复读和脏读的区别是,脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。
幻读:幻读是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改 为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。
【幻读】和【不可重复读】都是读取了另一条已经提交的事务(这点只有脏读不同)。
【不可重复读】查询的都是【同一个数据项】(ps:delete 或update 同一个数据项),
【幻读】针对的是一批数据整体(比如数据的个数)。(ps:insert操作)
2、隔离性的四个级别:
READ UNCOMMITTED(读未提交)
在READ UNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read)。这个级别会导致很多问题,从性能上来说,READ UNCOMMITTED不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。
READ COMMITTED(读已提交)
大多数数据库系统的默认隔离级别都是READ COMMTTED(但MySQL不是)。READ COMMITTED满足前面提到的隔离性的简单定义:一个事务开始时,只能”看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候叫做不可重复读(nonrepeatble read),因为两次执行同样的查询,可能会得到不一样的结果。
REPEATABLE READ(可重复读)
REPEATABLE READ解决了脏读的问题。该隔离级别保证了在同一个事务中多次读取同样记录结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom Read)的问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。
SERIALIZABLE(串行化)
SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读取每一行数据都加锁,所以可能导致大量的超时和锁争用问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。
隔离级别的总结
打 √ 说明该隔离级别还存在这种情况,打 × 代表该隔离级别已经解决了这种情况:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(Read uncommitted) | √ | √ | √ |
读已提交(Read committed) | × | √ | √ |
可重复读(Repeatable read) | × | × | √ |
可串行化(Serializable) | × | × | × |
参考文档:
https://www.2cto.com/database/201710/691297.html
https://blog.youkuaiyun.com/zh521zh/article/details/69400053