数据库有四大特性,分别为原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),就是我们一般所说的ACID,最近在研究分布式事务,才发现数据库的好多基础知识学的不够牢靠,所以先恶补一下这方面的知识。
1.原子性
所谓原子性就是一组不可分割的操作,要么全部成功,只要有一个失败,整个就都失败。这里所谓的成功一般就是指数据库的数据能够完全按照这一组操作完成,失败则是指失败后数据库的数据和这一组操作前的状态一致,不对数据库的数据产生任何影响。
2.一致性
一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,是指逻辑上的一致性。举个例子来说就是张三和李四分别有1000元、2000元,张三给李四转了500元,转账之前和转账之后张三和李四的总金额都是3000元,这里主要就是体现状态的一致性。
3.隔离性
隔离性一般是指多个事务之间相互独立,不影响彼此。这种场景一般是多并发访问。事务的隔离级别有四种分别为:Read uncommitted (读未提交)、Read committed (读已提交)、Repeatable read (可重复读)、Serializable (串行化),级别从高到底。要讨论这四种隔离级别,我们先来看看如果事务之间不进行隔离可能导致的几种情况:
(1)脏读
所谓脏读就是一个事务在修改数据库中每一条记录时,还没提交事务,另一个事务去读取这一条记录,那么当前面的事务最终没有提交事务就会导致修改不成功,而后面一个事物读取到的数据就可能不正确,从而导致脏读。
(2)不可重复读
不可重复读产生的原理就是一个事物在读取一条记录时,读到一条数据,此时另一个事务立马对这条记录进行修改,并且提交了事务,当前一个事务再次读取这条记录时就会发现与第一次读取的数据可能不同,从而出现了不可重复读。
(3)幻读
幻读又叫虚读,幻读是事务非独立执行时发生的一种现象。简单解释就是一个事务将一个表中某一字段全部改成另一个值,同时另一个事务有新增了一条记录,这是操作前面事务的人可能会发现数据库这个表中的数据并未按照他的事务全部修改,从而导致所谓的"不一致",即幻读。
不可重复读和幻读都是因为读了已经提交的另一个事务,而脏读则相反是因为读了另一个未提交的事务。不可重复读和幻读的区别在于,不可重复读的事务查询的是同一项数据,而幻读的事务针对的是一批数据整体。
因此上面四种隔离级别可以防止上述三种或者部分情况的产生,对应的关系如下:
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
② Repeatable read (可重复读):可避免脏读、不可重复读的发生。
③ Read committed (读已提交):可避免脏读的发生。
④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。
级别越高,能防范更多的情况发生,但是效率也会越低。串行化就类似于java中的锁的概念,一个事物在操作时,其它事务阻塞在那,直到锁释放。
读未提交级别:事务在读取数据时不会加锁,在写数据时会加行级共享锁,也就说事务A在修改一个数据时,不管A事务有没有提交,B事务都可以读到未提交的A修改的数据,但是不能写同一条记录的数据;当A也是读取数据,不影响B读取数据,所以这种级别不能预防脏读、不可重复读、幻读。
读已提交:一个事物在修改数据过程中,只要事务没提交,其它事务就不能读该数据。在事务提交后,其它事务读的时候也会加行级共享锁,一旦读完数据,锁立马释放;而写数据的瞬间会加行级排它锁,直到事务结束。这种情况下就避免了脏读,但是不可预防不可重复读。
可重复读:在读已提交的基础上更加严格控制,在读的时候加锁,直到事务结束,才释放锁,这样就不会导致不可重复读,但是避免不了幻读的现象,因为幻读是增加记录,并不是更改原先的记录。
串行化:串行一般是给表加锁,直到事务结束才释放,这样一来就可以避免所有情况。
参考链接:
https://www.cnblogs.com/fjdingsd/p/5273008.html
https://www.jianshu.com/p/2c30d1fe5c4e