>  기사  >  데이터 베이스  >  MySQL 아키텍처

MySQL 아키텍처

巴扎黑
巴扎黑원래의
2017-06-23 14:50:581005검색

MySQL 아키텍처의 첫 번째 장을 검토하고 "고성능MySQL"의 역사

1.1 MySQL 논리 아키텍처

Reference

그림 1-1: MySQL 서버 논리 아키텍처 다이어그램

최상위 수준 서비스는 MySQL에만 국한되지 않습니다. 대부분의 웹 기반 클라이언트/서버 도구 또는 서비스는 유사한 아키텍처를 가지고 있습니다. 접속처리, 권한인증, 보안 등

 두 번째 계층 아키텍처는 MySQL에서 더 흥미로운 부분입니다. 쿼리 구문 분석, 분석, 최적화, 캐싱 및 모든 내장 기능(예: 날짜, 시간, 수학 및 암호화 기능)을 포함하여 MySQL의 핵심 서비스 기능 대부분이 이 계층에 있습니다. 레이어 레이어 구현: 저장 프로시저, 트리거, 뷰 등

 세 번째 레이어에는 스토리지 엔진이 포함되어 있습니다. 스토리지 엔진은 MySQL에서 데이터의 저장 및 검색을 담당합니다. GNU/Linux의 다양한 파일 시스템과 마찬가지로 각 스토리지 엔진에는 장점과 단점이 있습니다. 서버는 API를 통해 스토리지 엔진과 통신합니다. 이러한 인터페이스는 서로 다른 스토리지 엔진 간의 차이점을 보호하여 이러한 차이점을 상위 계층 쿼리 프로세스에 투명하게 만듭니다. 스토리지 엔진 API에는 "트랜잭션 시작" 또는 "기본 키를 기반으로 레코드 행 추출"과 같은 작업을 수행하기 위한 수십 개의 하위 수준 함수가 포함되어 있습니다. 그러나 스토리지 엔진은 SQL을 구문 분석하지 않으며 서로 다른 스토리지 엔진은 서로 통신하지 않고 단순히 상위 서버의 요청에 응답합니다.

1.2 동시성 제어

1.2.1 읽기-쓰기 잠금

이 두 가지 유형의 잠금은 일반적으로 공유 잠금 및 배타적 잠금이라고 하며 읽기 잠금 및 쓰기 잠금(쓰기 잠금)이라고도 합니다. 읽기 잠금은 공유되거나 차단되지 않습니다. 여러 클라이언트가 서로 간섭하지 않고 동시에 동일한 리소스를 읽을 수 있습니다. 쓰기 잠금은 배타적입니다. 즉, 쓰기 잠금이 다른 쓰기 잠금과 읽기 잠금을 차단한다는 의미입니다.

1.2.2 잠금 세분성

 가장 중요한 두 가지 잠금 전략: 테이블 잠금과 행 수준 잠금

테이블 잠금(테이블 잠금)

 테이블 잠금은 MySQL에서 가장 기본적인 잠금 전략이며 최소한의 잠금 전략입니다. 오버헤드. 전체 테이블이 잠깁니다. 사용자가 테이블에 대한 쓰기 작업(삽입, 삭제, 업데이트 등)을 수행하려면 먼저 쓰기 잠금을 획득해야 합니다. 이는 다른 사용자가 테이블에 대한 모든 읽기 및 쓰기 작업을 차단하는 것입니다. 쓰기 잠금이 없는 경우에만 다른 읽기 사용자가 읽기 잠금을 얻을 수 있으며 읽기 잠금은 서로를 차단하지 않습니다.

 특정 시나리오에서는 테이블 잠금 장치의 성능도 좋을 수 있습니다. 예를 들어 READ LOCAL 테이블 잠금은 특정 유형의 동시 쓰기 작업을 지원합니다. 또한 쓰기 잠금도 읽기 잠금보다 우선순위가 높으므로 쓰기 잠금 요청이 읽기 잠금 큐 앞에 삽입될 수 있습니다(쓰기 잠금은 잠금 큐의 읽기 잠금 앞에 삽입될 수 있지만 읽기 잠금은 읽기 잠금 앞에 삽입될 수 있음). 잠금은 삽입할 수 없음)을 쓰기 잠금 앞에 삽입하세요.

