내 테스트에서 MariaDB을 사용하는 경우 일 때 REPETEABLE_READ 격리에서 동일한 쿼리를 실행해도 팬텀 읽기가 생성되지 않습니다.왜 팬텀 읽기를 생성하는 MariaDB에서 REPETEABLE_READ가 실행되지 않습니까?
예컨대:
내가 BANK_ACCOUNT 테이블의 두 행이는 :
ID | OWNER | MONEY
------------------------
1 | John | 1000
2 | Louis | 2000
예상 흐름은 아래와 같이 표시한다 :
THREAD 1 (REPETEABLE_READ) THREAD 2 (READ_UNCOMMITED)
| |
findAll()->[1|John|1000,2|Louis|2000] |
| |
| updateAccount(1, +100)
| createAccount("Charles", 3000)
| flush()
| |
| commitTx()
| |_
|
findAll()->[1|John|1000,2|Louis|2000,
| 3|Charles|3000]
|
|
commitTx()
|_
는 Thread2.createAccount("Charles", 3000);
후에 정리해 스레드 1은 모든 행을 검색하여 얻을 것이다.
ID | OWNER | MONEY
------------------------
1 | John | 1000
2 | Louis | 2000
3 | Charles | 3000
Thread1은 커밋되지 않은 변경 사항으로부터 보호되며 [1, John, 1100]
대신 [1, John, 1000]
이 표시되지만 새로 삽입 된 행이 표시됩니다.
ID | OWNER | MONEY
------------------------
1 | John | 1000
3 | Charles | 3000
그것은 팬텀 읽기가되지 않습니다
그러나, 무엇 Thread1 두 번째 findall은에서 검색하면 첫 findall은()의 것과 동일한 결과입니다. 왜?????
@Transactional(readOnly=true, isolation=Isolation.REPEATABLE_READ)
@Override
public Iterable<BankAccount> findAllTwiceRepeteableRead(){
printIsolationLevel();
Iterable<BankAccount> accounts = baDao.findAll();
logger.info("findAllTwiceRepeteableRead() 1 -> {}", accounts);
//PAUSE HERE
...
}
나는 그것이 //PAUSE HERE
을 SAIS 실행을 일시 정지 :
이
이 Thread1에 의해 실행 된 코드입니다. 나는 (내가 스레드 거래를 업데이트 한 정말 뭘하는지와 흐름 :bankAccountService.addMoneyReadUncommited(ba.getId(), 200);
bankAccountService.createAccount("Carlos", 3000);
을 그리고 Thread1이 다시 시작됩니다 :
그런 다음 Thread2는 실행
가//PAUSE HERE
...
Iterable<BankAccount> accounts = baDao.findAll();
logger.info("findAllTwiceRepeteableRead() 2 -> {}", accounts);
업데이트 새로운 행 삽입 후에 두 번째 트랜잭션을 커밋).
이것은 위키 백과에 따르면 유령 읽기이며 나는 매우 똑같은 시나리오라고 생각합니다. 그래서 난 아직도받지 못했습니다 이유를하지 않는 팬텀은 거래 과정에서, 두 동일한 쿼리가 실행될 때, 팬텀 읽기 [3|Charles,3000]
가 발생 읽고에 의해 반환 된 행의 컬렉션 두 번째 쿼리가 첫 번째 쿼리와 다릅니다.
SELECT ... WHERE 작업을 수행 할 때 범위 잠금을 얻지 못할 때 발생할 수 있습니다. 팬텀 읽기 이상은 트랜잭션SELECT ... WHERE 쿼리와 두 작업 사이에서 트랜잭션 2 이 (대상 테이블에서) 새 행을 생성 (즉, INSERT) 할 때 반복되지 않는 읽기의 특수한 경우입니다 (예 : ). WHERE 절을 수행하십시오.당신이 실제 행동으로 간주 무엇
는
Transaction 1 Transaction 2
/* Query 1 */
SELECT * FROM users
WHERE age BETWEEN 10 AND 30;
/* Query 2 */
INSERT INTO users(id,name,age) VALUES (3, 'Bob', 27);
COMMIT;
/* Query 1 */
SELECT * FROM users
WHERE age BETWEEN 10 AND 30;
COMMIT;
안녕하세요 Thilo, Thread1이 팬텀 읽기를 테스트 할 수있는 방법이 없습니다. – codependent
필자는 유령이 읽은 것 같아요, 업데이트 된 행이 아니기 때문에 더티 읽기가 아니라 새 것으로 생각합니다. – codependent
당신은 절대적으로 옳습니다. 감사 Thilo !! – codependent