什么是事务隔离?
事务的隔离性就是指,多个并发的事务同时访问一个数据库时,一个事务不应该被另一个事务所干扰,每个并发的事务之间要相互进行隔离。
脏读,不可重复读和幻象读:
在实际开发过程中,我们绝大部分的事务都是有并发情况。多个事务并发运行,经常会操作相同的数据来完成各自的任务。在这种情况下可能会导致以下的问题:
- 脏读(Dirty reads)—— 事务A读取了事务B更新的数据,然后事务B发生了回滚操作,那么A读取到的数据是脏数据。
- 不可重复读(Non-repeatable read)—— 事务 A 多次读取同一数据,事务 B 在事务A多次读取的过程中,对数据做了更新并提交,导致事务A多次读取同一数据时,结果不一致。
- 幻读(Phantom reads)—— 事务A更新数据时,事务B插入了一条数据,事务A修改结束后发现还有一条数据没修改,就好像发生了幻觉一样,这就叫幻读。
不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。(不可重复读是因为执行了更新操作所以造成多次读取同一数据时结果不一致,而幻读是因为执行了插入或删除操作造成数据条数不一致)
事务的隔离级别:
隔离级别定义了一个事务可能受其他并发事务影响的程度。
在并发状态下可能产生: 脏读、不可重复读、幻读的情况。因此我们需要将事务与事务之间隔离。根据隔离的方式来避免事务并发状态下脏读、不可重复读、幻读的产生。
Spring中定义了五种隔离规则:
- TransactionDefinition.ISOLATION_DEFAULT:
使用后端数据库默认的隔离级别 - TransactionDefinition.ISOLATION_READ_UNCOMMITTED:
读未提交,顾名思义,就是可以读到未提交的内容,这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。如无特殊情况,基本是不会使用这种隔离级别的。 - TransactionDefinition.ISOLATION_READ_COMMITTED:
读提交,顾名思义,就是只能读到已经提交了的内容。保证了一个事务不会读到另一个并行事务已修改但未提交的数据,避免了“脏读”。这是各种系统中最常用的一种隔离级别,也是SQL Server和Oracle的默认隔离级别。“读提交”只能避免“脏读”,并不能避免“不可重复读”和“幻读”。 - TransactionDefinition.ISOLATION_REPEATABLE_READ:
可重复读,顾名思义,就是专门针对“不可重复读”这种情况而制定的隔离级别,可以有效的避免“不可重复读”。而它也是MySql的默认隔离级别。保证了一个事务不会修改已经由另一个事务读取但未提交(回滚)的数据。避免了“脏读”和“不可重复读”的情况,但是带来了更多的性能损失。不能避免“幻读”,因为幻读是由于“插入或者删除操作(Insert or Delete)”而产生的。 - TransactionDefinition.ISOLATION_SERIALIZABLE:
串行化,这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用。