행 수준 잠금(행 잠금)

  행 수준 잠금은 동시 처리를 최대한 지원할 수 있습니다(잠금 오버헤드도 가장 큽니다). 우리 모두 알고 있듯이 행 수준 잠금은 InnoDB, XtraDB 및 기타 스토리지 엔진에서 구현됩니다. 행 수준 잠금은 스토리지 엔진 계층에서만 구현되고 MySQL 서버 계층에서는 구현되지 않습니다. 서버 계층은 스토리지 엔진의 잠금 구현에 대한 지식이 없습니다.

1.3 거래

거래는 ACID 원칙을 지원합니다.

원자성

  트랜잭션은 분할할 수 없는 최소 작업 단위로 간주되어야 합니다.

Consistency(일관성)

  데이터베이스는 항상 하나의 일관된 상태에서 다른 일관된 상태로 전환됩니다.

Isolation

일반적으로 한 트랜잭션에서 수정한 내용은 최종적으로 커밋되기 전에 다른 트랜잭션에 표시되지 않습니다.

Durability

트랜잭션이 커밋되면 수정 사항이 데이터베이스에 영구적으로 저장됩니다.

1.3.1 격리 수준

다음은 4가지 격리 수준에 대한 간략한 소개입니다.

READ UNCOMMITTED(커밋되지 않은 읽기)

 READ UNCOMMITTED 수준에서는 트랜잭션의 수정 사항이 커밋되지 않은 경우에도 다른 트랜잭션에 표시됩니다. 트랜잭션은 커밋되지 않은 데이터를 읽을 수 있으며, 이를 더티 읽기(dirty read)라고도 합니다. 이 수준은 많은 문제를 일으킬 수 있습니다. READ UNCOMMITTED는 다른 수준에 비해 그다지 좋지는 않지만 실제로 필요한 이유가 없으면 거의 사용되지 않습니다.

읽어 커밋됨

 대부분의 데이터베이스 시스템의 기본 격리 수준은 READ COMMITTED입니다(MySQL은 아님). 트랜잭션이 처음부터 커밋될 때까지 수정된 사항은 다른 트랜잭션에 표시되지 않습니다. 동일한 쿼리를 두 번 실행하면 다른 결과가 나올 수 있으므로 이 수준을 반복 불가능 읽기라고도 합니다.

REPEATABLE READ(반복 읽기)

  REPEATABLE READ는 더티 읽기 문제를 해결합니다. 이 수준은 동일한 트랜잭션에서 동일한 레코드를 여러 번 읽은 결과의 일관성을 보장합니다. 그러나 이론적으로 반복 읽기 격리 수준은 여전히 ​​다른 팬텀 읽기(Phantom Read) 문제를 해결할 수 없습니다. 소위 팬텀 읽기는 트랜잭션이 특정 범위의 레코드를 읽을 때 다른 트랜잭션이 해당 범위에 새 레코드를 삽입하는 것을 의미합니다. 이전 트랜잭션이 해당 범위의 레코드를 다시 읽으면 팬텀 행이 생성됩니다. InnoDB 및 XtraDB 스토리지 엔진은 MVCC(다중 버전 동시성 제어)를 통해 팬텀 읽기 문제를 해결합니다.

 반복 읽기는 MySQL의 기본 트랜잭션 격리 수준입니다.

SERIALIZABLE(직렬화 가능)

 SERIALIZABLE은 가장 높은 격리 수준입니다. 트랜잭션을 순차적으로 실행함으로써 앞서 언급한 팬텀 읽기 문제를 방지합니다. 간단히 말해서 SERIALIZABLE은 검색된 데이터의 모든 행을 잠그므로 많은 시간 초과 및 잠금 경합 문제가 발생할 수 있습니다. 이 격리 수준은 실제 애플리케이션에서는 거의 사용되지 않으며 데이터 일관성을 보장하는 데 매우 필요하고 동시성이 허용되지 않는 경우에만 고려해야 합니다.

