- 논리적인 작업 셋이 100% 적용되거나 아무것도 적용되지 않아야 함을 보장
- COMMIT
- ROLLBACK
- 트랜잭션이 없다면, 여러 동작을 수행했을 때, 중간 작업이 실패 했을 경우 손수 롤백 해야하는 불편함이 있다.
- 트랜잭션의 범위는 최소화해야 한다.
- 모놀리식 서비스는 트랜잭션을 하나로 관리가 가능하지만, MSA 는 하나의 트랜잭션으로 묶기 어렵다.
- SAGA 패턴: MSA 에서의 트랜잭션을 SAGA 라는 단위로 묶는다?
- 읽기 잠금
- 쓰기 잠금
- 서버 전체
- 백업 락
- MySQL 8.0에서는 데이터 변경을 허용하는 백업 락 추가됨
- 테이블 정보 수정 허용 x
- 명시적 락
- 묵시적 락
- 임의의 문자열에 대한 잠금 설정
- 동일 데이터를 변경하거나 참조하는 프로그램끼리 분류하여 네임드 락을 걸고 쿼리 실행
- MySQL 8.0 부터는 네임드 락을 중첩 사용 가능
- 락에다가 이름 같은 것을 설정
- 데드락
- DOG CAT
- CAT DOG
- https://helloworld.kurly.com/blog/vsms-performance-experiment/#%EB%8D%B0%EB%93%9C%EB%9D%BD%EC%9D%98-%EC%9B%90%EC%9D%B8-%EF%B8%8F
- 데이터베이스 객체의 이름이나 구조 변경 시 획득하는 잠금
- 레코드 기반 잠금
- 최근 버전에서는 트랜잭션 상태와 잠금에 대해서 조회할 수 있는 여러 모니터링 방법 추가
- 레코드 락
- 갭(GAP) 락
- 넥스트 키 락
- 자동 증가 락
- https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html#innodb-gap-locks
- 레코드 자체만을 잠금
- MySQL은 인덱스의 레코드를 잠금
- 보조 인덱스의 경우 넥스트 키 락 / 갭 락
- PK 또는 유니크 인덱스의 경우 레코드 락
- 레코드와 바로 인접한 레코드 사이의 간격만을 잠금
- STATEMENT 포맷의 바이너리 로그를 사용하는 경우 REPEATABLE READ 격리 수준 사용해야 함
- 바이너리 로그에 기록되는 쿼리가 레플리카 서버에서 실행될 때 소스 서버에서 만들어 낸 결과와 동일한 결과를 만들어내도록 보장하는 것이 주 목적
- 가능하면 바이너리 로그 포맷을 ROW 형태로 바꾸기
- MySQL 8.0 에서는 기본 설정
- PK Clustered Index 는 Sparse Index 로 구성 가능하고
- Secondary Index 는 dense index 로 구성가능하다.
- 레플리카 서버와 소스 서버에서 만든 쿼리결과가 동일하도록 보장
- 팬텀 리드 문제를 해결하기 위해서 넥스트 키 락이 필요
- 레코드 락과 갭락을 둘다 활용해서 구현된 개념이 넥스트 키 락
- AUTO_INCREMENT 에 대한 락
- INSERT, REPLACE
- 인덱스를 사용하면서 접근한 레코드 모두를 잠금
- 그러므로 인덱스 설계가 중요
- 잠금 / 트랜잭션 정보에 대한 조회
- DIRTY READ
- NON-REPEATABLE READ
- PHANTOM READ
- DIRTY READ
- NON-REPEATABLE READ
- PHANTOM READ
- NON-REPEATABLE READ
- PHANTOM READ
- PHANTOM READ
범위 조회 다른 트랜잭션
id 110 -> 1, 4, 4, 9 insert 7 OK
id 110 -> 1, 4, 4, 7, 9 PHAMTOM READ
- PHANTOM READ
- JPA는 캐시 구조가 있어 REPEATABLE READ를 기본적으로 지원
CREATE TABLE test(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
codesquad BIGINT NOT NULL,
);
INSERT INTO test (codesquad) VALUES (1), (3), (5), (7), (10);
START TRANSACTION;
SELECT * FROM test WHERE id >= 7;
COMMIT;
START TRANSACTION;
EXPLAIN SELECT * FROM test WHERE id = 1 FOR UPDATE;
COMMIT;1, 2, 3, 4, 5, ... 10000
인덱스 -> 찾을수 있는거에 대해서, 데이터 페이지 주소를 매핑 id 데이터 페이지 번호 (페이지 주소) 1 -> 1 2 -> 1 3 -> 1 4 5 6 ..
1000 -> 1 1001 -> 2 ... 1400 -> 2 ... 2000 -> 2
10000 -> dense index
index (first_name, last_name) first_name, record id
GERGI 10001 GERGI 10002 GERGI 10003 GERGI 10007 GERGI 10004 GERGI 10006
GERGY
SELECT 언제든 가능 SELECT FOR SHARE SELECT FOR UPDATE
UPDATE WHERE first_name = GERGI AND last_name=Klassen
1 -> 1 1001 -> 2 2001 -> 3 -> sparse index pk clustered index <-
secondary index -> dense index
페이지 1 1, 2 3 4 .. 1000
페이지 2 1001 1002
...
2000

