数据库之事务详解

什么是事务

事务是访问数据库的一个或多个操作的组合,事务执行完之后可以使数据库从一种状态变为另外一种状态。

事务的四个特性

1、原子性

原子性指的是事务中的操作要么全部执行,要么全部不执行。这意味着如果事务正确执行,则数据库从一种状态成功地变为了另外一种状态;如果事务中的某个操作未正确执行,则已正确执行的其他操作需要对数据库进行回滚,使数据库恢复到该事务执行之前的状态。

2、一致性

一致性指的是使数据库从一种状态正确地变为另外一种状态,这里的关键词是“正确地”,换句话说是,一个事务执行之前和执行之后都必须处于一致性状态。举个栗子,如果A给B汇款100元,则一致性就代表着A账户减少了100元,B账户增加了100元,但是他们的账户总和不会改变。

3、隔离性

隔离性指的是各个事务之间的执行不能相互影响,比如两个事务并发地对某个数据进行操作,则A事务在对该数据进行操作时,B事务不能对其操作。

4、持久性

持久性指的是事务一旦被提交了,该事务对数据库的数据改变就是永久性的,即时这时数据库系统遇到了故障,事务的处理结果也会保存下来。

并发中的事务引起的问题

在并发操作中,如果不考虑事务的隔离性,会引起一系列的问题,如脏读、不可重复读、幻读等。

1、脏读

脏读是指一个事务在处理过程中,读到了另一个未提交的事务中的数据。举个栗子,A向B转账100元这个事务需要两条SQL语句,首先给B的账户添加100元,A的账户减少100元,假如执行完第一条SQL语句后发生了阻塞,此时B对其账户进行查询操作,发现其账户已经多出了100元,但是此时事务阻塞结束,执行第二条语句时,发生了问题,这时数据库就需要回滚数据,返回事务执行之前的状态,那么B的账户会再减少100元,那么之前B查询到的多出100元的结果就是脏读。

2、不可重复读

不可重复读是指在一个事务中读取了两次同一个数据,但是结果不一致,这是因为这个事务两次查询操作之间的时候被另外一个事务修改了数据。举个栗子,事务A进行了两次查询账户的操作,事务B对账户进行了修改操作,改为减少100元,那么在A事务第一次查询账户后如果发生阻塞,B事务此时开启并执行,那么再执行A事务的第二次操作时,就会发现账户少了100元,这就是发生了不可重复读。

不可重复读与脏读的区别是,脏读是A事务读取了B事务未提交的数据,不可重复读是读取了B已提交的数据。

3、幻读

幻读是指在一个事务的操作后发现了未被操作的数据。什么意思呢,还是举个栗子吧,比如A事务想把所有人的账户数据全部改为100元,但此时事务B对该表进行了一个插入操作,增加了一个人Q和账户200元,也就是表增加了一行,那么A事务执行完毕后,会发现有一个人的账户未被修改过,这就是发生了幻读。

幻读和不可重复读都是读取了另一个已经提交的事务,不可重复读的重点在于update和delete,而幻读的重点是insert。

事务隔离级别

事务隔离级别是指的是事务四个特性之一的隔离性设置的不同级别,事务的隔离级别越高,由于并发导致的问题就会越少,但同时性能消耗也就更高。如果在两者之间做一个衡量的话,可以对不同的数据选择不同的隔离级别,MySQL支持四种隔离级别,默认为可重复读级别。

1、读未提交(READ_UNCOMMITTED)

可以读到没有被提交的数据,隔离的最低级别,不能防止脏读、不可重复读、幻读。

2、读已提交(READ_COMMITED)

读已提交是为了解决脏读的问题,它可以保证读不到未被提交的数据,这样的话就防止了脏读。

3、可重复读(REPEATABLE_READ)

重复读是为了解决不可重复读的问题,将要查询的数据加锁,这样其他事务就不会再对这些数据进行修改或删除操作,就可以实现可重复读了。但是这种对数据加锁的方式没办法对其他事务的插入操作有效,所以不能防止幻读。

4、串行化(SERLALIZABLE)

这个数据库隔离的最高级别,可以避免脏读、不可重复读、幻读,但这个级别的隔离也会降低数据库的增删改查性能。

你可能感兴趣的:(数据库)