database transaction

 

1. Database transactions

It is multiple SQL statements (a team), either all execute success, or fail. Its ultimate goal: data won't be corrupted. That is, the transaction operation is successful, and the result of the data is consistent with the result expected by the business. This is the consistency in ACID (Consistency). So what is ACID.

 

2. ACID

Namely atomicity, consistency, isolation and durability. The following vivid explanations:  a) Atomic  Atom is the smallest unit of matter, that is, it cannot be divided. Each simple SQL statement is contained in a transaction, which is atomic. b) Consistency  Ultimate goal: data will not be corrupted. (Isn't this nonsense? It's really a bit) Specifically, after a successful transaction operation, the state of the database is consistent with its business rules, that is, the data will not be destroyed. For example: two UPDATE statements, transfer from account A to account B, regardless of success or failure, the total amount of accounts A and B is unchanged. c) Isolation  isolation: It means that they do not interfere with each other. There is no interference between transactions, that is, each transaction is independent and will not intersect. This allows multiple threads to access the database concurrently.

 d) Persistent data must be persisted to the database (stored on disk). For a committed transaction, even if the database crashes after being committed, the unpersisted data can be re-executed according to the log when the database is restarted.

Three dirty degrees, non-repeatable read and phantom read 

 Most database transaction operations are executed concurrently, which may encounter the following problems:

lost update

: Two transactions update a row of data at the same time, and the update of the last transaction will overwrite the update of the first transaction, resulting in the loss of the data updated by the first transaction, with serious consequences. It is usually caused by the lack of locking.

Dirty read  : Refers to when a transaction is accessing data and making modifications to the data, and the modification has not been committed to the database, at this time, another transaction also accesses the data, and then uses the data.

 

non-repeatable read

The point of non-repeatable read is to modify:

The same conditions, the data you have read, read it again and find that the value is different

example:

在事务1中,Mary 读取了自己的工资为1000,操作并没有完成 

Java代码   收藏代码
  1. con1 = getConnection();  
  2. select salary from employee empId ="Mary";  

在事务2中,这时财务人员修改了Mary的工资为2000,并提交了事务. 

Java代码   收藏代码
  1. con2 = getConnection();  
  2. update employee set salary = 2000;  
  3. con2.commit();  

在事务1中,Mary 再次读取自己的工资时,工资变为了2000 

Java代码   收藏代码
  1. //con1  
  2. select salary from employee empId ="Mary";  

在一个事务中前后两次读取的结果并不致,导致了不可重复读。

 幻读

幻读的重点在于新增或者删除

同样的条件, 第1次和第2次读出来的记录数不一样

例子:

目前工资为1000的员工有10人。 
事务1,读取所有工资为1000的员工。 

Java代码   收藏代码
  1. con1 = getConnection();  
  2. Select * from employee where salary =1000;  

共读取10条记录 

 

这时另一个事务向employee表插入了一条员工记录,工资也为1000 

Java代码   收藏代码
  1. con2 = getConnection();  
  2. Insert into employee(empId,salary) values("Lili",1000);  
  3. con2.commit();  


事务1再次读取所有工资为1000的员工 

Java代码   收藏代码
  1. //con1  
  2. select * from employee where salary =1000;  

共读取到了11条记录,这就产生了幻像读。 

 为了处理这几种问题,SQL定义了下面的4个等级的事务隔离级别:

 

未提交读(READ UNCOMMITTED ):最低隔离级别,一个事务能读取到别的事务未提交的更新数据,很不安全,可能出现丢失更新、脏读、不可重复读、幻读;

提交读(READ COMMITTED):一个事务能读取到别的事务提交的更新数据,不能看到未提交的更新数据,不会出现丢失更新、脏读,但可能出现不可重复读、幻读;

Repeatable read (REPEATABLE READ): It is guaranteed that multiple queries executed successively in the same transaction will return the same result and will not be affected by other transactions. Lost updates, dirty reads, and non-repeatable reads are impossible, but phantom reads may occur;

Serialization (SERIALIZABLE): The highest isolation level. Transactions are not allowed to execute concurrently, but must be executed serially. It is the safest and impossible to update, dirty reads, non-repeatable reads, and phantom reads, but the efficiency is the lowest.

The higher the isolation level, the worse the concurrent execution performance of database transactions and the fewer operations that can be processed.

So in general, it is recommended to use the REPEATABLE READ level to ensure read consistency of data. For the problem of phantom reading, it can be prevented by locking.

MySQL supports these four transaction levels, and the default transaction isolation level is REPEATABLE READ.

Oracle database supports two transaction isolation levels of READ COMMITTED and SERIALIZABLE, so Oracle database does not support dirty reads. The default transaction isolation level of Oracle database is READ COMMITTED.

 

Detailed explanation of spring @Transactional annotation parameters

Thing annotation method: @Transactional

When marked in front of the class, all methods in the marked class are processed,

 

When some methods in a class don't need things:

 @Transactional(propagation =Propagation.NOT_SUPPORTED)

 public List getAll() { 
 return null; 
 } 

 

Introduction to the spread of things:

 

  @Transactional(propagation=Propagation.REQUIRED) : If there is a transaction, then join the transaction, if not, create a new one (by default)

  @Transactional(propagation=Propagation.NOT_SUPPORTED) : the container does not open transactions for this method

  @Transactional(propagation=Propagation.REQUIRES_NEW) :不管是否存在事务,都创建一个新的事务,原来的挂起,新的执行完毕,继续执行老的事务

  @Transactional(propagation=Propagation.MANDATORY) :必须在一个已有的事务中执行,否则抛出异常

  @Transactional(propagation=Propagation.NEVER) :必须在一个没有的事务中执行,否则抛出异常(与Propagation.MANDATORY相反)

  @Transactional(propagation=Propagation.SUPPORTS) :如果其他bean调用这个方法,在其他bean中声明事务,那就用事务.如果其他bean没有声明事务,那就不用事务.

 

事务隔离级别:

Isolation,该属性用于设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置

 

  @Transactional(isolation = Isolation.READ_UNCOMMITTED):读取未提交数据(会出现脏读, 不可重复读) 基本不使用

  @Transactional(isolation = Isolation.READ_COMMITTED):读取已提交数据(会出现不可重复读和幻读)

  @Transactional(isolation = Isolation.REPEATABLE_READ):可重复读(会出现幻读)

  @Transactional(isolation = Isolation.SERIALIZABLE):串行化

 

rollbackFor

该属性用于设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。例如:

指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)

指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})

 

noRollbackFor

该属性用于设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。例如:

指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)

指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})

 

@Transactional 注解应该只被应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。

@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。然而,请注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据,能够被可以识别 @Transactional 注解和上述的配置适当的具有事务行为的beans所使用。上面的例子中,其实正是 元素的出现 开启 了事务行为。

Spring团队的建议是你在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。你当然可以在接口上使用 @Transactional 注解,但是这将只能当你设置了基于接口的代理时它才生效。因为注解是不能继承的,这就意味着如果你正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装(将被确认为严重的)。因此,请接受Spring团队的建议并且在具体的类上使用 @Transactional 注解。

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326942517&siteId=291194637