数据库事务指的是一组数据操作,事务内的操作要么全部成功,要么全部失败,如果事务中有一个操作失败,就要回滚所有操作。

事务具有4个属性:原子性、一致性、隔离性、持久性,这四个属性通常称为ACID特性。

  • 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做;
  • 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态,一致性与原子性是密切相关的;
  • 隔离性(isolation):一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰;
  • 持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的,接下来的其他操作或故障不应该对其有任何影响。

事务隔离级别-SQL标准定义了四种隔离级别,分别是:

  • 读未提交:READ UNCOMMITTED
  • 读已提交:READ COMMITTED
  • 可重复读:REPEATABLE READ
  • 串行化:SERIALIZABLE

MySQL支持以上四种隔离级别,默认的隔离级别是REPEATABLE READ(查询SQL: select @@tx_isolation)。

在说这四种隔离级别之前,先说说事务中存在的三种关于读的问题:

  • 脏读:一个事务读取到另一个事务修改但未提交的数据;
  • 不可重复读:当一个事务执行SELECT操作时没有获得读锁或者SELECT操作执行完后马上释放了读锁,另一个事务对数据进行了更新,读到了不同的结果;
  • 幻读:是“不可重复读”的一种特殊场景,当事务1两次执行SELECT ... WHERE ...检索一定范围内数据的操作中间,事务2在这个表中INSERT/DELETE了一行新数据,这条新数据正好满足事务1的WHERE子句。

下面模拟介绍出现上面三种问题的场景,以下为数据库user表的结构和数据:

isolation data.png

脏读:当一个事务读取到另外一个事务修改但未提交的数据时,就可能发生脏读。

dirty read.png

事务1读取了事务2尚未提交的数据,如果事务2还有其他修改或者发生了回滚就会导致事务1读到了不正确的数据。

不可重复读:发生在当执行SELECT操作时没有获得读锁或者SELECT操作执行完后马上释放了读锁,另外一个事务对数据进行了更新,导致读到了不同的结果。

nonrepeatable read.png

事务2提交成功后,修改就对其他事务可见,所以事务1前后查询的结果不一致,这就是不可重复读。

幻读:

phantom read.png

在事务1两个相同查询之间事务2插入了新的数据,并且新数据也满足事务1查询中WHERE的条件,导致事务1第二次查询结果多了一条数据。

这四种隔离级别可能存在的以上问题:

isolation read.png

读未提交:最低的隔离级别,在该隔离级别下,所有事务都可以看到其他未提交事务的执行结果。

读已提交:大多数数据库的默认隔离级别(MySQL除外),一个事务只能看见其它已提交事务所做的改变。

可重复读:MySQL的默认隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。

串行化:最高的隔离级别,通过强制事务排序,使事务之间不可能相互冲突。

标签: MySQL, Database, Transaction

添加新评论