8. Non-repeatable read
Non-repeatable read란 같은 행을 두 번 읽었는데 값이 서로 다른 현상을 말함
원인은 다른 트랜잭션에서 그 사이에 데이터 변경 작업을 진행 후 COMMIT을 수행하였기 때문
ex)
- 트랜잭션 A가 고객 잔액을 조회 → 100
- 트랜잭션 B가 잔액을 100 → 200으로 변경하고 COMMIT
- A가 다시 같은 고객 잔액 조회
→ 100이 아닌 200이 조회됨
쿼리의 결과가 서로 달라지게 된 원인은 다른 트랜잭션(B)에서 A가 조회한 레코드의 값을 갱신하거나 삭제하였기 때문에 발생
현재 트랜잭션 격리 레벨이 READ COMMITTED인지 확인
sql
SELECT trx_id, trx_state, trx_started, trx_operation_state, trx_tables_in_use, trx_tables_locked, trx_isolation_level FROM INFORMATION_SCHEMA.INNODB_TRX;or
sql
SELECT @@SESSION.transaction_isolation;Transaction A
- SALES 테이블에서 상품의 개수별 총 금액 연산 후 조회
- SALES 테이블에서 상품별 총 금액을 합산 후 조회
Transaction B
- PRODUCT_ID가 1인 레코드의 QUANTITY의 개수 5개 추가 후
COMMIT수행
| 수행 시점 | 트랜잭션 A | A 결과 | 트랜잭션 B | B 결과 |
|---|---|---|---|---|
| (1) BEGIN; | (2) BEGIN; | |||
| (3) SELECT PRODUCT_ID, QUANTITY * PRICE FROM SALES; | ||||
| PRODUCT 1(50), PRODUCT 2(80) | ||||
| 트랜잭션 A가 아직 COMMIT되지 않은 상태 | (4) UPDATE SALES SET QUANTITY = QUANTITY + 5 WHERE PRODUCT_ID = 1; | |||
| (5) COMMIT; | ||||
| (6) SELECT SUM(QUANTITY * PRICE) FROM SALES; | 155 | |||
| COMMIT; |
해결 방법
격리 레벨을 REPEATABLE READ로 격상
트랜잭션 격리 레벨을 REPEATABLE READ로 격상 후 다시 테스트해보기
sql
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;Last updated on