리소스 예약 패턴의 잠금 및 분리
Spring과 MariaDB로 자원 예약 패턴을 해결해야 합니다.문제는 매우 간단합니다. 이벤트의 게스트 이름을 저장하는 게스트 테이블이 있습니다. 이벤트의 게스트 수가 최대 용량보다 작거나 같아야 합니다.
다음 표는 다음과 같습니다.
create table guest(
event int,
name varchar(50)
)
create index event on guest (event);
DB의 올바른 잠금 절차 및 격리 수준은 무엇입니까?이 코드는 멀티스레딩 컨테이너에서 실행된다는 점을 고려해 주십시오."SELECT..."로 테이블을 잠그는 것을 선택했습니다.FOR UPDATE"를 클릭하여 하나의 이벤트 행에서만 잠금을 제한합니다.
// START TRANSACTION
@Transactional
public void reserve(int event, String name){
getJdbc().query("SELECT * FROM guest WHERE id=? FOR UPDATE",event);
Integer count=getJdbc().queryForObject("SELECT COUNT(*) FROM guest WHERE id=?",Integer.class,event);
if(count>=MAX_CAPACITY)
throw new ApplicationException("No room left");
getJdbc().query("INSERT INTO guest VALUES (?,?)",event,name);
}
// COMMIT
테스트를 했는데 READ가 필요한 것 같아요.헌신적인 격리 수준 맞죠?제가 찾은 건 다음과 같습니다.
분리 레벨을 변경하는 것은 이번이 처음인데, 이 요구에 조금 놀랐습니다.이 패턴으로 표준 MariaDB 분리 레벨 REPTABLE_READ가 실패하는지 확인해 주시겠습니까?
문제는 스레드2의 트랜잭션 중에 repeatable_read를 사용하면 트랜잭션 시작 시 상태 그대로 DB를 볼 수 있다는 것입니다.따라서 그 때 아직 완료되지 않은 거래 1의 효과는 숨겨집니다.따라서 다른 트랜잭션과 관계없이 항상 동일한 수의 레코드가 표시됩니다.따라서 두 트랜잭션 모두 레코드를 삽입합니다.
READ_COMMITED는 매뉴얼에 따라 "같은 트랜잭션 내에서도 일관된 각 읽기는 자신의 새로운 스냅샷을 설정하고 읽는다"를 의미합니다.새로 고침 스냅샷은 커밋된 동시 트랜잭션의 결과가 포함됨을 의미합니다.
문제를 해결하기 위한 제안입니다.이것은 하는 대신에 카운터를 유지하는 것을 포함한다.COUNT(*)
(네, 이것은 중복 정보가 없다는 원칙에 위배됩니다.)
CREATE TABLE EventCount ( event ..., ct INT ..., PRIMARY KEY(event) ) ENGINE=InnoDB;
START TRANSACTION;
INSERT ...;
UPDATE EventCount
SET ct = ct + 1
WHERE event = ?;
ct = SELECT ct FROM EventCount WHERE event = ?;
if (ct > max)
{
ROLLBACK;
exit;
}
COMMIT;
(동굴:이것이 당신의 상황에 적합한지 확인하지 못했습니다.)
언급URL : https://stackoverflow.com/questions/52923678/lock-and-isolation-for-resource-reservation-pattern
'programing' 카테고리의 다른 글
Python의 목록 메서드 append와 extend의 차이점은 무엇입니까? (0) | 2023.01.28 |
---|---|
TLD는 얼마나 걸릴 수 있습니까? (0) | 2023.01.28 |
mysqldb python 인터페이스를 설치할 때 mysql_config를 찾을 수 없습니다. (0) | 2023.01.28 |
인쇄문이 없으면 루프가 다른 스레드에 의해 변경된 값을 볼 수 없습니다. (0) | 2023.01.28 |
SyntaxError: 모듈 외부에서 Import 문을 사용할 수 없습니다. (0) | 2023.01.28 |