Spring Boot-事务隔离教程

Posted 独孤文彬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring Boot-事务隔离教程相关的知识,希望对你有一定的参考价值。

在上一个教程 -Spring Boot事务管理示例中, 我们了解了什么是事务并实现了声明式事务管理。同样在 上一教程中,我们实现了各种事务传播类型。在本教程中,我们将了解什么是事务隔离及其不同类型。

视频讲解地址:(预留:待上传……)
让我们开始吧:

什么是事务隔离?
当两个事务同时作用于同一数据库实体时,事务隔离定义数据库状态。它涉及锁定数据库记录。因此,当一个事务在数据库实体上工作时,它描述了数据库的行为或状态,然后其他并发事务试图同时访问/编辑同一数据库实体。
ANSI / ISO标准定义了四个隔离级别。 隔离是ACID(原子性,一致性,隔离性,耐久性)的一种。 因此,事务隔离级别不是特定于Spring框架的。使用Spring,我们可以更改隔离级别以适合我们的业务逻辑。

在使用Spring实现隔离级别之前,让我们首先了解数据库级别的隔离级别。
我们将创建一个表名称为employee的表,并使用该表尝试了解隔离级别-

CREATE TABLE employee (
  empId VARCHAR(10) NOT NULL,
  empName VARCHAR(100) NOT NULL
);

我用于实现隔离级别的一些SQL命令是

//Show existing transaction isolation level if mysql version >= 8
SELECT @@TRANSACTION_ISOLATION;

//Show existing transaction isolation level if mysql version < 8
SELECT @@TX_ISOLATION;

//Set transaction isolation level to serializable. Using same syntax 
//we can set it to other isolation level.
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

//By default auto commit is enabled for mysql transaction. So we will disable it.
SET AUTOCOMMIT=0;

//Start transaction
BEGIN

//Commit transaction
COMMIT

以下是事务隔离级别的类型-

  • 可串行化
    如果两个事务同时执行,则好像是串行执行事务,即仅第一个事务被提交,然后第二个事务被执行。这是完全隔离。因此,正在运行的事务永远不会受到其他事务的影响。但是,这可能会导致问题,因为性能会很低,并且可能会发生死锁。
  • REPEATABLE_READ
    如果两个事务正在同时执行- 在提交第一个事务之前,第二个事务不能更改现有记录,但是可以添加新记录。提交第二个事务后,新添加的记录将反映在仍未提交的第一个事务中。对于MySQL,默认隔离级别为REPEATABLE_READ。
    但是,使用mysql时,REPEATABLE READ隔离级别的行为有所不同。使用MYSQL时,我们看不到第二笔交易提交的新添加的记录。

  • READ_COMMITTED
    如果两个事务同时执行- 在提交第一个事务之前,可以更改现有记录,也可以通过第二个事务更改新记录。 提交第二个事务后,新添加的记录和更新的记录也会反映在仍未提交的第一个事务中。

  • READ_UNCOMMITTED
    如果两个事务同时执行-在提交第一个事务之前,可以更改现有记录,也可以通过第二个事务更改新记录。即使未提交第二个事务,新添加的以及更新的记录也会反映在仍未提交的第一个事务中。

    摘要
  • 脏读-假设有两个事务-事务A和事务B同时运行。如果事务A修改了一条记录但没有提交。事务B读取该记录,但随后事务A再次回滚该记录的更改并提交。因此,事务B的值有误。
  • 不可重复读取,假设有两个事务-事务A和事务B同时运行。如果事务A读取某些记录。事务B在提交事务A之前先修改这些记录。因此,如果事务A再次读取这些记录,它们将是不同的。因此,相同的select语句会导致不同的现有记录。
  • 幻读,假设有两个事务-事务A和事务B同时运行。如果事务A读取某些记录。事务B在提交事务A之前添加了更多此类记录。因此,如果事务A再次读取,则记录将比前一个select语句更多。因此,相同的select语句会导致显示不同的数字记录,因为也会添加新记录。

使用Spring Boot实现事务隔离

在Spring Boot中使用事务隔离时,默认的事务隔离是基础数据库的事务隔离。因此,对于我们的Spring Boot应用程序,由于我们使用的是MySQL数据库,因此默认事务隔离为REPEATABLE_READ。在上一个教程 -Spring Boot事务管理示例中, 我们了解了什么是事务并实现了声明式事务管理。我们将修改此代码。我们可以如下更改事务隔离级别:

package com.javainuse.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import com.javainuse.model.Employee;
import com.javainuse.model.EmployeeHealthInsurance;
import com.javainuse.service.EmployeeService;
import com.javainuse.service.HealthInsuranceService;
import com.javainuse.service.OrganizationService;

@Service
public class OrganzationServiceImpl implements OrganizationService 

	@Autowired
	EmployeeService employeeService;

	@Autowired
	HealthInsuranceService healthInsuranceService;

	@Override
	// Using Transactional annotation we can define any isolation level supported by the underlying database.
	@Transactional(isolation = Isolation.SERIALIZABLE)
	public void joinOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance) 
		employeeService.insertEmployee(employee);
		healthInsuranceService.registerEmployeeHealthInsurance(employeeHealthInsurance);
	

	@Override
	@Transactional
	public void leaveOrganization(Employee employee, EmployeeHealthInsurance employeeHealthInsurance) 
		employeeService.deleteEmployeeById(employee.getEmpId());
		healthInsuranceService.deleteEmployeeHealthInsuranceById(employeeHealthInsurance.getEmpId());
	

以上是关于Spring Boot-事务隔离教程的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot事务管理-事务回滚示例

Spring Boot事务管理-事务回滚示例

Spring Boot 事务隔离级别

剑指架构师系列-InnoDB存储引擎Spring事务与缓存

Spring事务管理

Spring 之注解事务 @Transactional