哪怕真理无穷,进一步有一步的欢喜
No.1
说在前面
我们在平时开发过程中,经常接触到数据库比如MySQL、Oracle。那么避免不了的话题就是数据库的事务。很多时候,我们看似理解了事务,但是实际上让我们简洁清晰描述出来还是比较吃力。这篇文章就用大白话带着大家一起聊聊事务的基础知识,让我们有事务有一个清晰的认知
No.2
什么是事务
事务(Transaction),一般是指要做的或所做的事情。在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元。
——《百度百科》
事务的具体概念,我们不去深究,大家有个了解即可。
No.3
事务的特性
事务有四大特性,简称ACID。即原子性(Atom)、一致性(Consistency)、隔离性(Isolate)、持久性(Durability)
事务的原子性
原子性,说的是在同一个事务下的所有操作,要么全部执行成功,要么执行全部失败。比如事务A有1、2、3、4四个步骤,那么如果操作1、2执行成功,但是操作3执行失败了,这时候,事务A就会执行失败。
事务的一致性
一致性,说的是在事务的执行前后,数据都是准确的。不会说,存在执行事务A之前数据是准确的,执行事务A后对数据进行了修改操作,但是事务A执行成功了而数据却得不到修改。
事务的隔离性
事务的隔离性,说的是不同事务之间的操作互相独立。不能出现事务A的执行影响到了事务B的执行。
事务的持久性
持久性,说的是在事务执行完成后,对数据的修改结果是永久的,不会出现数据修改完后,又自动恢复回来。
画外音:以后对于涉及到事务的东西,我们都应该从这四个方面来思考是如何满足这些特性的。比如MySQL的事务。
No.4
事务隔离级别
事务的隔离级别,讲的是不同事务之间操作结果是怎样进行隔离的,达到不影响其它事务的操作。包括:读未提交、读提交、可重复读、串行化
读未提交(Read Uncommitted)
读未提交(也可以说未提交读),就是一个事务会读取到其它事务未提交的操作结果。
下面举个例子,如图,假设表里只有一条数据M,M=2。
现有事务A、B都有一系列操作。假设事务B的隔离级别是读未提交,那么如果在事务A开启后,执行完步骤一、二,接下来事务B开启,在事务A未执行步骤三之前,事务B执行了步骤1,那么此时,事务B读取到的M值就是2了,导致了事务B脏读了事务A的修改数据。
接着,如果事务A继续执行步骤三,插入一条数据,N=1。这时候,刚好事务B执行了步骤二,那么事务B读取到的数据就是M=3(事务A修改的结果),N=1(事务A插入一条数据)。如果接着事务A因为步骤四操作异常导致事务回滚,对M的修改回滚,插入N也回滚,这时候事务B接着执行步骤三,就会发现M=2,N不见了。对于事务B的步骤二和步骤三,M=3变成M=2,叫做不可重复读。对于新增了数据N,后来步骤三执行完后N不见了,叫做幻读。
下面,给大家说一下脏读、不可重复读,幻读的概念:
-
脏读:一个事务读取了其它事务对已经存在数据的修改结果叫做脏读
-
不可重复读:一个事务两次对同一个数据读取的结果不一样
-
幻读:幻读诗针对新增或者删除数据导致数据数量变化来说的,也就是说一个事务读取了其它事务新增的未提交的数据,会出现两次读取结果不一致,第一次读取有这天新增数据,但是第二次读取就没有这条数据了
从上面的分析中,读未提交事务隔离级别,会出现脏读、不可重复读、幻读问题。
读已提交(Read Committed)
读已提交(也可以说提交读),就是一个事务读取到了另外一个事务提交的结果。
读已提交,可以确保事务不会脏读其它事务未提交的数据,但是还是会出现不可重读、幻读的问题。下面用图解释:
事务B的事务隔离级别是读提交。事务A开启,执行步骤一、二,接着事务B开启,执行事步骤一,读取不到事务A的修改结果。接着事务A执行步骤三,新增一条数据N,事务B执行步骤二,读取不到事务A提交的结果。再继续下去,事务A提交事务,事务B执行步骤三,读取到M=3,N=1,多出来了N=1,也就是第一次读取到的M=2,现在是M=3,出现了不可重复读问题。第一次只有一条数据,但是第二次出现了两条数据,出现了幻读问题。当然,有一种情况,如果事务A不是新增N,而是删除M,这样事务B读取不到了任何值,这时候算不算幻读呢?其实算的。本质上,它们都是数据数量的变化。
所以。读已提交解决了脏读问题,但是会有不可重复读、幻读问题。
可重复读(Read Repeatable)
可重复读,就是在一个事务内,对同一个数据的所有读操作,读取到的结果是一样的。但是,如果有其它事务对数据进行新增或者删除并提交成功,那么可重复读事务还是会读取到该值的。如图:
可重复读解决了脏读、不可重复读问题,但会出现幻读问题。
串行化(Serializable)
串行话,就是一个事务的执行需要等待正在执行的事务执行完成后才可以进行执行。这样可以避免出现脏读、不可重复读和幻读的问题。如图:
综上所属,事务隔离级别以及对应可能出现的问题如下:
- 读已提交:脏读、不可重复读、幻读
- 读已提交:不可重复读、幻读
- 可重复读:幻读
-
串行化:没有上述问题
No.5
事务使用场景
在我们需要强调一系列操作的原子性和操作结果影响范围的时候,我们就需要使用事务。比如,在数据库系统中,关系型数据库都有事务这个概念,用来保证数据库操作的正确性。对于我们软件开发来说,事务我们更多的是讨论数据库的事务。