读已提交 有什么问题
在"读已提交"(Read Committed)隔离级别下,一个事务只能读取其他已经提交的事务所做的修改。尽管这比"读未提交"提供了更好的一致性,但仍然存在一些并发问题,最常见的是“不可重复读”问题。
不可重复读(Non-Repeatable Read): 在"读已提交"隔离级别下,一个事务在读取某个数据后,如果另一个事务修改了这个数据并且提交了,那么第一个事务再次读取该数据时会得到不同的结果,从而发生了不可重复读。
例子:
-
事务 A 读取数据:
- 事务A在"读已提交"隔离级别下开始读取某一行数据,得到结果X。
-
事务 B 修改并提交数据:
- 在事务A读取数据后,事务B修改了同一行数据,并提交了这个修改。
-
事务 A 再次读取相同数据:
- 事务A再次读取相同的数据,但由于事务B的修改,结果不再是X,而是Y。
这个过程展示了在"读已提交"隔离级别下,同一个事务在不同时间点读取相同的数据可能得到不同的结果。这种不一致性就是不可重复读的问题。要解决不可重复读,可以使用更高隔离级别,如"可重复读"或"串行化",但需要注意这可能会带来一定的性能开销。
事务的隔离级别 什么作用
事务的隔离级别是指在并发执行的情况下,一个事务对其他事务的影响程度。数据库系统通过设置不同的隔离级别来平衡事务的并发性和数据一致性。在SQL标准中,定义了四种事务隔离级别,从低到高分别是:
-
读未提交(Read Uncommitted):
- 允许一个事务读取另一个事务未提交的数据。
- 最低的隔离级别,可能导致脏读(读取到未提交的数据)、不可重复读和幻读。
-
读已提交(Read Committed):
- 允许一个事务只能读取另一个事务已经提交的数据。
- 避免了脏读,但仍然可能出现不可重复读和幻读。
-
可重复读(Repeatable Read):
- 保证在事务执行期间,多次读取同一数据都会返回相同的结果。
- 避免了脏读和不可重复读,但仍然可能出现幻读。
-
串行化(Serializable):
- 最高的隔离级别,确保事务串行执行,避免了脏读、不可重复读和幻读。
- 通过锁定数据的方式实现,性能开销较大,一般情况下不建议使用。
作用:
- 并发控制: 隔离级别定义了多个事务之间的可见性,从而控制了并发执行时可能出现的问题,如脏读、不可重复读和幻读。
- 数据一致性: 隔离级别确保了事务在并发执行时对数据的访问和修改是一致的,不会导致数据不一致的情况。
- 性能: 隔离级别的选择直接影响了系统的性能。较低的隔离级别通常允许更高的并发性,但可能导致更多的并发问题;而较高的隔离级别能够保证数据的一致性,但可能降低系统的并发性能。
选择合适的隔离级别取决于具体的应用场景和对数据一致性的要求。在实际应用中,通常需要根据业务需求和性能要求做出权衡。
事务的传播行为 有什么作用
事务的传播行为是指在一个事务范围内调用另一个事务时,新的事务如何与现有事务进行交互的规则。在许多编程环境和数据库访问框架中,都提供了一些用于控制事务传播行为的选项。这些选项定义了事务如何在方法、函数或代码块之间进行传播和交互。
以下是一些常见的事务传播行为:
-
PROPAGATION_REQUIRED:
- 如果当前没有事务,就新建一个事务;如果已经存在一个事务中,加入到这个事务中。这是默认的传播行为。
-
PROPAGATION_REQUIRES_NEW:
- 总是新建一个事务。如果当前存在事务,将其挂起。
-
PROPAGATION_SUPPORTS:
- 支持当前事务,如果没有事务则以非事务方式执行。
-
PROPAGATION_NOT_SUPPORTED:
- 以非事务方式执行操作,如果当前存在事务,就将其挂起。
-
PROPAGATION_MANDATORY:
- 强制要求存在一个事务,如果不存在,则抛出异常。
-
PROPAGATION_NESTED:
- 如果当前事务存在,则嵌套事务执行;如果当前事务不存在,则新建一个事务。
这些传播行为的选择可以根据应用程序的需求进行调整,以平衡对事务一致性和性能的需求。传播行为的作用包括:
-
控制事务的边界: 传播行为定义了事务的范围,决定了事务何时启动、何时提交或回滚。这有助于确保事务边界的清晰性,防止不同事务之间的相互影响。
-
提供灵活性: 不同的业务需求可能需要不同的事务传播行为。例如,在一个方法内调用的其他方法可能需要和当前事务共享一个事务,或者需要独立开启一个新的事务。
-
处理嵌套事务: 有些场景需要支持嵌套事务,即在一个事务内部又开启了一个新的事务。传播行为可以定义在这种情况下事务的行为,如何处理嵌套事务的提交和回滚。
在选择事务传播行为时,需要仔细考虑业务逻辑的要求以及对事务边界和性能的影响。