Frequently asked questions about work

A lock is added to the transaction

@Transactional(rollbackFor = Exception.class)
 public void addError(User user) {
    
    
      log.info("add user params user:{}", JSON.toJSONString(user));
      Assert.isTrue(StringUtils.isNotBlank(user.getIdCard()), "身份证号不允许null");
      String key = "key";
      RLock lock = redissonClient.getLock(key);
      lock.lock();
      try {
    
    
          LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
                  .eq(User::getIdCard, user.getIdCard());
          long count = userMapper.selectCount(wrapper);
          if (count == 0) {
    
    
              userMapper.insert(user);
          }
      } catch (Exception e) {
    
    
          log.error("add user error", e);
      } finally {
    
    
          lock.unlock();
      }
      System.out.println("并发执行,同时插入了两条");
}

After thread 1 releases the lock, the transaction has not been committed yet, and the database has no content.
Thread 2 acquires the lock to execute the logic, and the query database has no value that requires the lock.
The final result is inserted into two

Two error transaction propagation

a service

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void a() {
    
    
        try {
    
    
            userServiceB.b();
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        User user = new User();
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
                .eq(User::getIdCard, "1000");
        User user1 = userMapper.selectOne(wrapper);
        user1.setName("zhangsan");
        userMapper.updateById(user1);
    }

b service

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void b() {
    
    
        User user = new User();
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
                .eq(User::getIdCard, "1000");
        User user1 = userMapper.selectOne(wrapper);
        user1.setName("lisi");
        userMapper.updateById(user1);
        System.out.println(1 / 0);
    }

Error:

2023-03-21 14:24:25 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.etTransaction 370 : Creating new transaction with name [com.lx.debug.idempotent.moduler.service.impl.UserServiceAImpl.a]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Exception
2023-03-21 14:24:25  INFO - [          main] com.zaxxer.hikari.HikariDataSource      .getConnection 110 : HikariPool-1 - Starting...
2023-03-21 14:24:25  WARN - [          main] com.zaxxer.hikari.util.DriverDataSource .       <init>  70 : Registered driver with driverClassName=com.mysql.jdbc.Driver was not found, trying direct instantiation.
2023-03-21 14:24:25  INFO - [          main] com.zaxxer.hikari.HikariDataSource      .getConnection 123 : HikariPool-1 - Start completed.
2023-03-21 14:24:25 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.      doBegin 267 : Acquired Connection [HikariProxyConnection@1514631948 wrapping com.mysql.cj.jdbc.ConnectionImpl@15369d73] for JDBC transaction
2023-03-21 14:24:25 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.      doBegin 285 : Switching JDBC Connection [HikariProxyConnection@1514631948 wrapping com.mysql.cj.jdbc.ConnectionImpl@15369d73] to manual commit
2023-03-21 14:24:26 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.ngTransaction 470 : Participating in existing transaction
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.selectList.        debug 137 : ==>  Preparing: SELECT id,name,id_card,age,email,is_delete FROM user WHERE is_delete=0 AND (id_card = ?)
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.selectList.        debug 137 : ==> Parameters: 1000(String)
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.selectList.        debug 137 : <==      Total: 1
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.updateById.        debug 137 : ==>  Preparing: UPDATE user SET name=?, id_card=?, age=?, email=? WHERE id=? AND is_delete=0
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.updateById.        debug 137 : ==> Parameters: lisi(String), 1000(String), 1(Integer), 1(String), 1000(Long)
java.lang.ArithmeticException: / by zero
	at com.lx.debug.idempotent.moduler.service.impl.UserServiceBImpl.b(UserServiceBImpl.java:30)

2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.updateById.        debug 137 : <==    Updates: 1
2023-03-21 14:24:26 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.ocessRollback 842 : Participating transaction failed - marking existing transaction as rollback-only
2023-03-21 14:24:26 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.tRollbackOnly 359 : Setting JDBC transaction [HikariProxyConnection@1514631948 wrapping com.mysql.cj.jdbc.ConnectionImpl@15369d73] rollback-only
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.selectList.        debug 137 : ==>  Preparing: SELECT id,name,id_card,age,email,is_delete FROM user WHERE is_delete=0 AND (id_card = ?)
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.selectList.        debug 137 : ==> Parameters: 1000(String)
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.selectList.        debug 137 : <==      Total: 1
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.updateById.        debug 137 : ==>  Preparing: UPDATE user SET name=?, id_card=?, age=?, email=? WHERE id=? AND is_delete=0
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.updateById.        debug 137 : ==> Parameters: zhangsan(String), 1000(String), 1(Integer), 1(String), 1000(Long)
2023-03-21 14:24:26 DEBUG - [          main] ent.moduler.mapper.UserMapper.updateById.        debug 137 : <==    Updates: 1
2023-03-21 14:24:26 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.       commit 705 : Global transaction is marked as rollback-only but transactional code requested commit
2023-03-21 14:24:26 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.ocessRollback 833 : Initiating transaction rollback
2023-03-21 14:24:26 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.   doRollback 345 : Rolling back JDBC transaction on Connection [HikariProxyConnection@1514631948 wrapping com.mysql.cj.jdbc.ConnectionImpl@15369d73]
2023-03-21 14:24:26 DEBUG - [          main] work.jdbc.support.JdbcTransactionManager.terCompletion 389 : Releasing JDBC Connection [HikariProxyConnection@1514631948 wrapping com.mysql.cj.jdbc.ConnectionImpl@15369d73] after transaction

org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:870)

It can be seen from the log that
the current transaction is marked as rolled back when the B service commits

marking existing transaction as rollback-only

Service A commits the transaction after catching the exception, and finds that the current transaction is marked as rollback-only
and then throws an exception. Service A neither commits nor rolls back

Guess you like

Origin blog.csdn.net/lx9876lx/article/details/129690022