官方文档

事务

执行SQL的事务流程

image.png

Spring 声明式事务

image.png

数据库事务

数据库事务具有以下4个基本特征,也就是著名的ACID。

Atomic(原子性)

事务中包含的操作被看作一个整体的业务单元,这个业务单元中的操作要么全部成功,要么全部失败,不会出现部分失败、部分成功的场景。

Consistency(一致性)

事务在完成时,必须使所有的数据都保持一致状态,在数据库中所有的修改都基于事务,保证了数据的完整性。

Isolation(隔离性)

这是我们讨论的核心内容,正如上述,可能多个应用程序线程同时访问同一数据,这样数据库同样的数据就会在各个不同的事务中被访问,这样会产生丢失更新。为了压制丢失更新的产生,数据库定义了隔离级别的概念,通过它的选择,可以在不同程度上压制丢失更新的发生。因为互联网的应用常常面对高并发的场景,所以隔离性是需要掌握的重点内容。

Durability(持久性)

事务结束后,所有的数据会固化到一个地方,如保存到磁盘当中,即使断电重启后也可以提供给应用程序访问。

隔离级别

数据库标准

未提交读、读写提交、可重复读和串行化

未提交读

未提交读(read uncommitted)是最低的隔离级别,其含义是允许一个事务读取另外一个事务没有提交的数据。(脏读)

读写提交

读写提交(read committed)隔离级别,是指一个事务只能读取另外一个事务已经提交的数据,不能读取未提交的数据。(不可重复读)

可重复读

可重复读的目标是克服读写提交中出现的不可重复读的现象,因为在读写提交的时候,可能出现一些值的变化,影响当前事务的执行,这个时候数据库提出了可重复读的隔离级别。这样就能够克服不可重复读的现象

串行化

串行化(Serializable)是数据库最高的隔离级别,它会要求所有的SQL都会按照顺序执行,这样就可以克服上述隔离级别出现的各种问题,所以它能够完全保证数据的一致性。

image.png

  1. /*
  2. * Copyright 2002-2019 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * https://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.transaction.annotation;
  17. import org.springframework.transaction.TransactionDefinition;
  18. /**
  19. * Enumeration that represents transaction propagation behaviors for use
  20. * with the {@link Transactional} annotation, corresponding to the
  21. * {@link TransactionDefinition} interface.
  22. *
  23. * @author Colin Sampaleanu
  24. * @author Juergen Hoeller
  25. * @since 1.2
  26. */
  27. public enum Propagation {
  28. /**
  29. * 需要事务,它是默认传播行为,如果当前存在事务,就沿用当前事务,
  30. * 否则新建一个事务运行子方法
  31. *
  32. * Support a current transaction, create a new one if none exists.
  33. * Analogous to EJB transaction attribute of the same name.
  34. * <p>This is the default setting of a transaction annotation.
  35. */
  36. REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),
  37. /**
  38. * 支持事务,如果当前存在事务,就沿用当前事务;如果不存在,
  39. * 则继续采用无事务的方式运行子方法
  40. *
  41. * Support a current transaction, execute non-transactionally if none exists.
  42. * Analogous to EJB transaction attribute of the same name.
  43. * <p>Note: For transaction managers with transaction synchronization,
  44. * {@code SUPPORTS} is slightly different from no transaction at all,
  45. * as it defines a transaction scope that synchronization will apply for.
  46. * As a consequence, the same resources (JDBC Connection, Hibernate Session, etc)
  47. * will be shared for the entire specified scope. Note that this depends on
  48. * the actual synchronization configuration of the transaction manager.
  49. * @see org.springframework.transaction.support.AbstractPlatformTransactionManager#setTransactionSynchronization
  50. */
  51. SUPPORTS(TransactionDefinition.PROPAGATION_SUPPORTS),
  52. /**
  53. * 必须使用事务,如果当前没有事务,则会抛出异常,
  54. * 如果存在当前事务,就沿用当前事务
  55. *
  56. * Support a current transaction, throw an exception if none exists.
  57. * Analogous to EJB transaction attribute of the same name.
  58. */
  59. MANDATORY(TransactionDefinition.PROPAGATION_MANDATORY),
  60. /**
  61. * 无论当前事务是否存在,都会创建新事务运行方法,
  62. * 这样新事物就可以拥有新的锁和隔离级别等特性,与当前事务相互独立
  63. *
  64. * Create a new transaction, and suspend the current transaction if one exists.
  65. * Analogous to the EJB transaction attribute of the same name.
  66. * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
  67. * on all transaction managers. This in particular applies to
  68. * {@link org.springframework.transaction.jta.JtaTransactionManager},
  69. * which requires the {@code javax.transaction.TransactionManager} to be
  70. * made available to it (which is server-specific in standard Java EE).
  71. * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
  72. */
  73. REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),
  74. /**
  75. * 不支持事务,当前存在事务时,将挂起事务,运行方法
  76. *
  77. * Execute non-transactionally, suspend the current transaction if one exists.
  78. * Analogous to EJB transaction attribute of the same name.
  79. * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
  80. * on all transaction managers. This in particular applies to
  81. * {@link org.springframework.transaction.jta.JtaTransactionManager},
  82. * which requires the {@code javax.transaction.TransactionManager} to be
  83. * made available to it (which is server-specific in standard Java EE).
  84. * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
  85. */
  86. NOT_SUPPORTED(TransactionDefinition.PROPAGATION_NOT_SUPPORTED),
  87. /**
  88. * 不支持事务,如果当前方法存在事务,则抛出异常,否则继续使用无事务机制运行
  89. *
  90. * Execute non-transactionally, throw an exception if a transaction exists.
  91. * Analogous to EJB transaction attribute of the same name.
  92. */
  93. NEVER(TransactionDefinition.PROPAGATION_NEVER),
  94. /**
  95. * 在当前方法调用字方法时,如果子方法发生异常
  96. * 只回滚字方法执行过的SQL, 而不会滚当前方法的事务
  97. *
  98. * Execute within a nested transaction if a current transaction exists,
  99. * behave like {@code REQUIRED} otherwise. There is no analogous feature in EJB.
  100. * <p>Note: Actual creation of a nested transaction will only work on specific
  101. * transaction managers. Out of the box, this only applies to the JDBC
  102. * DataSourceTransactionManager. Some JTA providers might support nested
  103. * transactions as well.
  104. * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
  105. */
  106. NESTED(TransactionDefinition.PROPAGATION_NESTED);
  107. private final int value;
  108. Propagation(int value) {
  109. this.value = value;
  110. }
  111. public int value() {
  112. return this.value;
  113. }
  114. }