1.3.2 교착상태

교착상태는 두 개 이상의 트랜잭션이 동일한 자원에서 서로를 점유하고, 서로가 점유하고 있는 자원에 대한 잠금을 요청하여 악순환을 일으키는 현상이다. 여러 트랜잭션이 서로 다른 순서로 리소스를 잠그려고 하면 교착 상태가 발생할 수 있습니다. 여러 트랜잭션이 동시에 동일한 리소스를 잠그는 경우에도 교착 상태가 발생할 수 있습니다.

 이 문제를 해결하기 위해 데이터베이스 시스템은 다양한 교착 상태 감지 및 교착 상태 시간 초과 메커니즘을 구현합니다. InnoDB 스토리지 엔진과 같은 보다 복잡한 시스템은 교착 상태 순환 종속성을 감지하고 즉시 오류를 반환하는 능력이 더 뛰어납니다. 이 솔루션은 매우 효과적입니다. 그렇지 않으면 교착 상태로 인해 쿼리 속도가 매우 느려집니다. 또 다른 해결책은 쿼리 시간이 잠금 대기 시간 초과 설정에 도달하면 잠금 요청을 포기하는 것입니다. 이 방법은 일반적으로 좋지 않습니다. 교착 상태를 처리하는 InnoDB의 현재 방법은 최소 행 수준 배타적 잠금을 보유한 트랜잭션을 롤백하는 것입니다(이것은 비교적 간단한 교착 상태 롤백 알고리즘입니다).

 잠금의 동작과 순서는 스토리지 엔진과 관련이 있습니다. 동일한 순서로 명령문을 실행하면 일부 스토리지 엔진에서는 교착 상태가 발생하지만 다른 스토리지 엔진에서는 발생하지 않습니다. 교착 상태는 두 가지 이유로 발생합니다. 일부는 피하기 어려운 실제 데이터 충돌로 인해 발생하지만 일부는 전적으로 스토리지 엔진이 구현되는 방식으로 인해 발생합니다.

1.3.3 트랜잭션 로그

트랜잭션 로그를 사용하면 스토리지 엔진은 테이블 데이터를 수정할 때 메모리 복사본만 수정하면 되며, 매번 업데이트하는 대신 하드 디스크에 유지되는 트랜잭션 로그에 수정 동작을 기록하면 됩니다. 수정된 데이터 자체는 디스크에 유지됩니다. 트랜잭션 로그가 추가됩니다. 트랜잭션 로그가 지속되면 메모리의 수정된 데이터가 백그라운드에서 디스크로 천천히 플러시될 수 있습니다. 현재 대부분의 스토리지 엔진은 이러한 방식으로 구현되며, 이를 일반적으로 미리 쓰기 로깅(Write-Ahead Logging)이라고 합니다. 데이터를 수정하려면 디스크에 두 번 써야 합니다.

  데이터 수정 사항이 트랜잭션 로그에 기록되고 지속되었지만 데이터 자체가 디스크에 다시 기록되지 않아 시스템이 충돌하는 경우 스토리지 엔진은 다시 시작할 때 이 수정된 데이터를 자동으로 복원할 수 있습니다. 구체적인 복구 방법은 스토리지 엔진에 따라 다릅니다.

1.3.4 MySQL의 트랜잭션

1.4 다중 버전 동시성 제어

