以下文章来源于何先振,责编小何

上节我们主要讲解了事务,那么事务都有哪些特性呢?
第一个就是事务的原子性(Atomicity),一个事务是一个不可分割的工作单位,事务的操作要么都发生,要么都不发生。
第二个就是事务的一致性(Consistency),一个事务在没执行之前数据是一个状态,执行完之后数据是另外一个状态。
但是不管是什么状态一定是合法的状态。这里说的合法就是合理,不脱离现实生活。
例如,上讲说的转账,要么转成功,要么转失败。不管成功失败,两个用户加起来的总金额是不会变的。
第三个就是隔离性(lsolation),一个事务的执行不能被其它事务干扰,事务之间不能互相干扰。如何保证事务之间互不干扰呢?
这里就涉及到数据库事务的并发问题,后面我们会讲。
第四个就是持久性(Durability),就是一个事务一旦被提交了,它对数据库中的数据改变就是永久性的,没提交之前可以回滚,提交后就不能回滚了。
要想回滚,可以重新开启一个事务把数据改回来。
对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题。
例如:两个事务T1和T2,都同时读user表中张三这条记录中的数据。

T1事务要给张三加100元,加完之后张三的账户就是1000元了。
但是由于T2和T1是同时发生,T1还没来得及提交事务。
T2就读取到了T1修改后的数据,这就是脏读。
为啥会叫脏读呢?因为T1事务还没提交,也就是随时可以回滚。一回滚又变回原来的值,就会导致T2事务读取的值不准确。
还有就是T2读到的是900,结果T1修改成1000并且提交了。
那么T2事务还没执行完,再读张三的账户金额变成了1000元。
一个事务读两次,每次的值都不一样,这就出现了不可重复读的并发问题。
还有就是幻读的并发问题,T1从一个表中读出来1条数据。
结果T2在表中插入了2条数据。T1再读的时候就变成了3条数据,多出了几行。
最不能接受的就是脏写,T1事务将张三的金额修改为1000还未提交时。
事务T2就读取了T1修改后的1000元,基于1000元再增加了100元变成了1100元并提交了。
后面T1又回滚了,变成了900元,T2的操作被丢失了。
为了避免脏写、脏读、不可重复读、幻读这几种并发问题,数据库规定了多种事务的隔离级别,来保证数据库事务的隔离性。
不同的隔离级别对应着不同的干扰程度,隔离级别越高,数据一致性越好,但是并发性越弱。
数据库提供的四种隔离级别:
读未提交的数据:允许事务读取未被其它事务提交的变更。所以脏读、不可重复读和幻读的问题都会出现。
读已提交的数据:只允许事务读取已经被其它事务提交的变更。可以避免脏读,但不可重复读和幻读问题还是会出现。
可重复读:确保事务可以多次从一个字段中读取相同的值。在这个事务持续期间,禁止其它事务对这个字段进行更新。可以避免脏读和不可重复读,但是幻读的问题还是存在。
串行化:确保事务可以从一个表中读相同的行,在这个事务执行期间,禁止其它事务对该表执行插入、更新、删除操作。所有并发问题都可以解决,但是性能十分低下。
上面说的这些隔离级别,都可以解决脏写问题。
不同的数据库会支持不同的隔离级别:
Oracle支持2种事务隔离级别:读已提交、串行化。Oracle默认的事务隔离级别是读已提交。
MySQL支持4种事务隔离级别:MySQL默认的事务隔离级别是可重复读。
下讲我们就来验证下数据库的隔离级别。

扫码进微信答疑群





