MySQL 의 격 리 단 계 를 전면적으로 분석 합 니 다.

7673 단어 MySQL격 리 단계
데이터 베 이 스 를 동시에 수정 하면 우리 가 말 하 는 더러 운 쓰기,더러 운 읽 기,중복 읽 기,환 독 등 일련의 문제 가 발생 할 수 있다.MySQL 은 일련의 메커니즘 을 제공 하여 업무 병행 문 제 를 해결 했다.예 를 들 어 사무 격 리,잠 금 메커니즘,MVCC 다 중 버 전의 병행 제어 메커니즘 이다.오늘 은 사무 격 리 체 제 를 탐구 해 보 자.
사 무 는 SQL 로 구 성 된 논리 처리 장치 입 니 다.먼저 업무 의 ACID 특성 을 살 펴 보 겠 습 니 다.
  • 원자 성(Atomicity):사 무 는 원자 조작 장치 로 데 이 터 를 수정 하거나 모두 실행 하거나 실행 하지 않 습 니 다.집행 차원 에서 묘사 한 것 이다.
  • 일치 성(Consistent):업무 시작 과 완성 시 데이터 가 일치 해 야 합 니 다.집행 결과 차원 에서 묘사 한 것 이다.
  • 격 리 성(Isolation):데이터 베이스 시스템 은 일정한 격 리 체 제 를 제공 하여 업무 수행 과정 에서 외부 에 보이 지 않 고 독립 적 으로 운행 하 며 외부 영향 을 받 지 않도록 확보한다.
  • 지속 성(Durable):업무 가 완 료 된 후에 데이터 에 대한 수정 은 영구적 이 고 시스템 고장 이 나 도 유지 할 수 있 습 니 다.
  • 동시 다발 업무 의 영향:
  • 더러 운 쓰기(업데이트 분실:Lost Update):여러 개의 사무 가 같은 줄 을 선 택 했 습 니 다.서로 상대방 이 존재 하 는 지 모 르 고 이전 업무 의 데 이 터 를 덮어 씁 니 다.
  • 더러 운 읽 기(Dirty Reads):A 사 무 는 B 사무 가 제출 하지 않 은 데 이 터 를 읽 었 고 B 사 무 는 스크롤 백,A 가 제출 했 으 며 최종 결 과 는 일치 성 원칙 에 부합 되 지 않 았 습 니 다
  • .
  • 재 읽 을 수 없습니다(Non-repeatable Reads):같은 사무,같은 조회 문 구 는 여러 번 실 행 된 결과 가 일치 하지 않 습 니 다.외부 사무 수정 으로 인 한 것 일 수도 있 고 격 리 성에 부합 되 지 않 습 니 다.
  • 환 독(Phantom Reads):사무 A 가 사무 B 가 제출 한 새로운 데 이 터 를 읽 었 습 니 다.격 리 성에 부합 되 지 않 습 니 다.
  • 트 랜 잭 션 격 리 단계:
    격 리 단계
    더러 운 읽 기(더러 운 읽 기)
    중복 읽 기 불가(반복 읽 기 불가)
    환 독(Phantom Read)
    읽 기 미 제출(읽 기 uncommitted)
    이 가능 하 다,~할 수 있다,...
    이 가능 하 다,~할 수 있다,...
    이 가능 하 다,~할 수 있다,...
    제출 한 읽 기(읽 기 committed)
    불가능
    이 가능 하 다,~할 수 있다,...
    이 가능 하 다,~할 수 있다,...
    반복 읽 기 가능(반복 읽 기)
    불가능
    불가능
    이 가능 하 다,~할 수 있다,...
    직렬 화(Serializable)
    불가능
    불가능
    불가능
    MySQL 은 위의 네 가지 격 리 단 계 를 제공 하 는데 격 리 가 엄격 할 수록 발생 할 수 있 는 문제 가 적 지만 지불 하 는 성능 대가 가 클 수록 기본 격 리 단 계 는 중복 읽 을 수 있다.다음은 클 라 이언 트 를 사용 하여 조작 을 검증 합 니 다.
    먼저 표 와 데 이 터 를 만 듭 니 다.
    
    CREATE TABLE `account` (
     `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
     `balance` int(11) DEFAULT NULL,
     PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
    
    INSERT INTO `account` (`id`, `balance`)
    VALUES
      (1, 500),
      (2, 600),
      (3, 200);
    클 라 이언 트 를 연결 하고 격 리 단 계 를 보면 중복 읽 을 수 있 습 니 다.
    
    MySQL [test]> show variables like 'tx_isolation';
    +---------------+-----------------+
    | Variable_name | Value      |
    +---------------+-----------------+
    | tx_isolation | REPEATABLE-READ |
    +---------------+-----------------+
    읽 기 미 제출 테스트:
    AB 클 라 이언 트 모두 set tx 실행isolation='read-uncommitted';읽 기 미 제출 로 격 리 단 계 를 설정 합 니 다.
    A 클 라 이언 트 가 업 무 를 시작 합 니 다:start transaction;조회 데이터:select*from account;
    B 클 라 이언 트 오픈 사무:start transaction;업데이트 데이터:update account set balance=balance-100 where id=1;이 때 트 랜 잭 션 이 제출 되 지 않 았 습 니 다.
    클 라 이언 트 가 데 이 터 를 다시 조회:select*from account;이때 두 번 조회 한 데 이 터 는 이미 달 라 졌 다.


    B 가 제출 하기 전에 A 는 B 가 업데이트 한 데 이 터 를 읽 었 습 니 다.이때 B 가 굴 러 가면 A 쪽 은 더러 운 데이터 입 니 다.이런 상황 은 제출 되 지 않 은 더러 운 독 서 를 읽 는 것 이다.읽 기 제출 한 격 리 단계 로 해결 할 수 있 습 니 다.
    commt 명령 을 사용 하여 AB 클 라 이언 트 의 업 무 를 제출 합 니 다.
    제출 한 테스트 읽 기:
    AB 클 라 이언 트 모두 실행  set tx_isolation='read-committed'; 읽 기 제출 을 위 한 격 리 단 계 를 설정 합 니 다.
    A 클 라 이언 트 가 업 무 를 시작 합 니 다:start transaction;조회 데이터:select*from account;
    B 클 라 이언 트 오픈 사무:start transaction;업데이트 데이터:update account set balance=balance-100 where id=1;이 때 트 랜 잭 션 이 제출 되 지 않 았 습 니 다.
    클 라 이언 트 가 데 이 터 를 다시 조회:select*from account; 이때 A 클 라 이언 트 가 두 번 조회 한 데이터 가 일치 하고 더러 운 읽 기 상황 이 나타 나 지 않 는 것 을 보 았 습 니 다.
    이때 B 클 라 이언 트 업무 제출:commt;
    클 라 이언 트 가 데 이 터 를 다시 조회:select*from account;이때 A 클 라 이언 트 조회 데이터 가 변 한 것 을 보 았 습 니 다.이것 은 중복 읽 을 수 없 는 것 입 니 다.


    반복 읽 기 테스트:
    AB 클 라 이언 트 모두 실행  set tx_isolation='repeatable-read'; 중복 읽 을 수 있 도록 격 리 단 계 를 설정 합 니 다.
    A 클 라 이언 트 가 업 무 를 시작 합 니 다:start transaction;조회 데이터:select*from account;
    B 클 라 이언 트 오픈 사무:start transaction;업데이트 데이터:update account set balance=balance-100 where id=1;commt 제출 사무
    클 라 이언 트 가 데 이 터 를 다시 조회:select*from account; 이때 A 클 라 이언 트 가 두 번 조회 한 데이터 가 일치 하고 중복 읽 기 데이터 가 일치 하 는 것 을 보 았 습 니 다.
    A 클 라 이언 트 실행 업데이트 문구:update account set balance=balance-50 where id=1;
    클 라 이언 트 가 데 이 터 를 다시 조회:select*from account;이때 id=1 의 이 데 이 터 는 B 클 라 이언 트 가 업데이트 한 데이터-50 이 고 데이터 의 일치 성 은 파괴 되 지 않 았 습 니 다.
    B 클 라 이언 트 가 업 무 를 다시 시작 하고 데 이 터 를 삽입 합 니 다.insert into account(id,balance)values(4,1000);commt 제출 사무;
    A 클 라 이언 트 조회,지난번 결과 와 일치
    A 클 라 이언 트 실행:update account set balance=balance-100 where id=4;B 클 라 이언 트 가 새로 삽입 한 데 이 터 를 업데이트 하면 성공 적 으로 실행 할 수 있 고 모든 데 이 터 를 다시 조회 할 수 있 으 며 id=4 의 데 이 터 를 삽입 하여 환 독 할 수 있 습 니 다.
    
    # A       :#           MySQL [test]> set tx_isolation='repeatable-read';
    Query OK, 0 rows affected, 1 warning (0.00 sec)
    #     
    MySQL [test]> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    #       
    MySQL [test]> select * from account;
    +----+---------+
    | id | balance |
    +----+---------+
    | 1 |   300 |
    | 2 |   600 |
    | 3 |   200 |
    +----+---------+
    3 rows in set (0.00 sec)
    #               
    MySQL [test]> select * from account;
    +----+---------+
    | id | balance |
    +----+---------+
    | 1 |   300 |
    | 2 |   600 |
    | 3 |   200 |
    +----+---------+
    3 rows in set (0.00 sec)
    #  B         ,  A        
    MySQL [test]> select * from account;
    +----+---------+
    | id | balance |
    +----+---------+
    | 1 |   150 |
    | 2 |   600 |
    | 3 |   200 |
    +----+---------+
    3 rows in set (0.00 sec)
    # A     B        ,        
    MySQL [test]> update account set balance = balance + 1000 where id = 4;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1 Changed: 1 Warnings: 0
    #     ,      ,    
    MySQL [test]> select * from account;
    +----+---------+
    | id | balance |
    +----+---------+
    | 1 |   400 |
    | 2 |   600 |
    | 3 |   200 |
    | 4 |  2000 |
    +----+---------+
    4 rows in set (0.00 sec)
    #     
    MySQL [test]> commit;
    Query OK, 0 rows affected (0.01 sec)
    
    # B       :          
    MySQL [test]> set tx_isolation='repeatable-read';
    Query OK, 0 rows affected, 1 warning (0.00 sec)
    #     
    MySQL [test]> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    #     ,    
    MySQL [test]> update account set balance = balance - 100 where id = 1;
    Query OK, 1 row affected (0.00 sec)
    Rows matched: 1 Changed: 1 Warnings: 0
    
    MySQL [test]> commit;
    Query OK, 0 rows affected (0.01 sec)
    #       
    MySQL [test]> start transaction;
    Query OK, 0 rows affected (0.00 sec)
    #       
    MySQL [test]> insert into account(id,balance) values (4,1000);
    Query OK, 1 row affected (0.01 sec)
    MySQL [test]> commit;
    Query OK, 0 rows affected (0.00 sec)
    마지막 직렬 화:set txisolation='serializable';자체 적 으로 검증 할 수 있 고 위의 모든 문 제 를 해결 할 수 있 지만 일반적으로 사용 되 지 않 습 니 다.일치 성 을 확보 하 는 동시에 성능 이 큰 폭 으로 떨 어 지고 동시성 이 매우 낮 으 며 기본 적 으로 중복 읽 을 수 있 습 니 다.
    격 리 단 계 를 통 해 어느 정도 에 업무 병행 문 제 를 처리 할 수 있 고 그 밖 에 다른 수단 이 있 으 므 로 추 후 다시 탐구 할 것 이다.
    이상 은 MySQL 의 격 리 단 계 를 전면적으로 분석 하 는 상세 한 내용 입 니 다.MySQL 격 리 단계 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!

    좋은 웹페이지 즐겨찾기