MVCC 구현은 특정 시점의 데이터 스냅샷을 저장하여 수행됩니다. 즉, 실행하는 데 시간이 얼마나 걸리더라도 각 트랜잭션에 표시되는 데이터는 일관됩니다. 트랜잭션이 시작되는 시간에 따라 동일한 테이블에 있는 각 트랜잭션이 동시에 보는 데이터는 다를 수 있습니다. 아래에서는 InnoDB 동작의 단순화된 버전을 통해 MVCC가 어떻게 작동하는지 보여줍니다.

 InnoDB의 MVCC는 각 레코드 행 뒤에 두 개의 숨겨진 열을 저장하여 구현됩니다. 이 두 열 중 하나는 행 생성 시간을 보유하고 다른 하나는 행 만료 시간(또는 삭제 시간)을 보유합니다. 물론 저장되는 것은 실제 시간 값이 아니라 시스템 버전 번호이다. 새로운 트랜잭션이 시작될 때마다 시스템 버전 번호가 자동으로 증가됩니다. 트랜잭션 시작 시 시스템 버전 번호는 쿼리된 각 레코드 행의 버전 번호와 비교하는 데 사용되는 트랜잭션 버전 번호로 사용됩니다. REPEATABLE READ 격리 수준에서 MVCC가 구체적으로 어떻게 작동하는지 살펴보겠습니다.

SELECT

InnoDB는 다음 두 가지 조건에 따라 레코드의 각 행을 확인합니다.

    가. InnoDB는 버전이 현재 트랜잭션 버전보다 이전인 데이터 행만 찾습니다(즉, 행의 시스템 버전 번호가 트랜잭션의 시스템 버전 번호보다 작거나 같음). 이렇게 하면 트랜잭션에서 행을 읽을 수 있습니다. 트랜잭션이 시작되기 전에 이미 존재합니다. 트랜잭션 자체에 의해 삽입되거나 수정되었습니다.

b. 삭제된 행 버전이 정의되지 않았거나 현재 트랜잭션 버전 번호보다 큽니다. 이렇게 하면 트랜잭션이 읽은 행이 트랜잭션이 시작되기 전에 삭제되지 않았음을 보장합니다.

​ 위 두 조건을 모두 만족하는 레코드만 쿼리 결과로 반환될 수 있습니다.

INSERT

InnoDB는 현재 시스템 버전 번호를 새로 삽입된 각 행의 행 버전 번호로 저장합니다.

DELETE

​​InnoDB는 현재 시스템 버전 번호를 삭제된 각 행의 행 삭제 식별자로 저장합니다.

UPDATE

​​InnoDB는 새로운 레코드 행을 삽입하고, 현재 시스템 버전 번호를 행 버전 번호로 저장하고, 현재 시스템 버전 번호를 행 삭제 식별자로 원래 행에 저장합니다.

  대부분의 읽기 작업을 잠그지 않고 수행할 수 있도록 이 두 개의 추가 시스템 버전 번호를 저장하세요. 이 디자인은 데이터 읽기 작업을 매우 간단하게 만들고 성능도 매우 좋으며 표준을 충족하는 행만 읽도록 보장합니다. 단점은 레코드의 각 행에 추가 저장 공간, 더 많은 행 확인 및 일부 추가 유지 관리 작업이 필요하다는 것입니다.

 MVCC는 REPEATABLE READ와 READ COMMITTED라는 두 가지 격리 수준에서만 작동합니다. 다른 두 격리 수준은 MVCC Note 4와 호환되지 않습니다. READ UNCOMMITTED는 항상 현재 트랜잭션 버전을 준수하는 데이터 행이 아닌 최신 데이터 행을 읽기 때문입니다. SERIALIZABLE은 읽은 모든 행을 잠급니다.

1.5 MySQL 스토리지 엔진

