MySQL 이 기본 격 리 단계 로 Repeatable Read 를 선택 한 이유

MySQL 의 사무 격 리 등급 에 대해 많은 독자 들 이 낯 설 지 않다 고 믿 습 니 다.인터넷 업 체 는 관련 된 글 이 많 습 니 다.많은 사람들 이 각종 격 리 등급 과 서로 다른 등급 에 대해 해결 할 수 있 는 읽 기 현상 은 모두 디지털 입 니 다.
ANSI/ISO SQL 이 정의 하 는 표준 격 리 단 계 는 네 가지 가 있 습 니 다.높 은 곳 에서 끝까지 직렬 화(Serializable),중복 읽 기(Repeatable Reads),읽 기(Read Committed),읽 기 미 제출(Read Uncommitted)순 으로 나 타 났 습 니 다.
图片
RU 격 리 단계 에 서 는 더러 운 읽 기,환 독,중복 읽 기 불가 등의 문제 가 발생 할 수 있다.RC 격 리 단계 에서 더러 운 독 서 를 해 결 했 고 환 독,재 독 불가 문제 가 있 었 다.RR 격 리 단계 에 서 는 더러 운 독 서·다시 읽 을 수 없 는 문 제 를 해 결 했 고,환 독 의 문제 가 있 었 다.Serializable 격 리 단계 에서 더러 운 읽 기,환 독,다시 읽 을 수 없 는 문 제 를 해결 했다.
이 네 가지 격 리 단 계 는 ANSI/ISO SQL 이 정의 하 는 표준 정의 입 니 다.저희 가 자주 사용 하 는 MySQL 은 이 네 가지 격 리 단 계 를 모두 지원 합 니 다.그러나 Oracle 데이터 베 이 스 는 Serializable 과 Read Committed 만 지원 합 니 다.
그러나 많은 사람들 이 Oracle 의 기본 격 리 단 계 는 RC 이 고 MySQL 의 기본 격 리 단 계 는 RR 이라는 것 을 모 를 것 이다.
그렇다면 Oracle 은 왜 RC 를 기본 단계 로 선택 하고 MySQL 은 RR 을 기본 격 리 단계 로 선택 하 는 지 아 십 니까?
이것 은 내 가 이전에 면접 을 볼 때 후보자 에 게 물 어 본 문제 다.
많은 사람들 이 이 문제 가 의미 가 없다 고 생각 하 는데,이것 은 우리 에 게 팔고문 을 외우 라 고 강요 하 는 것 이 아닌가?
그러나 사실은 그렇지 않다.만약 네가 인내심 을 가지 고 이 글 을 다 볼 수 있다 면,너 는 나의 매우 고 된 마음 을 발견 할 수 있 을 것 이다.
Oracle 의 격 리 단계
앞에서 말 했 듯 이 Oracle 은 ANSI/ISO SQL 이 정의 하 는 Serializable 과 Read Committed 만 지원 합 니 다.사실은 Oracle 공식 문서 에 따 르 면 Oracle 은 세 가지 격 리 단 계 를 지원 합 니 다.
图片
즉,Oracle 은 Read Committed,Serializable,Read-Only 를 지원 합 니 다.
Read-Only 읽 기 전용 격 리 단 계 는 직렬 화 가능 한 격 리 단계 와 유사 하지만 읽 기 전용 트 랜 잭 션 은 사용자 가 SYS 가 아 닌 트 랜 잭 션 에서 데 이 터 를 수정 할 수 없습니다.
Oracle 이라는 세 가지 격 리 단계 에서 Serializable 과 Read-Only 는 기본 격 리 단계 로 적합 하지 않 은 것 이 분명 하 다.그러면 Read Committed 라 는 유일한 선택 만 남 았 다.
MySQL 의 격 리 단계
Oracle 에 비해 MySQL 의 기본 격 리 단계 의 선택 범위 가 비교적 크다.
우선,우 리 는 먼저 네 가지 격 리 단계 에서 Serializable 과 Read Uncommitted 두 가 지 를 제외 합 니 다.주로 이 두 단계 의 격 리 단계 가 너무 높 고 하 나 는 너무 낮 기 때 문 입 니 다.너무 높 으 면 병발 도 에 영향 을 주 고 너무 낮 으 면 더러 운 독 서 를 하 는 현상 이 있다.
그럼 나머지 RR 과 RC 두 가 지 는 어떻게 고 를 까요?
이 일 은 긴 전부터 말 해 야 한다.
MySQL 디자인 에서 그의 포 지 셔 닝 은 안정 적 인 관계 형 데이터 베 이 스 를 제공 하 는 것 이다.한편,MySQL 의 단일 고장 으로 인 한 문 제 를 해결 하기 위해 MySQL 은 주종 복제 메커니즘 을 사용한다.
주종 복제 란 사실은 MySQL 클 러 스 터 를 구축 하여 전체적으로 대외 적 으로 서 비 스 를 제공 하 는 것 이다.클 러 스 터 의 기 계 는 주 서버(Master)와 서버(Slave),주 서버 는 쓰기 서 비 스 를 제공 하고 서버 에서 읽 기 서 비 스 를 제공한다.
서버 간 데이터 의 일치 성 을 확보 하기 위해 서 는 데이터 동기 화가 필요 합 니 다.대체적으로 동기 화 과정 은 다음 과 같 습 니 다.여기 서 상세 하 게 소개 하지 않 겠 습 니 다.
图片
MySQL 은 주종 복사 과정 에서 데이터 의 동기 화 는 bin log 를 통 해 이 루어 진다.쉽게 이해 하면 메 인 서버 가 데이터 변경 을 bin log 에 기록 한 다음 에 bin log 를 서버 에서 동기 화하 고 서버 에서 bin log 를 받 은 후에 그 중의 데 이 터 를 자신의 데이터 베이스 저장 소로 복원 하 는 것 이다.
그렇다면 binlog 에 기 록 된 내용 은 무엇 일 까?격식 이 어떻게 되 나 요?
MySQL 의 bin log 는 주로 statement,row,mixed 세 가지 형식 을 지원 합 니 다.MySQL 은 5.1.5 버 전에 서 row 를 지원 하기 시 작 했 고 5.1.8 버 전에 서 mixed 를 지원 하기 시작 했다.
statement 과 row 의 가장 큰 차이 점 은 binlog 의 형식 이 statemen 일 때 binlog 에 기 록 된 것 은 SQL 문장의 원문 입 니 다(이 말 은 매우 중요 합 니 다!!!뒤에 쓸 게 요.
이 몇 가지 형식의 차 이 는 여기에서 상세 하 게 전개 되 지 않 습 니 다.row 형식 을 지원 하 는 이 유 는 statement 형식 에 많은 문제 가 존재 하기 때 문 입 니 다.가장 뚜렷 한 것 은 주종 데이터베이스 의 데이터 가 일치 하지 않 을 수 있 기 때 문 입 니 다.자세 한 소 개 는 딩 치가 극객 시간 에 나 눈'마 이 SQL 실전 45 강'을 참고 하면 된다.
그렇다면 이 주종 동기 화 와 빈 로그 가 우리 가 말 하고 자 하 는 격 리 단 계 는 어떤 관계 가 있 습 니까?
관계 가 있 고 관계 가 매우 크다.
MySQL 은 초기 에 statement 이라는 bin log 형식 만 있 었 기 때문에 이 럴 때 제출 읽 기(Read Committed),제출 하지 않 은 읽 기(Read Uncommitted)두 가지 격 리 단 계 를 사용 하면 문제 가 발생 할 수 있 습 니 다.
예 를 들 어 MySQL 홈 페이지 에서 누군가가 공식 적 으로 관련 bug 를 언급 한 적 이 있다.
图片
이 bug 의 재현 과정 은 다음 과 같 습 니 다.
데이터베이스 시트 t1 이 있 습 니 다.표 에는 다음 과 같은 두 가지 기록 이 있 습 니 다.

   CREATE TABLE t1 (

      a int(11) DEFAULT NULL,

      b int(11) DEFAULT NULL,

      KEY a (a)

    ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

    insert into t1 values(10,2),(20,1);
이어서 두 가지 업무 의 쓰기 작업 을 시작 합 니 다.
图片
상기 두 가지 업무 가 실 행 된 후에 데이터 베이스 안의 기록 은(11,2)과(20,2)로 변 할 것 이다.이 메 인 라 이브 러 리 에 올 린 데이터 변경 은 모두 가 이해 할 수 있다.
트 랜 잭 션 의 격 리 단 계 는 read committed 이기 때문에 트 랜 잭 션 1 은 업데이트 할 때 b=2 줄 에 줄 잠 금 만 추가 하고 트 랜 잭 션 2 대 b=1 줄 의 쓰기 에 영향 을 주지 않 습 니 다.
상기 두 사무 가 실 행 된 후에 bin log 에 두 개의 기록 을 기록 합 니 다.사무 2 가 먼저 제출 되 기 때문에UPDATE t1 SET b=2 where b=1;우선 기록 되 고 다시 기록 합 니 다UPDATE t1 SET a=11 where b=2;(다시 알림:statement 형식의 bin log 는 SQL 문장의 원문 을 기록 합 니 다)
이렇게 하면 bin log 가 준비 라 이브 러 리 에 동기 화 된 후에 SQL 문 구 를 재생 할 때 먼저 실행UPDATE t1 SET b=2 where b=1;한 다음 에 실행UPDATE t1 SET a=11 where b=2;합 니 다.
이때 데이터베이스 에 있 는 데 이 터 는(11,2)과(11,2)로 바뀐다.이 로 인해 메 인 라 이브 러 리 와 예비 라 이브 러 리 의 데이터 가 일치 하지 않 습 니 다!!!
이런 문제 가 발생 하지 않도록MySQL 은 데이터베이스 의 기본 격 리 단 계 를 Repetable Read 로 설정 합 니 다.그러면 Repetable Read 의 격 리 단 계 는 어떻게 이런 문 제 를 해결 합 니까?
그것 은 Repetable Read 라 는 격 리 단계 가 데 이 터 를 업데이트 할 때 업 데 이 트 된 줄 에 대한 추가 잠 금 뿐만 아니 라 GAP lock 도 증가 하기 때문이다.위의 예 는 트 랜 잭 션 2 가 실 행 될 때 트 랜 잭 션 1 에 GAP lock 이 추가 되 어 트 랜 잭 션 실행 이 걸 리 기 때문에 트 랜 잭 션 1 이 제출 되 거나 스크롤 백 되 어야 계속 실 행 될 수 있 습 니 다.(GAP lock 에 대해 서 는 제 뒤에 따로 소개 할 글 이 있 습 니 다).
MySQL 은 기본 격 리 단 계 를 설정 하 는 것 외 에 statement 형식의 bin log 를 사용 하 는 경우 READ COMMITTED 를 트 랜 잭 션 격 리 단계 로 사용 하 는 것 도 금지 하고 있다.
사용자 가 자발적으로 격 리 단 계 를 수정 하면 업 데 이 트 를 시도 할 때 오류 가 발생 합 니 다.
 ERROR 1598 (HY000): Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT'
총결산
그래서 이 제 는 MySQL 이 왜 RR 을 기본 데이터베이스 격 리 단계 로 선 택 했 는 지 알 겠 습 니 다.사실은 역사상 의 statement 형식의 bin log 를 호 환 하기 위해 서 입 니 다.
그러면 본 고 는 여기까지 말 했 습 니 다.MySQL 격 리 단계 에 관 한 지식 점 에서 1/5 도 안 되 는 것 같 습 니 다.이 글 을 통 해 다음 과 같은 문제 가 있 을 수 있 습 니 다.
1.row 형식 과 statement 은 어떤 차이 가 있 습 니까?row 를 사용 한 경우 RR 을 사용 할 수 있 습 니까?
2.글 에서 언급 한 RC 의 GAP lock 은 도대체 무엇 입 니까?
3.RR 과 RC 는 어떤 차이 가 있 습 니까?RC 는 중복 읽 을 수 없 는 문 제 를 어떻게 해결 합 니까?
4.MySQL 데이터 베 이 스 는 기본적으로 RR 을 선택 한 이상 왜 알 리 와 같은 큰 인터넷 회 사 는 기본 적 인 격 리 단 계 를 RC 로 바 꿉 니까?
상기 몇 가지 문제 에 대해 당신 은 답 을 알 고 있 습 니까?아니면 어떤 것 에 더 관심 이 있 습 니까?댓 글 환영 합 니 다!저 는 여러분 들 이 비교적 관심 이 있 는 주 제 를 골 라 서 뒤의 글 에서 계속 깊이 있 게 소개 하 겠 습 니 다.
아직도 이 문제 가 무의미 하 다 고 생각 합 니까?
저 는 사실 이런 무의미 해 보 이 는 문 제 를 통 해 더 많은 지식 을 넓 혀 후 보 를 전방위 적 으로 이해 하고 싶 습 니 다.
MySQL 이 왜 Repeatable Read 를 기본 격 리 단계 로 선 택 했 는 지 에 대한 이 글 은 여기까지 입 니 다.더 많은 MySQL Repeatable Read 기본 격 리 단계 내용 은 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!

좋은 웹페이지 즐겨찾기