簡體   English   中英

如何在 Spring 中處理並發訪問的事務

[英]How to handle transactions with concurrent access in Spring

我有一種方法的服務:

    @Service
    public class DefaultTestService implements TestService {
        private static final Logger LOGGER = Logger.getLogger(DefaultTestService.class);
        @Autowired
        private TestRepository testRepository;

        @Transactional(readOnly = false, isolation = Isolation.SERIALIZABLE)
        @Override
        public void incrementAndGet(Long testModelId) {
            LOGGER.debug("Transaction is active: " + TransactionSynchronizationManager.isActualTransactionActive());
            final TestModel tm = testRepository.findOne(testModelId);
            if (tm != null) {
                LOGGER.debug("Updated " + testModelId + " from value: " + tm.getValue());
                tm.setValue(tm.getValue() + 1);
                testRepository.save(tm);
            } else {
                LOGGER.debug("Saved with id: " + testModelId);
                final TestModel ntm = new TestModel();
                ntm.setId(testModelId);
                testRepository.save(ntm);
            }
       }
    }

而且我正在使用帶有testModelId = 1L參數的 2 個並行調用配置運行 Gatling。 由於這些調用,我收到錯誤:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "test_model_pkey"

我從日志中看到的是兩個調用一次進入了這個方法,並且每個打印的日志

"Saved with id: 1"
"Saved with id: 1"

我假設在此方法上添加事務注釋會阻止testRepository.findOne(testModelId)行中的一個調用,直到其他調用完成其執行,但正如我從日志中看到的那樣,它以不同的方式工作。

所以我的問題是當並發訪問出現時,在這種情況下事務如何工作? 以及如何通過並發訪問處理這種情況?

我有一種方法的服務:

    @Service
    public class DefaultTestService implements TestService {
        private static final Logger LOGGER = Logger.getLogger(DefaultTestService.class);
        @Autowired
        private TestRepository testRepository;

        @Transactional(readOnly = false, isolation = Isolation.SERIALIZABLE)
        @Override
        public void incrementAndGet(Long testModelId) {
            LOGGER.debug("Transaction is active: " + TransactionSynchronizationManager.isActualTransactionActive());
            final TestModel tm = testRepository.findOne(testModelId);
            if (tm != null) {
                LOGGER.debug("Updated " + testModelId + " from value: " + tm.getValue());
                tm.setValue(tm.getValue() + 1);
                testRepository.save(tm);
            } else {
                LOGGER.debug("Saved with id: " + testModelId);
                final TestModel ntm = new TestModel();
                ntm.setId(testModelId);
                testRepository.save(ntm);
            }
       }
    }

我正在使用帶有testModelId = 1L參數的2個並行調用config運行Gatling。 這些調用的結果是我得到了錯誤:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "test_model_pkey"

我從日志中看到的是,有兩個調用一次輸入了此方法,每個打印的日志

"Saved with id: 1"
"Saved with id: 1"

我假設在此方法上添加事務注釋會阻塞對testRepository.findOne(testModelId)的調用,直到其他調用完成執行為止,但是正如我從日志中看到的那樣,它以不同的方式工作。

所以我的問題是,當出現並發訪問時,事務在這種情況下如何工作? 我如何通過並發訪問來處理這種情況?

我有一種方法的服務:

    @Service
    public class DefaultTestService implements TestService {
        private static final Logger LOGGER = Logger.getLogger(DefaultTestService.class);
        @Autowired
        private TestRepository testRepository;

        @Transactional(readOnly = false, isolation = Isolation.SERIALIZABLE)
        @Override
        public void incrementAndGet(Long testModelId) {
            LOGGER.debug("Transaction is active: " + TransactionSynchronizationManager.isActualTransactionActive());
            final TestModel tm = testRepository.findOne(testModelId);
            if (tm != null) {
                LOGGER.debug("Updated " + testModelId + " from value: " + tm.getValue());
                tm.setValue(tm.getValue() + 1);
                testRepository.save(tm);
            } else {
                LOGGER.debug("Saved with id: " + testModelId);
                final TestModel ntm = new TestModel();
                ntm.setId(testModelId);
                testRepository.save(ntm);
            }
       }
    }

我正在使用帶有testModelId = 1L參數的2個並行調用config運行Gatling。 這些調用的結果是我得到了錯誤:

org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique constraint "test_model_pkey"

我從日志中看到的是,有兩個調用一次輸入了此方法,每個打印的日志

"Saved with id: 1"
"Saved with id: 1"

我假設在此方法上添加事務注釋會阻塞對testRepository.findOne(testModelId)的調用,直到其他調用完成執行為止,但是正如我從日志中看到的那樣,它以不同的方式工作。

所以我的問題是,當出現並發訪問時,事務在這種情況下如何工作? 我如何通過並發訪問來處理這種情況?

您可以使用樂觀鎖定,正如本Baeldung 指南中所示。 必須做的小總結。

  1. 向在常見死鎖事務中修改的表添加一個bigint (or anything similar)版本字段(數據庫方面)
  2. 在 JPA 模型新創建的版本字段中添加注解@Version

通過一個非常簡單的解決方案,我的大部分僵局問題都消失了。 希望它可以幫助別人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM