[英]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 指南中所示。 必須做的小總結。
bigint (or anything similar)
版本字段(數據庫方面)@Version
通過一個非常簡單的解決方案,我的大部分僵局問題都消失了。 希望它可以幫助別人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.