JDBC的事务和隔离级别

这里简单写一下我对JDBC的事务和隔离级别的理解。

名词解释

事务

数据库事务是DBMS执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
一个事务一定是具有原子性(atomic)一致性(consistency)隔离性(isolation)持久性(durability),即ACID
一个事务会包含一个或多个数据操作语句(data-manipulation statements)和查询语句。
通常来说,事务会依照如下的流程执行:

  1. 开始一个事务

  2. 执行一系列操作或查询语句

  3. 如果没有发生错误,则提交这个事务,并将其结束

  4. 如果发生了错误,则回滚这个事务,并将其结束。

ACID

  • Atomic

原子性,即一个事务内的所有操作都被作为一个整体看待,要么全部成功,要么全部失败

  • Consistency

一致性,即事务中有操作失败时,这个事务所更改的数据都必须回滚至操作前的状态。

  • Isolation

隔离性,即事务所查看到的数据,要么是一个事务提交前的状态,要么是一个事务提交后的状态,而不可能是事务在执行中的状态。

  • Durability

持久性,即事务对系统的影响是永久的。

读现象

  • 脏读

当一个事务允许读取另一个事务修改但尚未提交的数据时,就有可能发生脏读。

  • 不可重复读

在一次事务中,对一行数据的两次读取获得了不同的结果。
该现象发生于在执行SELECT时没有获得读锁,或者在读取完毕后立刻释放了读锁。

  • 幻读

在事务执行过程中,两个完全一样的查询得到了不同的结果集,即是幻读。它是不可重复读的一个特殊场景。
当事务1在执行两次SELECT ... WHERE操作中间,事务2在这个表中生成了一行新数据,而这条新数据正好满足事务1的WHERE条件,导致事务1的两次查询得到了不同的结果集。

隔离级别

NONE

NONE是一个特殊的级别,代表JDBC驱动不支持事务。

未提交读(READ UNCOMMITED)

这个是最低的隔离级别。
这个隔离级别允许事务读取到其他事务尚未提交(commit)的数据,即允许脏读。

提交读(READ COMMITED)

这个隔离级别中,DBMS需要选定对象的写锁一直保持到事务结束,但是读锁会在SELECT操作完成后马上释放,所以有可能会发生“不可重复读”。

可重复读(REPEATABLE READ)

在这个隔离级别下,DBMS需要对选定对象的读锁和写锁一直保持到事务结束,但是不要求范围锁,所以有可能发生幻读。

可串行化(SERIALIZABLE)

这是最高的隔离级别。
在这个隔离级别下,要求DBMS在选定对象上的读锁和写锁一直保持到事务结束,如果使用了WHERE来描述范围时,则应当获取一个范围锁。这个隔离级别可以防止幻读。

隔离级别与读现象

隔离级别脏读不可重复读幻读
未提交读可能发生可能发生可能发生
提交读不会发生可能发生可能发生
可重复读不会发生不会发生可能发生
可串行化不会发生不会发生不会发生

隔离级别与锁持续时间

隔离级别写操作读操作范围操作
未提交读当前语句执行完毕当前语句执行完毕当前语句执行完毕
提交读当前事务提交当前语句执行完毕当前语句执行完毕
可重复读当前事务提交当前事务提交当前语句执行完毕
可串行化当前事务提交当前事务提交当前事务提交