Server

[비관적인락/PESSIMISTIC]_쓰기락 테스트

Raconer 2024. 2. 6. 00:52
728x90

트랜잭션을 테스트 해보기 위해서 다른 SQL편집기를 열어서 테스트 해야한다.

테스트 방법

  • START TRANSACTION;
    • 트랜잭션을 실행한다.
  • QUERY문 실행
    • SELECT .... FOR UPDATE를 해야 쓰기락이 걸린다.
  • 완료후 COMMIT한다.

트랜잭션 및 락 상태 확인

  • 락 상태 확인
    • SELECT * 
      FROM performance_schema.data_locks 
      WHERE LOCK_TYPE = 'RECORD';
    • 여러 ROW가 출력되는 이유는 여러 락이 동시에 잡혀서 그런다.
    • LOCK_MODE가 X 는 쓰기락이 잡혀있다라는 뜻이다.
    • INDEX_NAME : 어느 인덱스에 락이 잡혀있는지 출력된다.
    • LOCK_DATA : Index VALUE
  • 트랜잭션이 상태 확인
  • SELECT * FROM information_schema.innodb_trx;

테스트 코드

트랜잭션 1

START TRANSACTION;
SELECT * 
FROM POST p
WHERE p.memberId = 2
AND p.contents = 'v'
FOR UPDATE;
COMMIT;

설명

--  START TRANSACTION;는 실행하고
SELECT *
FROM POST p
WHERE p.memberId = 2

-- COMMIT;은 테스트가 종료 될때까지 실행하지 않는다.

위코드를 출력 했을때는 4개의 ROW가 출력이된다.
하지만

AND p.contents = 'b'

를 붙이면 2개의 ROW만 출력이된다.
이때 FOR UPDATE;를 붙이고 실행을 한후 트랜잭션 2에서 같은 QUERY를 실행하면 계속해서 READ 시도를 한다.

  • 중요!!
    • 이때 출력된 2개 ROW말고 출력되지 않는 ROW의 Index를 가지고 SELECT 해도 출력이 되지 않는다.
      • 출력은 2개이지만 Index에 모두 락이 걸리니 실질적으로 memberId가 2인 모든 ROW에 락이 걸려 있다

혹시 모르니 테스트 할때 코드를 올린다.

트랜잭션1

-- 트랜잭션 1


START TRANSACTION;
-- 출력은 2개가 출력이 되나 
-- Index에 모두 락이 걸리니 실질적으로 memberId가 2인 모든 ROW에 락이 걸려 있다.
SELECT * 
FROM POST p
WHERE p.memberId = 2
AND p.contents = 'v'
FOR UPDATE;
COMMIT;


-- 락 상태 확인
-- 여러 ROW가 출력되는 이유는 여러 락이 동시에 잡혀서 그런다.
-- LOCK_MODE가 X 는 쓰기락이 잡혀있다라는 뜻이다. 
-- INDEX_NAME에 어디에 잡혀있는지 출력된다.
-- LOCL_DATE는 Index의 값
select * 
FROM performance_schema.data_locks 
where LOCK_TYPE = 'RECORD';

-- 트랜잭션이 상태 확인
select *
from information_schema.innodb_trx;

트랜잭션2

-- 트랜잭션 2

START TRANSACTION;
SELECT * 
FROM POST p
WHERE p.memberId = 2
and p.contents = 'v'
for update;
COMMIT;

 

 

추가로 공부 해볼만한 것들!!!

  • Java에서의 동시성 이슈 제어 방법
  • 분산환경에서의 동시성 이슈제어 방법
  • MySQL의 넥스트 키락이 등장한 배경
  • MySQL 외래키로 인한 잠금
  • MySQL 데드락
728x90