파일 시스템에서 MySQL은 각 데이터베이스(스키마라고도 함)를 데이터 디렉터리 아래의 하위 디렉터리로 저장합니다. 테이블을 생성할 때 MySQL은 테이블 정의를 저장하기 위해 데이터베이스 하위 디렉터리에 테이블과 동일한 이름을 가진 .frm 파일을 생성합니다. 예를 들어, MyTable이라는 테이블을 생성하면 MySQL은 테이블 정의를 MyTable.frm 파일에 저장합니다. MySQL은 파일 시스템 디렉터리와 파일을 사용하여 데이터베이스와 테이블 정의를 저장하기 때문에 대소문자 구분은 특정 플랫폼과 밀접하게 관련되어 있습니다. Windows에서는 대소문자를 구분하지 않습니다. Unix와 같은 경우에는 대소문자를 구분합니다. 다양한 스토리지 엔진이 다양한 방식으로 데이터와 인덱스를 저장하지만, 테이블 정의는 MySQL 서비스 계층에서 동일하게 처리됩니다.

  SHOW TABLE STATUS 명령(MySQL 5.0 이상 버전에서는 INFORMATION SCHEMA에서 해당 테이블을 쿼리할 수도 있음)을 사용하여 테이블 관련 정보를 표시할 수 있습니다. 예를 들어 mysql 데이터베이스의 사용자 테이블의 경우:

mysql> SHOW TABLE STATUS LIKE 'user': 6

Avg_row_length: 59

데이터 길이: 356

최대 데이터 길이: 4294967295

인덱스 길이: 2048

Data_free: 0

Auto_increment: NULL

Create_time: 2002-01-24 18:07:17

Update_time : 2002-01-24 21 : 56 : 29

          Check_time: NULL

                                              

세트 내 1행( o.oo 초)

elm out 결과는 이것이 MyISAM 테이블임을 보여줍니다. 출력에는 통계뿐만 아니라 다른 많은 정보도 있습니다. 다음은 각 줄의 의미에 대한 간략한 소개입니다.

Name

테이블 이름입니다.

Engine
테이블의 스토리지 엔진 유형입니다. 이전 버전에서는 열 이름이 Engine이 아니라 Type이었습니다.

행 형식
행 형식. MyISAM 테이블의 경우 선택적 값은 동적, 고정 또는 압축입니다. Dynamic의 행 길이는 가변적이며 일반적으로 VARCHAR 또는 BLOB와 같은 가변 길이 필드를 포함합니다. 고정의 행 길이는 고정되어 있으며 CHAR 및 INTEGER와 같은 고정 길이 열만 포함합니다. 압축된 행은 압축된 테이블에만 존재합니다.

Rows
테이블의 행 수입니다. MyISAM 및 기타 스토리지 엔진의 경우 값은 정확하지만 InnoDB의 경우 추정치입니다.

Avg_row_length

각 줄에 포함된 평균 바이트 수입니다.

Data_length

테이블 데이터의 크기(바이트)입니다.

Max- data_length

테이블 데이터의 최대 용량 이 값은 스토리지 엔진과 관련이 있습니다.

Index_length

인덱스의 크기(바이트)입니다.

Data_free

MyISAM 테이블의 경우 할당되었지만 현재 사용되지 않는 공간을 나타냅니다. 이 부분에는 이전에 삭제된 행과 나중에 INSERT에서 사용할 수 있는 공간이 포함됩니다.

Auto_increment

다음 AUTO INCREMENT의 값입니다.

Create_time

테이블 생성 시간입니다.

Update_time

테이블 데이터의 마지막 수정 시간입니다.

Check_ time

CKECK TABLE 명령이나 myisamchk 도구를 사용하여 테이블을 마지막으로 확인한 시간입니다.

Collation

테이블의 기본 문자 집합 및 문자 열 조합입니다.

Checksum

활성화하면 전체 테이블의 실시간 체크섬이 저장됩니다.

Create_options

테이블을 생성할 때 지정한 기타 옵션입니다.

Comment

이 열에는 기타 추가 정보가 포함되어 있습니다. MyISAM 테이블의 경우 테이블 생성 시 포함된 설명이 저장됩니다. InnoDB 테이블의 경우 InnoDB 테이블스페이스의 남은 공간 정보가 저장된다. 보기인 경우 이 열에는 "VIEW"라는 텍스트 단어가 포함됩니다.

1.6 MySQL 타임라인

1.7 MySQL 개발 모델

참조: "고성능 MySQL"

위 내용은 MySQL 아키텍처의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.