Spring事务传播、隔离等级

时间:2023-12-14 09:46:14

事务传播

PROPAGATION_REQUIRED

如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。

PROPAGATION_SUPPORTS

支持当前事务,如果当前没有事务,就以非事务方式执行。

PROPAGATION_MANDATORY

使用当前的事务,如果当前没有事务,就抛出异常。

PROPAGATION_REQUIRES_NEW

新建事务,如果当前存在事务,把当前事务挂起。

PROPAGATION_NOT_SUPPORTED

以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

PROPAGATION_NEVER

以非事务方式执行,如果当前存在事务,则抛出异常。

PROPAGATION_NESTED

如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与 PROPAGATION_REQUIRED 类似的操作。

事务隔离

数据库并发操作存在的异常情况:
  1. 更新丢失(Lost update)
两个事务都同时更新一行数据但是第二个事务却中途失败退出导致对数据两个修改都失效了这是系统没有执行任何锁操作因此并发事务并没有被隔离开来。
  2. 脏读取(Dirty Reads)
一个事务开始读取了某行数据但是另外一个事务已经更新了此数据但没有能够及时提交。这是相当危险很可能所有操作都被回滚。
  3. 不可重复读取(Non-repeatable Reads)
一个事务对同一行数据重复读取两次但是却得到了不同结果。例如在两次读取中途有另外一个事务对该行数据进行了修改并提交。
  4. 两次更新问题(Second lost updates problem)
无法重复读取特例,有两个并发事务同时读取同一行数据然后其中一个对它进行修改提交而另一个也进行了修改提交这就会造成第一次写操作失效。
  5. 幻读(Phantom Reads)
也称为幻像(幻影)。事务在操作过程中进行两次查询,第二次查询结果包含了第一次查询中未出现的数据(这里并不要求两次查询SQL语句相同)这是因为在两次查询过程中有另外一个事务插入数据造成的。
      为了避免上面出现几种情况在标准SQL规范中定义了4个事务隔离级别,不同隔离级别对事务处理不同 。
解决事务并发存在的问题
   1.未授权读取(Read Uncommitted)
也称未提交读。允许脏读取但不允许更新丢失,如果一个事务已经开始写数据,另外一个事务则不允许同时进行写操作,但允许读此行数据。该隔离级别可以通过
“排他写锁”实现。事务隔离的最低级别,仅可保证不读取物理损坏的数据。与READ COMMITTED
隔离级相反,它允许读取已经被其它用户修改但尚未提交确定的数据。
   2. 授权读取(Read Committed)
也称提交读。允许不可重复读取但不允许脏读取,读取数据的事务允许其他事务继续访问该行数据,但是未提交写事务将会禁止其他事务访问该行。这可以通过“瞬间共享读锁”和“排他写锁”实现,SQL
Server 默认的级别。在此隔离级下,SELECT 命令不会返回尚未提交(Committed) 的数据,也不能返回脏数据。
   3. 可重复读取(Repeatable Read)
禁止不可重复读取和脏读取。但是有时可能出现幻影数据,读取数据事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。这可以通过“共享读锁”和“排他写锁”实现,在此隔离级下,用SELECT
命令读取的数据在整个命令执行过程中不会被更改。此选项会影响系统的效能,非必要情况最好不用此隔离级。
   4. 串行(Serializable)
也称可串行读。提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作事务访问到。事务隔离的*别,事务之间完全隔离。如果事务在可串行读隔离级别上运行,则可以保证任何并发重叠事务均是串行的。
隔离级别     更新丢失 脏读取 重复读取 幻读
未授权读取     N            Y        
Y          Y
授权读取        N            N         Y          Y
可重复读取    
N            N         N         Y
串行               N            N        
N         N