Skip to content

6. 事务

把多条语句作为一个整体进行操作的功能,被称为数据库事务

1. ACID特性

  • A:atomicity,原子性,将所有SQL作为原子工作单元执行,要么全部执行,要么全部不执行;
  • C:consistency,一致性,事务完成后,所有数据的状态都是一致的,即A账户只要减去了100,B账户则必定加上了100;
  • I:isolation,隔离性,如果有多个事务并发执行,每个事务作出的修改必须与其他事务隔离;
  • D:durability,持久性,即事务完成后,对数据库数据的修改被持久化存储。

对于单条SQL语句,数据库系统自动将其作为一个事务执行,这种事务被称为隐式事务

要手动把多条SQL语句作为一个事务执行,使用BEGIN开启一个事务,使用COMMIT提交一个事务,这种事务被称为显式事务

BEGIN;
<SQL>;
COMMIT;

有些时候,我们希望主动让事务失败,这时,可以用ROLLBACK回滚事务,整个事务会失败:

BEGIN;
<SQL>;
ROLLBACK;

2. 隔离级别

Transaction Isolation Levels

针对隔离性,SQL标准定义了4种隔离级别:

Isolation Level 脏读(Dirty Read) 不可重复读(Non Repeatable Read) 幻读(Phantom Read)
Read Uncommitted May May May
Read Committed - May May
Repeatable Read - - May
Serializable - - -

2.1 Read Uncommitted

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

2.2 Read Committed

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

所以正确做法就是只读一次,不要再去读了。

2.3 Repeatable Read

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

幻读出现的原因:因为Repeatable Read下在同一个事务内的查询都是与事务开始时刻一致,所以在B事务过程中是不会读到期间A中insert的值的。

2.4 Serializable

所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。但是效率会大大下降。

2.5 默认隔离级别

在MySQL中,如果使用InnoDB,默认的隔离级别是Repeatable Read。