undo log → undo log 의 역할과 활용이 아래 내용을 이해하는데 필수 적임
undo log 는 update 문장이나 delete 와 같은 문장으로 데이터를 변경 했을때 변경 전의 데이터를 보관(백업)하는 곳이다.
예를 들어 xxx 테이블의 abc 컬럼의 값이 ‘ABC’ 이였다고 가정할때
update xxx set abc = ‘abc’ 라는 실행이 된 경우 테이블 레코드 에는 ‘abc’ 로 변경 되어 있고, 언두 로그에는 ‘ABC’ 로 저장 된다. commit 을 하게 되면 현재 상태가 그대로 유지 되고, rollback 을 하면 언두 로그의 데이터가 다시 테이블 레코드로 덮어쓰게 된다.
- MVCC (Multi Version Concurrency Control)
정의 하자면 테이블의 레코드에 대하여 여러 개의 버전이 동시 관리 된다는 의미이고, LOCK 이 없는 일관된 읽기가 목적이다. 그리고 이것은 undo log를 사용하여 구현하고 있다.
사례 : tableA 에 company 컬럼의 값이 Toss 인 신규 레코드 생성 후 commit 한다. 그리고 company 를 TossPayments 로 업데이트 한다.(commit x)
- insert into tableA (no, company) values (1, ‘Toss’);
- Commit;
- update tableA set company = ’TossPayments’ where no = 1;
- (Commit 를 하기 전)
이 상황에서 다른 사용자가
select * from tableA 을 한 경우 company 는 어떤 값이 출력 되는지 격리 수준 별로 정리
- READ UNCOMMITTED : ‘TossPayments’
- READ COMMITTED : ‘Toss’
- REPEATABLE READ : ‘Toss’
격리 수준 별로 왜 위와 같은 결과가 나오는지 아래에서 설명한다.
isolation level
격리 수준은 한 트랜잭션 내에서 데이터가 일관성 있게 보여지는 수준을 정의 한 것이다. 이를 위해서 undo log 를 이용한다.
- READ UNCOMMITTED : dirty read, non-repeatable-read, phantom read
- commit 이나 rollback 과 상관없이 보여짐
- dirty read? 어떤 트랜잭션에서 완료되지 않은 작업을 다른 트랜잭션에서 조회 하는 현상
- READ COMMITTED : non-repeatable-read, phantom read
- commit 이 완료된 데이터만 보여 준다.
- non-repeatable-read? 한 트랜잭션 내에서 동일한 결과를 가져올 수 없는 현상
- a 가 select 를 한다. (트랜잭션 ID = 1)
b가 update 를 친다 (트랜잭션 ID = 2)
a 가 select 를 동일 조건으로 다시 한 경우 b 의 작업이 반영된 결과가 보여진다
- REPEATABLE READ : phantom read(inno db 에서는 발생하지않음)
- 바이너리 로그(replica 에 전달 될 쿼리 or 레코드) 를 가진 mysql 은 부정합이 생기지 않게 하기 위하여 non-repeatable-read 가 발생하지 않은 이 격리 수준을 default 로 설정하고 있다.
- a 가 select 를 한다.(트랜잭션 ID = 1)
b 가 update 를 한다. (트랜잭션 ID = 2) (undo log 에 레코드 생성)
a가 select 를 동일 조건으로 다시 한다.
select 의 대상을 테이블의 레코드가 아닌 undo log 에 있는 레코드를 가져온다. undo log 에 있는 레코드를 가져오는 이유는 a의 트랜잭션 ID =1 이 b 보다 먼저 생성 되어서 현재 변경이 반영된 테이블의 레코드가 아닌 undo log 의 레코드를 선택 한다.
a 는 1번의 결과와 동일한 select 결과를 얻는다.