数据库事务

显式事务与隐式事务

  • 对于单条SQL语句,数据库系统自动将其作为一个事务执行,这种事务被称为隐式事务
  • 手动把多条SQL语句作为一个事务执行,使用BEGIN开启一个事务,使用COMMIT提交一个事务,这种事务被称为显式事务

事务的四个特性

原子性

将所有SQL作为原子工作单元执行,要么全部执行,要么全部不执行

一致性

事务完成后,数据状态的改变是一致的,结果是完整的

隔离性

事务与事务试图操纵同样数据时,他们之间是互相隔离的
如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离

持久性

事务提交后,数据结果会永久保存,也即完成数据持久化,即使断电数据也已经保存

隔离级别与数据读取问题

脏读(Read Uncommitted)

在这种隔离级别下,一个事务会读到另一个事务更新后但未提交的数据,如果另一个事务回滚,那么当前事务读到的数据就是脏数据

例如:
A事务修改了一条数据,但是未提交修改,此时A事务对数据的修改对其他事务是可见的,B事务中能够读取A事务未提交的修改。一旦A事务回滚,B事务中读取的就是不正确的数据

不可重复读(Read Committed)

一个事务先后采用相同的策略读取数据,发现两次读取的数据不一致

详细解释:在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致

例如:

  1. A事务中读取一行数据
  2. B事务中修改了该行数据
  3. A事务中再次读取该行数据将得到不同的结果

幻读(Repeatable Read)

一个事务按照相同的条件查询数据,却发现其他事务插入了满足其查询条件的数据

详细解释:在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了

例如:

  1. A事务中通过WHERE条件读取若干行
  2. B事务中插入了符合条件的若干条数据
  3. A事务中通过相同的条件再次读取数据时将会读取到B事务中插入的数据。

此外隔离级别还有Serializable,最严格的隔离级别,但效率最低

参考

  1. 事务
  2. MyBatis 3源码深度解析/江荣波