Mysql 아키텍처 및 내부 모듈
데모 환경:
MySQL 5.7
스토리지 엔진: InnoDB
1. 쿼리 SQL은 어떻게 실행됩니까?
데이터베이스를 운영하기 위한 프로그램이나 도구의 경우 첫 번째 단계는 데이터베이스와의 연결을 설정하는 것입니다.
1. 통신 프로토콜
먼저 MySQL은 기본 포트(3306)에서 수신 대기 중인 서비스를 실행해야 합니다.
통신 프로토콜
MySQL은 다양한 통신 프로토콜을 지원합니다.
첫 번째는 TCP/IP 프로토콜입니다.프로그래밍 언어의 연결 모듈은 TCP 프로토콜을 사용하여 mysqlconnector-java-xxxx.jar와 같은 MySQL 서버에 연결합니다.
두 번째는 유닉스 소켓입니다. 예를 들어, 우리의 Linux 서버는 네트워크 프로토콜을 거치지 않고 MySQL 서버에 연결할 수 있으며 서버의 물리적 파일(mysql.sock)을 사용해야 합니다.
mysql -uroot -p123456
show variables like 'socket';
명명된 파이프(Named Pipes)와 메모리 공유(Share Memory)도 있습니다.
통신 방법
두 번째는 통신 방법입니다.
MySQL은 반이중 통신을 사용합니다.
반이중은 클라이언트가 서버로 데이터를 보내거나 서버가 클라이언트로 데이터를 보내는 것을 의미하며 두 작업이
동시에 발생할 수 없습니다.
따라서 클라이언트가 SQL 문을 서버에 보낼 때 (하나의 연결에서) 데이터를 작은 조각으로 나누어 보낼 수 없으며
SQL 문이 아무리 크더라도 한 번에 보냅니다. 서버로 전송되는 데이터 패킷이 너무 크면 MySQL 서버 구성 max_allowed_packet 매개변수 (기본값은 4M)
의 값을 조정해야 합니다 .
반면에 서버의 경우 모든 데이터가 한 번에 전송되며 원하는 데이터를 얻었다고 작업을 중단할 수 없습니다.
따라서 프로그램 내에서 제한 없이 이러한 조작을 피해야 합니다.
연결 방법
세 번째는 이 부분을 연결하는 것입니다.
MySQL은 짧은 연결과 긴 연결을 모두 지원합니다. 짧은 연결은 작업이 완료된 후 즉시 닫는 것입니다. 긴 연결은 열린 상태로 유지할 수 있으며 이 연결은 프로그램이 나중에 액세스할 때도 사용할 수 있습니다.
비활성 연결이 장기간 지속되면 MySQL 서버의 연결이 끊어집니다.
기본값은 28800초, 8시간입니다.
https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_interactive_timeout
MySQL의 기본 최대 연결 수는 151(버전 5.7)이고 최대 연결 수는 16384(2^14)입니다.
show variables like 'max_connections';
포트 3306의 현재 연결 수 보기
netstat-an|grep3306|wc-l
쿼리의 실행 상태를 보려면 SHOW FULL PROCESSLIST;를 사용하십시오.
몇 가지 일반적인 상태:
2. 쿼리 캐시
MySQL은 내부적으로 캐시 모듈과 함께 제공됩니다. 기본값은 꺼져 있습니다. 주된 이유는 MySQL의 내장 캐시의 애플리케이션 시나리오가 제한되어 있기 때문이며, 첫 번째는 SQL 문이 정확히 동일해야 한다는 것입니다. 두 번째는 테이블의 데이터가 변경되면 이 테이블의 모든 캐시가 무효화된다는 것입니다.
MySQL 5.8에서는 쿼리 캐시가 제거되었습니다.
3. 파싱 및 전처리(Parser & Preprocessor)
다음에 무엇을 할 건가요?
임의의 문자열 fkdljasklf를 실행하면 서버에서 1064 오류를 보고합니다.
[Err] 1064 - SQL 구문에 오류가 있습니다. 라인 1의 'fkdljasklf' 근처에서 사용할 올바른 구문은 MySQL 서버 버전에 해당하는 설명서를 확인하십시오.
서버는 내가 입력한 내용이 잘못되었다는 것을 어떻게 알 수 있습니까?
또는 완벽하게 올바른 구문으로 SQL을 입력했지만 테이블 이름이 존재하지 않는 경우 어떻게 찾았습니까?
이것은 MySQL의 파서 파서 및 전처리기 전처리 모듈입니다.
이 단계에서 가장 중요한 것은 SQL 문에 대한 어휘 및 문법 분석과 의미 분석을 수행하는 것입니다.
어휘 분석
어휘 분석은 완전한 SQL 문을 개별 단어로 분해하는 것입니다.
예를 들어 간단한 SQL 문은 다음과 같습니다.
select name from user where id = 1;
그것은 8개의 기호로 나뉘고 각 기호의 유형, 시작 위치 및 끝 위치를 기록합니다.
문법 분석
두 번째 단계는 문법 분석으로, 문법 분석은 작은따옴표가 닫혀 있는지 등 SQL의 구문을 확인한 다음 MySQL에서 정의한 문법 규칙에 따라 SQL 문에 따라 데이터 구조를 생성합니다. 이 데이터 구조를 구문 분석 트리라고 합니다.
전처리기(Preprocessor)에
잘못된 테이블 이름이 있는 경우 전처리기 처리 중에 오류가 보고됩니다.
결과 구문 분석 트리를 검사하여 구문 분석기가 해결할 수 없는 의미 체계를 해결합니다. 예를 들어 테이블 및 열 이름이 있는지 확인하고 이름과 별칭을 확인하여 모호성이 없는지 확인합니다.
4. 쿼리 최적화 프로그램 및 쿼리 실행 계획
어떤 옵티마이저?
질문: SQL 문을 실행하는 방법은 한 가지뿐입니까? 아니면 데이터베이스가 최종적으로 실행하는 SQL이 우리가 보낸 SQL과 같습니까?
이에 대한 대답은 '아니오'입니다. SQL 문은 여러 가지 방법으로 실행할 수 있습니다. 그러나 실행 방법이 너무 많은 경우 이러한 실행 방법은 어떻게 얻습니까? 결국 어떤 것을 선택해야 할까요? 어떤 기준으로 고를까?
이것은 MySQL 쿼리 최적화 모듈(Optimizer)입니다.
쿼리 옵티마이저의 목적은 파스 트리를 기반으로 다양한 실행 계획을 생성한 후 최적의 실행 계획을 선택하는 것인데, MySQL은 비용 기반 옵티마이저를 사용하는데 비용이 가장 적은 실행 계획을 사용한다.
쿼리 비용을 보려면 다음 명령을 사용하십시오.
show status like 'Last_query_cost';
– 조회를 완료하려면 여러 4K 데이터 페이지를 무작위로 읽어야 함을 의미합니다.
옵티마이저가 어떻게 작동하는지 알고 싶다면 여러 실행 계획을 생성합니다. 각 실행 계획의 비용은 얼마이며 어떻게 해야 합니까?
옵티마이저는 실행 계획을 어떻게 얻습니까?
https://dev.mysql.com/doc/internals/en/optimizer-tracing.html
먼저 옵티마이저 추적을 활성화해야 합니다(기본적으로 꺼져 있음).
SHOW VARIABLES LIKE 'optimizer_trace';
set optimizer_trace="enabled=on";
참고로 이 스위치를 켜면 최적화 분석 결과를 테이블에 기록해야 하므로 성능 소모가 크므로 가볍게 켜거나 확인 후 끄는(off로 변경) 것이 좋다.
그런 다음 SQL 문을 실행하면 옵티마이저가 실행 계획을 생성합니다.
selectt.tcidfromteachert,teacher_contacttcwheret.tcid=tc.tcid;
현재 옵티마이저 분석 프로세스는 시스템 테이블에 기록되어 있으며 쿼리할 수 있습니다.
select*frominformation_schema.optimizer_trace\G
expand_query는 최적화된 SQL 문입니다.
모든 실행 계획은 간주_실행_계획에 나열됩니다.
끄는 것을 잊지 마십시오.
setoptimizer_trace="enabled=off";
SHOWVARIABLESLIKE'optimizer_trace';
옵티마이저는 무엇을 할 수 있습니까?
MySQL의 옵티마이저는 어떤 유형의 최적화를 처리할 수 있습니까?
예를 들면 다음과 같습니다.
1. 여러 테이블에서 연결된 쿼리를 수행할 때 어떤 테이블의 데이터가 참조 테이블로 사용됩니다.
2. a=1이고 b=2이고 c=3인 사용자로부터 *를 선택하고 c=3인 경우 100개, b=2인 경우 200개, a=1인 경우 300개의 결과가 있는 경우 어떻게 생각하십니까
? 필터가 먼저 수행됩니까?
3. 조건에 항등식 또는 부등식이 있는 경우 제거할 수 있습니까?
4. 쿼리 데이터, 값을 인덱스에서 직접 얻을 수 있는지 여부.
5. count(), min(), max(), 예를 들어 인덱스에서 직접 값을 얻을 수 있는지 여부.
6. 기타.
옵티마이저가 얻은 결과
옵티마이저는 결국 구문 분석 트리를 데이터 구조인 쿼리 실행 계획으로 전환합니다.
물론 이 실행계획이 반드시 최적의 실행계획일까? MySQL이 모든 실행 계획을 포함하지 않을 수 있기 때문에 반드시 그런 것은 아닙니다.
MySQL은 계획 실행을 위한 도구를 제공합니다. SQL 문 앞에 EXPLAIN을 추가하면 실행 계획 정보를 볼 수 있습니다.
EXPLAINselectnamefromuserwhereid=1;
5. 스토리지 엔진
데이터는 어디에 저장됩니까? 실행 계획은 어디에서 실행됩니까? 누가 그것을 실행할 것인가?
스토리지 엔진에 대한 기본 소개
관계형 데이터베이스에서 데이터는 테이블에 배치됩니다. 이 테이블을 Excel 스프레드시트로 이해할 수 있습니다. 따라서 테이블이 데이터를 저장하는 동안 데이터의 저장 구조도 구성해야 하며, 이 저장 구조는 스토리지 엔진에 의해 결정되므로 스토리지 엔진을 테이블 유형이라고 부를 수도 있습니다.
MySQL에서는 여러 개의 스토리지 엔진이 지원되며 교체가 가능하므로 플러그인 스토리지 엔진이라고 합니다. 왜 그렇게 많은 스토리지 엔진을 사용합니까? 하나로 충분하지 않습니까? 서로 다른 비즈니스 시나리오에서 데이터 작업에 대한 요구 사항이 다르기 때문입니다.이 서로 다른 스토리지 엔진은 서로 다른 스토리지 메커니즘, 인덱싱 방법, 잠금 수준 및 기타 기능을 제공하여 비즈니스 요구 사항을 충족합니다.
스토리지 엔진 보기
데이터베이스 테이블의 스토리지 엔진 보기:
show table status from `training`;
MySQL에서 우리가 생성하는 각 테이블은 자신의 스토리지 엔진을 지정할 수 있으며 하나의 스토리지 엔진만 사용할 수 있는 데이터베이스가 아닙니다. 또한 테이블 생성 후 스토리지 엔진을 수정할 수 있습니다.
데이터베이스에 데이터를 저장하는 경로:
show variables like 'datadir';
각 데이터베이스에는 자체 폴더가 있으며 훈련 데이터베이스를 예로 들어 보겠습니다.
모든 스토리지 엔진에는 테이블 구조 정의 파일인 frm 파일이 있습니다.
서로 다른 스토리지 엔진을 사용하여 데이터베이스에 세 개의 테이블을 만들었습니다.
서로 다른 스토리지 엔진은 서로 다른 방식으로 데이터를 저장하고 서로 다른 파일을 생성합니다.
스토리지 엔진 비교
일반 스토리지 엔진
MySQL 5.5 이전의 기본 스토리지 엔진은 MySQL과 함께 제공되는 MyISAM입니다. 버전 5.5 이후에는 MySQL을 위해 타사에서 개발한 InnoDB로 기본 스토리지 엔진이 변경되었습니다. 왜 변경합니까? 주된 이유는 InnoDB가 높은 비즈니스 일관성 요구 사항이 있는 시나리오에 더 적합한 트랜잭션 및 행 수준 잠금을 지원하기 때문입니다.
데이터베이스가 지원하는 스토리지 엔진 이
명령을 사용하여 스토리지 엔진에 대한 데이터베이스 지원을 확인할 수 있습니다.
SHOWENGINES;
스토리지 엔진에 대한 설명과 트랜잭션 지원, XA 프로토콜 및 세이브포인트가 있습니다.
공식 웹사이트의 스토리지 엔진 소개:
https://dev.mysql.com/doc/refman/5.7/en/storage-engines.html
MyISAM(3个文件)
이 테이블은 설치 공간이 작습니다. 테이블 수준 잠금은 읽기/쓰기 워크로드의 성능을 제한하므로 웹 및 데이터 웨어하우징 구성에서 읽기 전용 또는 읽기 위주의 워크로드에 자주 사용됩니다.
적용 범위는 상대적으로 작습니다. 테이블 수준 잠금은 읽기/쓰기 성능을 제한하므로 웹 및 데이터 웨어하우스 구성에서 읽기 전용 또는 주로 읽기 작업에 자주 사용됩니다.
기능:
1 테이블 수준 잠금을 지원합니다(삽입 및 업데이트는 테이블을 잠급니다). 거래가 지원되지 않습니다.
2는 삽입(insert) 및 쿼리(select) 속도가 빠릅니다.
3은 테이블의 행 수를 저장합니다(카운트가 더 빠름).
4 읽기 전용과 같은 데이터 분석에 적합한 프로젝트.
InnoDB(2 个文件)
MySQL 5.7의 기본 스토리지 엔진. InnoDB는 커밋, 롤백 및 충돌 복구 기능을 통해 사용자 데이터를 보호하는 MySQL용 트랜잭션 안전(ACID 호환) 스토리지 엔진입니다. InnoDB 행 수준 잠금(더 거친 세분성 잠금으로의 에스컬레이션 없음) 및 Oracle 스타일의 일관된 비잠금 읽기는 다중 사용자 동시성과 성능을 향상시킵니다. InnoDB는 클러스터형 인덱스에 사용자 데이터를 저장하여 기본 키를 기반으로 하는 일반적인 쿼리에 대한 I/O를 줄입니다. 데이터 무결성을 유지하기 위해 InnoDB는 FOREIGN KEY 참조 무결성 제약 조건도 지원합니다.
mysql 5.7의 기본 스토리지 엔진. InnoDB는 사용자 데이터를 보호하기 위해 커밋, 롤백 및 충돌 복구 기능을 갖춘 트랜잭션 안전(ACID 호환) MySQL 스토리지 엔진입니다. InnoDB 행 수준 잠금(Coarse-grained 잠금으로 업그레이드되지 않음) 및 Oracle 스타일의 일관된 비잠금 읽기는 다중 사용자 동시성과 성능을 향상시킵니다. InnoDB는 클러스터형 인덱스에 사용자 데이터를 저장하여 기본 키를 기반으로 하는 일반적인 쿼리에 대한 I/O를 줄입니다. 데이터 무결성을 유지하기 위해 InnoDB는 외래 키 참조 무결성 제약 조건도 지원합니다.
특징:
1. 트랜잭션 및 외래 키를 지원하므로 데이터의 무결성 및 일관성이 더 높습니다.
2 행 수준 잠금 및 테이블 수준 잠금을 지원합니다.
3 동시 읽기 및 쓰기 지원, 쓰기는 읽기를 차단하지 않습니다.
4 특별한 인덱스 저장 방법은 IO를 줄이고 쿼리 효율성을 향상시킬 수 있습니다.
5 자주 갱신되는 테이블에 적합하며 동시 읽기 및 쓰기 또는 트랜잭션 처리가 있는 비즈니스 시스템이 있습니다.
메모리(1개 파일)
중요하지 않은 데이터의 빠른 조회가 필요한 환경에서 빠른 액세스를 위해 모든 데이터를 RAM에 저장 이 엔진은 이전에 HEAP 엔진으로 알려져 있었으며 사용 사례가 감소하고 있습니다. 대부분의 또는 모든 데이터를 메모리에 보관하는 범용적이고 내구성 있는 방법이며, NDBCLUSTER는 대규모 분산 데이터 세트에 대한 빠른 키-값 조회를 제공합니다.
중요하지 않은 데이터 액세스의 빠른 조회가 필요한 환경에서 빠른 조회를 위해 모든 데이터를 RAM에 저장합니다. 이 엔진은 이전에 힙 엔진으로 알려져 있었습니다. 사용 사례는 줄어들고 있습니다. InnoDB와 버퍼 풀 메모리 영역은 대부분의 또는 모든 데이터를 메모리에 유지하는 범용적이고 내구성 있는 방법을 제공하는 반면 ndbcluster는 대규모 분산 데이터 세트에 대한 빠른 키-값 조회를 제공합니다.
특징:
데이터를 메모리에 넣으면 읽기 및 쓰기 속도가 매우 빠르지만 데이터베이스가 다시 시작되거나 충돌하면 모든 데이터가 사라집니다. 임시 테이블에만 적합합니다. 기본적으로 해시 인덱스가 사용됩니다. 테이블의 데이터를 메모리에 저장합니다.
CSV(3个文件)
테이블은 실제로 쉼표로 구분된 값이 있는 텍스트 파일입니다. CSV 테이블을 사용하면 CSV 형식으로 데이터를 가져오거나 덤프하여 동일한 형식을 읽고 쓰는 스크립트 및 애플리케이션과 데이터를 교환할 수 있습니다. CSV 테이블은 인덱싱되지 않기 때문에 일반적으로 정상적인 작업 중에는 InnoDB 테이블에 데이터를 보관하고 가져오기 또는 내보내기 단계에서는 CSV 테이블만 사용합니다.
해당 테이블은 실제로 쉼표로 구분된 값이 있는 텍스트 파일입니다. csv 테이블을 사용하면 동일한 형식을 읽고 쓰는 스크립트 및 응용 프로그램과 데이터를 교환하기 위해 csv 형식으로 데이터를 가져오거나 덤프할 수 있습니다. csv 테이블에는 인덱스가 없기 때문에 정상 작동 중에는 innodb 테이블에 데이터를 보관하고 가져오기 또는 내보내기 단계에서만 csv 테이블을 사용하는 것이 일반적입니다.
기능:
빈 줄은 허용되지 않으며 색인은 지원되지 않습니다. 형식은 공통적이며 직접 편집할 수 있어 서로 다른 데이터베이스 간에 가져오기 및 내보내기에 적합합니다.
아카이브(파일 2개) 이 작고 색인화되지 않은 테이블
은 거의 참조되지 않는 대량의 기록, 아카이브 또는 보안 감사 정보를 저장하고 검색하기 위한 것입니다.
기능:
색인을 지원하지 않으며 업데이트 삭제를 지원하지 않습니다.
6. 쿼리 실행 엔진, 반환 결과
스토리지 엔진을 사용하여 해당 API를 제공하여 스토리지 엔진의 작업을 완료하는 실행 엔진. 마지막으로 결과가 없더라도 클라이언트에 데이터를 반환합니다.
2. MySQL 아키텍처 요약
계층화된 아키텍처
전반적으로 MySQL을 3개의 계층으로 나눌 수 있습니다.
모듈에 대한 자세한 설명
1.Connector: PHP, Python, Java JDBC 등 다양한 언어와 SQL 간의 상호 작용을 지원하는 데 사용됩니다.
2.Management Services & Utilities: 백업 및 복구, MySQL 복제, 클러스터링 등을 포함한 시스템 관리 및 제어 도구
3.Connection Pool : 연결 풀, 버퍼링이 필요한 리소스 관리, 사용자 암호 권한 스레드 등
4.SQL 인터페이스: 사용자의 SQL 명령을 수신하고 사용자가 요구하는 쿼리 결과를 반환하는 데 사용
5.Parser: SQL 문을 구문 분석하는 데 사용됩니다.
6.최적화기: 쿼리 최적화기
7. 캐시 및 버퍼: 쿼리 캐시, 행 레코드 캐시 외에도 테이블 캐시, 키 캐시, 권한 캐시 등이 있습니다.
8.Pluggable Storage Engines: 특정 파일을 처리하기 위해 서비스 계층에 API를 제공하는 Pluggable 스토리지 엔진.
3. 업데이트 SQL은 어떻게 실행됩니까?
데이터베이스에서 우리가 말하는 업데이트 작업에는 실제로 업데이트, 삽입 및 삭제가 포함됩니다. 업데이트 프로세스와 쿼리 프로세스의 차이점은 무엇입니까?
기본 프로세스도 동일합니다. 즉, 파서와 최적화 프로그램에 의해 처리되고 최종적으로 실행자에게 전달됩니다.
차이점은 검증된 데이터를 얻은 후 작업에 있습니다.
우선 InnoDB에는 메모리 버퍼 풀(buffer pool)이 있다. IO 비용이 너무 높기 때문에 매번
디스크에 데이터 업데이트를 직접 쓰지 않고 버퍼 풀에 먼저 씁니다. 메모리의 데이터 페이지가 디스크 데이터와 일치하지 않는 경우 이를 더티 페이지라고 합니다.
InnoDB에는 버퍼 풀 데이터를 디스크에 기록하는 특수 스레드가 있으며 가끔씩 디스크에 여러 수정 사항을 한 번에 기록합니다.
여기에 문제가 있는데 더티 페이지가 디스크에 기록되기 전에 서버가 실패하면 메모리의 데이터가 손실됩니다. 또는 더러워진 상태에서 중간에 데이터 파일을 파괴하기도 합니다. 따라서 지속적인 메커니즘이 있어야 합니다.
redo log
InnoDB는 redo log(redo log)라는 로그 파일을 도입하여 메모리 데이터에 대한 모든 수정 작업을 로그 파일에 기록함 서버에 문제가 있을 경우 로그 파일에서 데이터를 읽어 복원함 Data - Use 이는 트랜잭션 지속성을 달성하기 위한 것입니다.
리두 로그의 특징은 무엇입니까?
1. 물리 로그에 속하는 수정된 값을 기록
2. 리두 로그의 크기가 고정되어 이전 내용을 덮어쓰므로 데이터 롤백/데이터 복구에 사용할 수 없습니다.
3. 리두 로그는 InnoDB 스토리지 엔진에 의해 구현되며 모든 스토리지 엔진에 있는 것은 아닙니다.
binlog
MySQL Server 계층에는 모든 스토리지 엔진에서 사용할 수 있는 binlog라는 로그 파일도 있습니다.
Binlog는 모든 DDL 및 DML 문을 이벤트 형태로 기록하고(논리 로그에 속하는 데이터 값이 아닌 작업을 기록하기 때문에) 마스터-슬레이브 복제 및 데이터 복구에 사용할 수 있습니다.
마스터-슬레이브 복제
데이터 복구
리두 로그와 달리 파일 내용을 추가할 수 있으며 고정된 크기 제한이 없습니다.
이 두 로그를 사용하여 업데이트 문이 실행되는 방식을 살펴보겠습니다.
예: update teacher set name='jim' where name ='666'
1. 먼저 이 데이터를 쿼리합니다. 캐시가 있으면 캐시도 사용합니다.
2. 이름을 jim으로 변경한 다음 엔진의 API 인터페이스를 호출하고 이 데이터 줄을 메모리에 쓰고 동시에 리두 로그를 기록합니다. 이때 리두 로그는 준비 상태에 들어간 후 실행자에게 실행이 완료되었으며 언제든지 제출할 수 있음을 알립니다.
3. Executor는 알림을 받은 후 binlog를 기록한 다음 스토리지 엔진 인터페이스를 호출하여 redo 로그를 커밋 상태로 설정합니다.
4. 업데이트가 완료되었습니다.
질문: 2단계 커밋(XA)을 사용하는 이유는 무엇입니까?
예:
이름을 jim으로 변경하면 redo 로그가 기록되고 bin 로그가 기록되지 않으면 MySQL이 다시 시작됩니다.
리두 로그는 데이터를 복원할 수 있기 때문에 디스크에 쓰는 것은 짐이다. 그러나 bin 로그에는 논리 로그가 기록되지 않으므로 이때 binlog를 사용하여 데이터를 복원하거나 슬레이브 데이터베이스에 동기화하면 데이터 불일치가 발생합니다.
따라서 두 개의 로그를 작성하는 경우에는 binlog가 트랜잭션 코디네이터 역할을 합니다. 준비 또는 커밋 또는 롤백을 실행하도록 InnoDB에 알립니다.
간단히 말해서 분산 트랜잭션과 유사한 두 가지 로그 쓰기 작업이 있으며 2단계 커밋이 없으면 둘 다 성공하거나 실패할 것이라는 보장이 없습니다.