MySQL 인터뷰를 철저하게 이해하기 8부작 에세이

내용은 내 학습 웹사이트인 topjavaer.cn에서 발췌되었습니다.

MySQL이란?

MySQL은 데이터를 테이블 형식으로 저장하는 관계형 데이터베이스입니다. 엑셀의 표라고 생각하면 되는데, 데이터가 표 형태로 저장되기 때문에 표 구조(행과 열)를 갖고 있습니다. 행은 데이터의 각 행을 나타내고 열은 해당 행의 각 값을 나타냅니다. 열의 값에는 정수, 문자열, 날짜 등과 같은 데이터 유형이 있습니다.

데이터베이스의 세 가지 주요 패러다임

첫 번째 정규형 1NF

데이터베이스 테이블 필드의 원자성을 보장합니다. 매우 포괄적인 Java 인터뷰 웹사이트

userInfo예를 들어 : 필드는 첫 번째 정규형에 따라 : : 두 개의 필드 广东省 10086'로 분할되어야 합니다 .userInfo广东省 userTel 10086

두 번째 정규형 2NF

첫째, 첫 번째 정규형을 충족해야 하며, 두 부분도 포함해야 합니다. 첫째, 테이블에 기본 키가 있어야 하고, 둘째, 기본 키가 아닌 열은 기본 키에 완전히 의존해야 하며, 기본 키에만 의존할 수는 없습니다. 기본 키의 일부입니다.

예를 들어. 교과목 선택 관계 테이블은 student_course(student_no, Student_name, age, Course_name, grade,credit)이고 기본 키는 (student_no,course_name)이라고 가정합니다. 학점은 과목명에 전적으로 의존하고, 이름과 나이는 학생 번호에 전적으로 의존하는데, 이는 두 번째 패러다임을 따르지 않으며 데이터 중복으로 이어집니다(학생은 n개의 과목을 선택하고 이름에 대한 n개의 기록이 있습니다). 및 연령) 및 삽입이상(신규교과목 삽입, 학생증이 없으므로 신규수업기록을 저장할 수 없음) 등의 문제가 있습니다.

student학생: (stuent_no, school_name, age), 강좌: course(course_name, 학점), 강좌 선택 관계: student_course_relation(student_no, 강좌_name, grade) 의 세 가지 테이블로 분할되어야 합니다 .

제3정규형 3NF

우선 제2정규형을 만족해야 하며, 또한 기본키가 아닌 열은 기본키에 직접 종속되어야 하며 전이적 종속성이 있을 수 없다. 즉, 존재할 수 없습니다. 기본 키가 아닌 열 A는 기본 키가 아닌 열 B에 종속되고 기본 키가 아닌 열 B는 기본 키에 종속됩니다.

학생 관계 테이블이 Student(student_no, Student_name, age, academy_id, academy_telephone)이고 기본 키가 "student number"라고 가정하면, 대학 ID는 학생 번호에 따라 달라지며, 대학 위치 및 대학 전화번호는 학생 번호에 따라 다릅니다. 대학 ID 일관성이 없는 전이적 종속성이 있습니다. 세 번째 패러다임입니다.

학생 관계 테이블은 학생: (student_no, Student_name, age, academy_id), 대학: (academy_id, academy_telephone)의 두 테이블로 나눌 수 있습니다.

2NF와 3NF의 차이점은 무엇입니까?

  • 2NF는 기본 키가 아닌 열이 기본 키에 전적으로 의존하는지 아니면 기본 키의 일부에 의존하는지에 따라 결정됩니다.
  • 3NF는 기본 키가 아닌 열이 기본 키 또는 기본 키가 아닌 열에 직접적으로 종속되는지 여부를 기반으로 합니다.

이 기사는 컴퓨터 기초, Java 기초, 멀티스레딩, JVM, 데이터베이스, Redis, Spring, Mybatis, SpringMVC, SpringBoot, 분산, 마이크로서비스, 디자인 패턴, 아키텍처, 학교 모집 및 사회 모집을 포함하는 Github 저장소에 포함되었습니다 . 공유 등 핵심 지식 포인트, 스타에 오신 것을 환영합니다!

링크(클릭 가능): Github 주소

Github에 접근할 수 없는 경우 gitee 주소로 접근할 수 있습니다.

링크(클릭 가능): gitee 주소

거래의 네 가지 주요 특징은 무엇입니까?

트랜잭션 특성 ACID : 원자성 ( Atomicity), 일관성 ( Consistency), 격리 ( Isolation), 내구성 ( Durability).

  • 원자성은 트랜잭션에 포함된 모든 작업이 성공하거나 실패하고 롤백된다는 의미입니다.
  • 일관성 이란 트랜잭션이 실행 전후에 일관된 상태를 유지해야 함을 의미합니다. 예를 들어, a와 b의 계좌 합계가 1,000위안이고, 두 사람 간의 이체가 성공하거나 실패한 후에도 두 사람의 계좌 합계는 여전히 1,000위안입니다.
  • 격리 . 예를 들어 격리 수준과 관련하여 read committed트랜잭션은 제출된 수정 사항만 읽을 수 있습니다.
  • 내구성 이란 일단 트랜잭션이 커밋되면 데이터베이스의 데이터 변경 사항이 영구적이며 데이터베이스 시스템에 오류가 발생하더라도 트랜잭션 커밋 작업이 손실되지 않음을 의미합니다.

트랜잭션 격리 수준은 무엇입니까?

먼저 더티 읽기(dirty reading), 반복 불가능한 읽기, 팬텀 읽기(phantom reading)라는 개념을 이해하세요.

  • 더티 읽기(Dirty Reading)는 한 트랜잭션 중에 커밋되지 않은 다른 트랜잭션의 데이터를 읽는 것을 의미합니다.
  • 반복 불가능 읽기는 데이터베이스의 특정 레코드 행에 대해 트랜잭션 범위 내의 여러 쿼리가 서로 다른 데이터 값을 반환하는 것을 의미합니다. 이는 다른 트랜잭션이 쿼리 간격 동안 데이터를 수정하고 제출했기 때문입니다.
  • 팬텀 읽기는 트랜잭션이 특정 범위의 레코드를 읽고 다른 트랜잭션이 해당 범위에 새 레코드를 삽입할 때 발생합니다. 팬텀 읽기에 대한 올바른 이해는 트랜잭션 내 읽기 작업의 결론이 후속 비즈니스 실행을 지원할 수 없다는 것입니다. 트랜잭션이 새 레코드를 추가하려고 하고 기본 키가 id이고 추가하기 전에 선택이 실행되었으며 ID가 xxx인 레코드가 발견되지 않았지만 삽입 중에 기본 키 충돌이 발생한다고 가정합니다. 레코드를 읽을 수 있지만 기본 키 충돌이 발견되었습니다. 이는 해당 레코드가 실제로 다른 트랜잭션에 의해 삽입되었지만 현재 트랜잭션에는 표시되지 않기 때문입니다.

반복 불가능 읽기와 더티 읽기의 차이점은 더티 읽기는 트랜잭션이 다른 트랜잭션의 커밋되지 않은 더티 데이터를 읽는 경우이고, 반복 불가능 읽기는 이전 트랜잭션에서 제출된 데이터를 읽는 경우라는 것입니다.

트랜잭션 격리는 위에서 언급한 더티 읽기(dirty read), 반복 불가능한 읽기, 팬텀 읽기(phantom read) 문제를 해결하기 위한 것입니다.

MySQL 데이터베이스가 제공하는 네 가지 격리 수준은 다음과 같습니다.

  • 직렬화 가능 : 트랜잭션이 서로 충돌하지 않도록 강제로 순서를 지정하여 팬텀 읽기 문제를 해결합니다.
  • 반복 읽기 : MySQL의 기본 트랜잭션 격리 수준으로, 동일한 트랜잭션의 여러 인스턴스가 동시에 데이터를 읽을 때 동일한 데이터 행을 볼 수 있도록 보장하여 반복 불가능한 읽기 문제를 해결합니다.
  • 커밋된 읽기 : 트랜잭션은 커밋된 트랜잭션에 의해 변경된 내용만 볼 수 있습니다. 더티 읽기(Dirty Read)를 방지할 수 있습니다.
  • 커밋되지 않은 읽기 : 모든 트랜잭션은 커밋되지 않은 다른 트랜잭션의 실행 결과를 볼 수 있습니다.

격리 수준을 확인합니다.

select @@transaction_isolation;

격리 수준 설정:

set session transaction isolation level read uncommitted;

프로덕션 환경 데이터베이스에는 일반적으로 어떤 격리 수준이 사용됩니까?

대부분의 프로덕션 환경에서는 RC 를 사용합니다 . 왜 RR이 아닌가?

반복 가능 읽기(RR
Read Committed), RC라고 함

이유 1: RR 격리 수준에는 간격 잠금이 있어 RC보다 교착 상태가 발생할 확률이 훨씬 높습니다!
이유 2: RR 격리 수준에서 조건부 열이 인덱스를 놓치면 테이블이 잠깁니다! RC 격리 수준에서는 행만 잠깁니다.

즉, RC는 RR보다 동시성이 높습니다.

그리고 대부분의 시나리오에서는 반복 불가능한 읽기 문제가 허용됩니다. 결국 데이터가 제출되었으니 읽어보는 데에는 큰 문제가 없습니다!

링크(클릭 가능): 매우 포괄적인 Java 인터뷰 웹사이트

인코딩과 문자 집합의 관계

우리는 보통 편집기에서 다양한 중국어, 영어 문자를 입력할 수 있지만 이는 컴퓨터가 읽을 수 있는 것이 아니라 사람이 읽을 수 있는 것입니다.사실 컴퓨터는 실제로 바이너리 0101 형식으로 데이터를 저장하고 전송 합니다 .

그러면 한자와 영문자를 바이너리로 변환하는 규칙이 필요합니다. 그 중 d는 16진수로 64에 해당하며, 이는 01 바이너리 형식으로 변환할 수 있다. 그래서 문자와 숫자가 1:1로 대응되는데, 이것이 ASCII 인코딩 형식입니다.

1바이트를 사용하여 문자를 식별 하며 8位기본 기호 128개와 확장 기호 128개가 있습니다. 영문자와 숫자 만 표현할 수 있습니다 .

이것은 분명히 충분하지 않습니다. 따라서 중국어를 식별하기 위해 GB2312 인코딩 형식이 등장했습니다 . 그리스어를 식별하기 위해 그리스어 인코딩 형식이 등장했고 , 러시아어를 식별하기 위해 cp866 인코딩 형식을 조정했습니다 .

이를 통일하기 위해 2~4바이트를 사용하여 문자를 표현하는 유니코드 인코딩 형식이 등장하여 이론적으로는 모든 기호를 포함할 수 있으며 ASCII 인코딩, 즉 동일한 문자와도 완벽하게 호환됩니다. d는 ASCII에서는 64로 표시되지만 유니코드에서는 여전히 64로 표시됩니다.

그러나 차이점은 ASCII 인코딩은 1바이트로 표시되는 반면 유니코드는 2바이트로 표시된다는 것입니다.

문자 d이기도 합니다. 유니코드는 다음과 같이 ascii보다 1바이트 더 많은 바이트를 사용합니다.

D   ASCII:           01100100
D Unicode:  00000000 01100100

보시다시피, 위의 유니코드 인코딩은 앞이 모두 0이어서 실제로는 유용하지 않지만, 그래도 여전히 1바이트를 차지해 조금 낭비적입니다. 숨겨야 할 때 숨길 수 있다면 많은 공간을 절약할 수 있습니다.이 아이디어에 따르면 UTF-8 인코딩이 있습니다 .

요약하면 특정 규칙에 따라 기호를 이진 코드와 일치시키는 것을 인코딩 이라고 합니다 . 그리고 이렇게 인코딩된 문자를 n개 모으는 것을 흔히 문자 세트 라고 부릅니다 .

예를 들어, utf-8 문자 세트는 utf-8 인코딩 형식의 모든 문자 모음입니다.

mysql이 어떤 문자 세트를 지원하는지 알고 싶습니다. 실행 가능show charset;

utf8과 utf8mb4의 차이점

위에서 언급했듯이 utf-8은 유니코드 기반의 최적화입니다. 유니코드는 모든 문자를 표현할 수 있는 방법이 있으므로 utf-8도 모든 문자를 표현할 수 있습니다. 혼란을 피하기 위해 나중에 utf8이라고 부르 겠습니다 .

mysql이 지원하는 문자 세트에는 utf8 및 utf8mb4가 포함됩니다.

먼저 utf8mb4 인코딩 에 대해 이야기해 보겠습니다 . mb4는 대부분의 바이트를 의미합니다 . 4. 위의 가장 오른쪽 그림에서 볼 수 있듯이 Maxlen최대 4바이트 까지 문자를 표현하는 데 지원하며 현재 알려진 거의 모든 문자를 표현하는 데 사용할 수 있습니다.

데이터베이스의 기본 문자 집합mysql 문자 집합의 utf8 에 대해 이야기해 보겠습니다 . 하지만 이 utf8은 utf8이 아니며 , 이를 작은 utf8 문자 집합이라고 부릅니다. 왜 이렇게 말하는 걸까요? Maxlen을 보면 문자 표현을 위해 최대 3바이트까지 지원한다는 것을 알 수 있기 때문에 utf8mb4의 네이밍 방식에 따르면 좀 더 정확하게 utf8mb3 이라고 불러야 합니다 .

utf8은 일부 문자만 지원하는 utf8mb4의 거세 버전과 같습니다. 예를 들어 emoji이모티콘을 지원하지 않습니다.

mysql이 지원하는 문자 집합에서 세 번째 열인 collation은 문자 집합의 비교 규칙을 나타냅니다 .

예를 들어 "debug"와 "Debug"는 같은 단어인데 대문자 표기가 다른데, 같은 단어로 봐야 할까요?

이때 콜레이션을 사용해야 합니다.

SHOW COLLATION WHERE Charset = 'utf8mb4';어떤 비교 규칙이 지원되는지 확인할 수 있습니다 utf8mb4.

이면 collation = utf8mb4_general_ciutf8mb4 문자 집합 사용을 전제로 문자 단위 ( general)로 비교가 수행되며 대소문자를 구분하지 않음( _ci,case insensitice)을 의미합니다.

이 경우 "디버그"와 "디버그"는 같은 단어입니다.

로 변경하면 바이너리 비트 크기를 하나씩 비교한다는collation=utf8mb4_bin 의미입니다 .

따라서 "디버그"와 "디버그"는 같은 단어가 아닙니다.

그렇다면 utf8에 비해 utf8mb4의 단점은 무엇입니까?

데이터베이스 테이블에서 필드 유형이 문자 수를 의미 한다는 것을 알고 있습니다. char(2)이는 이 테이블에서 어떤 인코딩 문자 세트가 사용되는지에 관계없이 2개의 문자를 배치할 수 있음을 의미합니다 .2

그리고 char은 고정된 길이를 가지고 있습니다 . 2개의 utf8mb4 문자를 맞추기 위해 char은 2*4(maxlen=4)= 8기본적으로 1바이트의 공간을 예약합니다.

utf8mb3인 경우 2 * 3 (maxlen=3) = 6기본적으로 바이트 공간이 예약됩니다. 즉, 이 경우 utf8mb4는 utf8mb3보다 더 많은 공간을 사용합니다.

색인

인덱스란 무엇입니까?

인덱스는 데이터베이스 테이블의 액세스 속도를 향상시키기 위해 스토리지 엔진에서 사용하는 데이터 구조 입니다 . 사전의 목차와 비교할 수 있어 해당 기록을 빠르게 찾을 수 있습니다.

인덱스는 일반적으로 물리적 공간을 차지하는 디스크의 파일에 저장됩니다.

인덱싱의 장점과 단점은 무엇입니까?

이점:

  • 데이터 조회 속도 향상
  • 정렬 또는 그룹화에 사용되는 필드에 인덱스를 추가하면 그룹화 및 정렬 속도가 빨라질 수 있습니다.
  • 테이블 간 조인 속도 향상

결점:

  • 인덱싱에는 물리적 공간이 필요합니다.
  • 테이블 레코드가 추가, 삭제, 수정될 때마다 인덱스를 동적으로 유지 해야 하므로 추가, 삭제 , 수정 시간이 길어지기 때문에 테이블 추가, 삭제, 수정 효율성이 떨어집니다.

C 언어, C++, Java, Python, 프런트 엔드, 데이터베이스, 운영 체제, 컴퓨터 네트워크, 데이터 구조 및 알고리즘, 기계를 포함하여 Dabin 이 편집한 300개 이상의 클래식 컴퓨터 서적 PDF가 포함된 Github 저장소를 공유하겠습니다. 학습, 프로그래밍 생활 등 별표표시하고 다음에 책을 찾을 때 바로 검색할 수 있습니다. 창고는 지속적으로 업데이트 중입니다! Github 주소

인덱스의 역할은 무엇인가요?

데이터는 디스크에 저장되며, 데이터를 쿼리할 때 인덱스가 없으면 모든 데이터가 메모리에 로드되어 순차적으로 검색되며 디스크를 더 많이 읽게 됩니다. 인덱스를 사용하면 B+ 트리의 높이가 일반적으로 2~4개 레이어이고 최대 2~4개의 디스크 읽기만 필요하므로 모든 데이터를 로드할 필요가 없어 쿼리 속도가 크게 향상됩니다.

어떤 상황에서 인덱스를 생성해야 합니까?

  1. 쿼리에 자주 사용되는 필드
  2. 연결에 자주 사용되는 인덱싱 필드는 연결 속도를 높일 수 있습니다.
  3. 자주 정렬해야 하는 필드는 인덱스가 이미 정렬되어 있으므로 인덱스화되어 쿼리 정렬 속도를 높일 수 있습니다.

어떤 상황에서 인덱싱이 생성되지 않습니까?

  1. where조건에 사용되지 않은 필드는 인덱싱에 적합하지 않습니다.
  2. 테이블에 더 적은 수의 레코드가 있습니다. 예를 들어, 데이터가 수백 개뿐이라면 인덱스를 추가할 필요가 없습니다.
  3. 빈번한 추가, 삭제 및 수정이 필요합니다. 인덱싱이 적합한지 평가 필요
  4. 컬럼 계산에 참여하는 컬럼은 인덱스 작성에 적합하지 않습니다.
  5. 남성/여성/알 수 없음의 세 가지 값만 있는 성별과 같이 구별하기 어려운 필드는 인덱싱에 적합하지 않습니다. 인덱스를 추가해도 쿼리 효율성은 향상되지 않습니다.

인덱스 데이터 구조

인덱스의 데이터 구조는 주로 B+ 트리와 해시 테이블을 포함하며 해당 인덱스는 각각 B+ 트리 인덱스와 해시 인덱스입니다. InnoDB 엔진의 인덱스 유형에는 B+ 트리 인덱스와 해시 인덱스가 있으며, 기본 인덱스 유형은 B+ 트리 인덱스입니다.

B+트리 인덱스

B+ 트리는 B-트리와 리프 노드 순차 접근 포인터를 기반으로 구현되었으며, B-트리의 균형을 가지며 순차 접근 포인터를 통해 간격 질의의 성능을 향상시킨다.

B+ 트리에서 노드의 노드는 key왼쪽에서 오른쪽으로 오름차순으로 배열됩니다. 포인터의 왼쪽 및 오른쪽 이웃이 각각 keyi 및 키 i+1 이면 포인터는 노드의 모든 노드를 가리킵니다. 키 ikey 보다 크거나 같고 키 i+ 1 보다 작거나 같습니다 .

[외부 링크 이미지 전송에 실패했습니다. 원본 사이트에 리칭 방지 메커니즘이 있을 수 있습니다. 이미지를 저장하고 직접 업로드하는 것이 좋습니다. (img-sBews5yP-1691456619394) (http://img.topjavaer.cn/img/B) +트리 인덱스 0.png) ]

검색 작업을 수행할 때 먼저 루트 노드에서 이진 검색을 수행하여 포인터를 찾은 key다음 포인터가 가리키는 노드를 재귀적으로 검색합니다. key리프 노드를 찾을 때까지 리프 노드에서 이진 검색을 수행하여 해당 데이터 항목을 찾습니다 .

MySQL 데이터베이스에서 가장 일반적으로 사용되는 인덱스 유형은 BTREEB+ 트리 데이터 구조를 기반으로 구현된 인덱스입니다.

mysql> show index from blog\G;
*************************** 1. row ***************************
        Table: blog
   Non_unique: 0
     Key_name: PRIMARY
 Seq_in_index: 1
  Column_name: blog_id
    Collation: A
  Cardinality: 4
     Sub_part: NULL
       Packed: NULL
         Null:
   Index_type: BTREE
      Comment:
Index_comment:
      Visible: YES
   Expression: NULL

해시 인덱스

해시 인덱스는 해시 테이블을 기반으로 구현되며, 각 데이터 행에 대해 스토리지 엔진은 인덱스 열을 해시하여 해시 코드를 얻고, 해시 알고리즘은 서로 다른 열 값에 대해 계산된 해시 코드 값을 보장해야 합니다. ​다르게 해시 코드 값은 해시 테이블의 키 값으로 사용되며, 데이터 행에 대한 포인터는 해시 테이블의 값 값으로 사용됩니다. 이러한 방식으로 데이터를 검색할 때의 시간복잡도는 O(1)로, 일반적으로 정밀한 검색에 사용됩니다.

해시 인덱스와 B+ 트리 인덱스의 차이점은 무엇입니까?

  • 해시 테이블은 순서가 없기 때문에 해시 인덱스는 정렬을 지원하지 않습니다 .
  • 해시 인덱스는 범위 조회를 지원하지 않습니다 .
  • 해시 인덱스는 퍼지 쿼리 와 다중 열 인덱스에 대한 가장 왼쪽 접두사 일치를 지원하지 않습니다 .
  • 해시 테이블에서 해시 충돌이 발생하기 때문에 해시 인덱스의 성능은 불안정한 반면 B+ 트리 인덱스의 성능은 상대적으로 안정적이며 각 쿼리는 루트 노드에서 리프 노드까지 수행됩니다.

데이터베이스 인덱스 구현에 B 트리보다 B+ 트리가 더 적합한 이유는 무엇입니까?

  • B+ 트리의 데이터는 모두 리프 노드에 저장되고 리프 노드는 모두 인덱스이므로 데이터베이스를 스캔하는 것이 편리합니다. 리프 노드를 한 번만 스캔하면 됩니다. 그러나 B 트리도 데이터를 저장합니다. Branch 노드에서는 특정 데이터를 순서대로 탐색해야 하므로 B+ 트리는 간격 쿼리에 더 적합합니다. 데이터베이스에서는 범위 기반 쿼리가 매우 빈번하므로 B+ 트리는 다음과 같습니다. 일반적으로 데이터베이스 인덱스에 사용됩니다.

  • B+ 트리의 노드에는 인덱스 키 값만 저장되며 리프 노드의 주소에는 특정 정보의 주소가 존재합니다. 이를 통해 페이지 기반 인덱스에 더 많은 노드를 저장할 수 있습니다. 더 많은 I/O 비용을 줄입니다.

  • B+ 트리의 쿼리 효율성은 더욱 안정적이며 모든 키워드 검색은 루트 노드에서 리프 노드까지의 경로를 취해야 합니다. 모든 키워드 쿼리의 경로 길이는 동일하므로 각 데이터에 대한 쿼리 효율성이 동일합니다.

인덱스 카테고리는 무엇입니까?

1. 기본 키 인덱스 : Primary라는 이름의 비어 있지 않은 유일한 인덱스이며 null 값은 허용되지 않습니다.

2. 고유 인덱스 : 인덱스 열의 값은 고유해야 하며, null 값은 허용됩니다. 고유 인덱스와 기본 키 인덱스의 차이점은 고유 인덱스 필드는 Null이 될 수 있고 여러 Null 값이 있을 수 있지만 기본 키 인덱스 필드는 Null이 될 수 없다는 것입니다. 고유 인덱스의 목적: 주로 데이터의 반복 삽입을 방지하기 위해 데이터베이스 테이블의 각 레코드를 고유하게 식별합니다. 고유 인덱스를 생성하는 SQL 문은 다음과 같습니다.

ALTER TABLE table_name
ADD CONSTRAINT constraint_name UNIQUE KEY(column_1,column_2,...);

3. 결합 인덱스 : 테이블 내 여러 필드의 조합에 대해 생성된 인덱스는 해당 필드의 왼쪽 필드가 쿼리 조건에 사용되는 경우에만 사용되며, 결합 인덱스를 사용할 경우 가장 왼쪽 접두사 원칙을 따라야 합니다.

4. 전체 텍스트 색인 : 전체 텍스트 색인은 CHAR, VARCHARTEXT유형 필드에만 사용할 수 있습니다.

5. 일반 인덱스 : 일반 인덱스는 가장 기본적인 인덱스로 제한이 없으며 값이 비어 있을 수 있습니다.

가장 왼쪽의 일치 원리는 무엇입니까?

결합된 인덱스의 가장 왼쪽 인덱스가 SQL 문에서 사용되는 경우 이 SQL 문은 이 결합된 인덱스를 사용하여 일치를 수행할 수 있습니다. 범위 쿼리( >, <, between, like)가 발생하면 일치가 중지되고 후속 필드에 인덱스가 사용되지 않습니다.

인덱싱 의 경우 (a,b,c)쿼리 조건이 a/ab/abc이면 인덱스가 사용되지만, bc를 사용하면 인덱스가 사용되지 않습니다.

인덱싱 의 경우 (a,b,c,d)쿼리 조건이 이면 a = 1 and b = 2 and c > 3 and d = 4a, b, c 세 필드는 인덱스를 사용할 수 있지만 d는 인덱스를 사용할 수 없습니다. 범위 쿼리가 발생했기 때문입니다.

아래 그림과 같이 인덱스 (a, b)가 생성되는데, 인덱스 트리에서 a는 글로벌하게 정렬되고, b는 글로벌하게 정렬되지 않고 로컬로 정렬됩니다(a가 같으면 b에 따라 정렬됩니다). 이 쿼리 조건을 직접 실행하는 데 인덱스를 사용할 수 없습니다 b = 2.

[외부 링크 이미지 전송에 실패했습니다. 원본 사이트에 리칭 방지 메커니즘이 있을 수 있습니다. 이미지를 저장하고 직접 업로드하는 것이 좋습니다. (img-e4IVib9u-1691456619394) (http://img.topjavaer.cn/img/ 가장 왼쪽 접두사.png)]

a의 값이 결정되면 b의 순서가 지정됩니다. 예를 들어 a = 1, b 값은 1이고 2는 정렬된 상태입니다. 이때 a = 2b의 값은 1이고, 4도 정렬된 상태이다. a = 1 and b = 2a 및 b 필드는 를 실행할 때 인덱스를 사용할 수 있습니다. 실행 중에 a > 1 and b = 2a 필드는 인덱스를 사용할 수 있지만 b 필드는 인덱스를 사용할 수 없습니다. 이때 a의 값은 범위이고 고정되어 있지 않기 때문에 b의 값은 이 범위 내에서 정렬되지 않으므로 b 필드에는 인덱스를 사용할 수 없습니다.

클러스터형 인덱스란 무엇입니까?

InnoDB는 테이블의 기본 키를 사용하여 기본 키 인덱스 트리를 구성하고 리프 노드에는 테이블 전체의 레코드 데이터가 저장됩니다. 클러스터링된 인덱스 리프 노드의 저장은 논리적으로 연속적이며 이중 연결 리스트 연결을 사용하며, 리프 노드는 기본 키의 순서대로 정렬되므로 기본 키의 정렬 검색 및 범위 검색이 더 빠릅니다.

클러스터형 인덱스의 리프 노드는 전체 테이블의 행 레코드입니다. InnoDB는 클러스터형 인덱스를 기본 키로 사용합니다. 클러스터형 인덱스는 비클러스터형 인덱스 쿼리보다 훨씬 더 효율적입니다.

의 경우 InnoDB클러스터형 인덱스는 일반적으로 테이블의 기본 키 인덱스이며, 지정된 기본 키가 테이블에 표시되지 않으면 NULL테이블에서 허용되지 않는 첫 번째 고유 인덱스가 선택됩니다. 기본 키도 없고 적합한 고유 인덱스도 없으면 InnoDB내부적으로 클러스터형 인덱스로 숨겨진 기본 키가 생성되는데, 이 숨겨진 기본 키의 길이는 6바이트이며 데이터가 삽입될 때마다 값이 자동으로 증가합니다.

커버링 인덱스란 무엇입니까?

select데이터 열은 인덱스에서만 가져올 수 있으며 두 번째 쿼리를 위해 테이블로 돌아갈 필요가 없습니다 . 즉, 쿼리 열은 사용된 인덱스로 덮여야 합니다. innodb테이블의 보조 인덱스의 경우 인덱스가 쿼리된 열을 포함할 수 있으면 기본 키 인덱스에 대한 보조 쿼리를 피할 수 있습니다 .

모든 유형의 인덱스가 인덱스를 포함할 수 있는 것은 아닙니다. 커버링 인덱스는 인덱스 열의 값을 저장하는 반면, 해시 인덱스와 전체 텍스트 인덱스는 인덱스 열의 값을 저장하지 않으므로 MySQL은 커버링 인덱스로 b+ 트리 인덱스를 사용합니다.

커버링 인덱스를 사용하는 쿼리의 경우 쿼리 앞에 사용하면 explain출력 추가 열이 로 표시됩니다 using index.

예를 들어 user_like사용자가 좋아하는 테이블에서 결합된 인덱스는 이고 (user_id, blog_id)다 가 user_id아닙니다 .blog_idnull

explain select blog_id from user_like where user_id = 13;

explain결과의 Extra컬럼은 Using index쿼리된 컬럼이 인덱스로 덮여 있으며, where 필터링 조건은 가장 왼쪽 접두사 원칙을 따르며, 쿼리를 위해 다시 테이블로 갈 필요 없이 인덱스 검색을 통해 조건에 ​​맞는 데이터를 바로 찾을 수 있습니다. 자료.

explain select user_id from user_like where blog_id = 1;

explain결과의 Extra컬럼은 Using where; Using index쿼리된 컬럼이 인덱스에 포함되어 있는 것으로, where 필터링 조건은 가장 왼쪽 접두사 원칙을 따르지 않습니다. 그리고 데이터를 쿼리하기 위해 테이블을 반환할 필요가 없습니다 .

인덱스 디자인 원칙?

  • 쿼리 조건으로 자주 사용되는 필드의 경우 쿼리 속도를 높이기 위해 인덱스를 생성해야 합니다.
  • 정렬, 그룹화 및 통합 작업이 자주 필요한 인덱스 필드
  • 인덱스 열의 판별력이 높을수록 인덱스 효과가 좋아집니다. 예를 들어 성별과 같이 구별성이 낮은 컬럼을 인덱스로 사용한다면 효과가 매우 약할 것입니다.
  • "큰 필드"를 인덱싱하지 마세요. 데이터 볼륨이 작은 필드를 인덱스로 사용해 보세요. MySQL인덱스 유지 시 필드 값이 함께 유지되기 때문에 필연적으로 인덱스가 더 많은 공간을 차지하게 되고, 정렬 시 비교하는 데에도 시간이 더 많이 걸리게 됩니다.
  • 짧은 인덱스를 사용해 보세요 . 긴 문자열을 인덱싱할 때는 접두사 길이를 더 짧게 지정해야 합니다. 인덱스가 작을수록 디스크 I/O가 적고 쿼리 속도가 더 빠르기 때문입니다.
  • 인덱스는 많을수록 좋습니다. 인덱스마다 추가 물리적 공간이 필요하고 유지 관리에 시간이 걸립니다.
  • 자주 추가, 삭제 또는 수정되는 필드에 대해서는 색인을 생성하지 마십시오. 특정 필드가 자주 수정된다는 것은 인덱스를 자주 재구축해야 한다는 의미이며, 이는 필연적으로 MySQL의 성능에 영향을 미치게 됩니다.
  • 가장 왼쪽 접두사 원칙을 사용합니다 .

인덱스는 언제 만료되나요?

인덱스 실패로 이어지는 상황:

  • 복합 인덱스의 경우, 복합 인덱스의 가장 왼쪽 필드를 사용하지 않으면 인덱스가 사용되지 않습니다.
  • 예를 들어 %로 시작하는 쿼리와 마찬가지로 %abc인덱스를 사용할 수 없으며, 예를 들어 %로 시작하지 않는 쿼리와 마찬가지로 abc%범위 쿼리와 동일하며 인덱스가 사용됩니다.
  • 쿼리 조건의 컬럼 타입은 문자열이며 따옴표를 사용하지 않으며, 타입에 따라 암시적 변환이 발생하여 인덱스가 무효화될 수 있다.
  • 인덱스 컬럼이 특정 값과 같지 않은지 판단할 때
  • 인덱스 열에 대한 작업 수행
  • 연결을 사용하는 쿼리 조건 or도 인덱스 오류를 발생시킵니다.

접두사 색인이란 무엇입니까?

매우 긴 문자 열에 인덱스를 생성해야 하는 경우가 있는데, 이로 인해 인덱스가 매우 크고 느려집니다. 접두사 색인을 사용하면 이 문제를 피할 수 있습니다.

접두사 인덱스란 텍스트나 문자열의 처음 몇 글자를 인덱스화하여 인덱스 길이를 짧게 하고 쿼리 속도를 높이는 것을 말합니다.

접두사 색인을 만드는 핵심은 높은 색인 선택성을 보장할 만큼 충분히 긴 접두사를 선택하는 것입니다 . 인덱스 선택성이 높을수록 쿼리 효율성도 높아집니다. 왜냐하면 선택성이 높은 인덱스를 사용하면 MySQL이 검색 시 더 많은 데이터 행을 필터링할 수 있기 때문입니다.

접두사 색인을 만드는 방법:

// email列创建前缀索引
ALTER TABLE table_name ADD KEY(column_name(prefix_length));

인덱스 푸시다운

내 다른 기사인 Illustrated Index Pushdown을 참조하세요 !

일반적인 스토리지 엔진은 무엇입니까?

MySQL에서 일반적으로 사용되는 4가지 스토리지 엔진은 MyISAM , InnoDB , MEMORYARCHIVE 입니다 . MySQL 5.5 이후의 기본 스토리지 엔진은 InnoDB.

InnoDB 스토리지 엔진

InnoDB는 가장 널리 사용되는 MySQL의 기본 트랜잭션 스토리지 엔진 이며 클러스터형 인덱스를 기반으로 구축되었습니다. InnoDB는 읽기 작업 속도를 높이기 위해 메모리에 적응형 해시 인덱스를 자동으로 생성하는 등 내부적으로 많은 최적화를 수행했습니다.

장점 : 트랜잭션 및 충돌 복구 기능을 지원하고 행 수준 잠금 및 외래 키 제약 조건을 도입합니다.

단점 : 차지하는 데이터 공간이 상대적으로 크다.

적용 가능한 시나리오 : 트랜잭션 지원이 필요하며 동시 읽기 및 쓰기 빈도가 높습니다.

MyISAM 스토리지 엔진

데이터는 압축된 형식으로 저장됩니다. 읽기 전용 데이터 또는 테이블이 상대적으로 작고 복구 작업을 허용할 수 있는 경우 MyISAM 엔진을 사용할 수 있습니다. MyISAM은 테이블을 데이터 파일 .MYD과 인덱스 파일의 두 파일에 저장합니다 .MYI.

장점 : 접근이 빠르다.

단점 : MyISAM은 트랜잭션 및 행 수준 잠금을 지원하지 않으며 충돌 후 안전한 복구를 지원하지 않으며 외래 키를 지원하지 않습니다.

적용 가능한 시나리오 : 트랜잭션 무결성에 대한 요구 사항이 없으며 모든 테이블 데이터는 읽기 전용입니다.

MEMORY 스토리지 엔진

MEMORY 엔진은 모든 데이터를 메모리에 저장하므로 액세스 속도는 더 빠르지만 시스템이 충돌하면 데이터가 손실됩니다.

MEMORY 엔진은 기본적으로 해시 인덱스를 사용하여 키의 해시 값과 데이터 행에 대한 포인터를 해시 인덱스에 저장합니다.

장점 : 접근이 더 빠르다.

단점 :

  1. 해시 인덱스 데이터는 인덱스 값의 순서대로 저장되지 않으며 정렬용으로 사용할 수 없습니다.
  2. 해시 인덱스는 인덱스 열의 전체 콘텐츠를 사용하여 해시 값을 계산하므로 부분 인덱스 일치 조회는 지원되지 않습니다.
  3. 같음 비교만 지원되며 범위 쿼리는 지원되지 않습니다.
  4. 해시 충돌이 발생하면 스토리지 엔진은 연결된 목록의 모든 행 포인터를 탐색하고 조건을 충족하는 행을 찾을 때까지 행별로 비교해야 합니다.

ARCHIVE 스토리지 엔진

ARCHIVE 스토리지 엔진은 대용량의 독립적인 데이터를 이력 기록으로 저장하는 데 매우 적합합니다. ARCHIVE는 압축 기능을 제공하고 삽입 속도가 효율적이지만, 이 엔진은 인덱스를 지원하지 않아 쿼리 성능이 좋지 않습니다.

MyISAM과 InnoDB의 차이점은 무엇입니까?

  1. 저장 구조의 차이점 . 각 MyISAM은 디스크에 세 개의 파일로 저장됩니다. 파일 이름은 테이블 이름으로 시작하고 확장자는 파일 유형을 나타냅니다. .frm 파일은 테이블 정의를 저장합니다. 데이터 파일 확장자는 .MYD(MYData)입니다. 인덱스 파일의 확장자는 .MYI(MYIndex)입니다. 모든 InnoDB 테이블은 동일한 데이터 파일(또는 여러 파일 또는 독립적인 테이블스페이스 파일)에 저장됩니다. InnoDB 테이블의 크기는 운영 체제 파일 크기(일반적으로 2GB)에 의해서만 제한됩니다.
  2. 수납공간의 차이 . MyISAM은 정적 테이블(기본값이지만 데이터 끝에 공백이 있을 수 없으므로 제거됨), 동적 테이블 및 압축 테이블의 세 가지 저장 형식을 지원합니다. 테이블이 생성되고 데이터를 가져온 후에는 수정 작업이 수행되지 않습니다. 압축된 테이블을 사용하면 디스크 공간 사용량을 크게 줄일 수 있습니다. InnoDB는 더 많은 메모리와 스토리지를 필요로 하며 데이터와 인덱스를 캐싱하기 위해 메인 메모리에 전용 버퍼 풀을 구축합니다.
  3. 이식성, 백업 및 복구 . MyISAM 데이터는 파일 형태로 저장되므로 크로스 플랫폼 데이터 전송에 매우 편리합니다. 백업 및 복구 중에 테이블에 대한 작업을 개별적으로 수행할 수 있습니다. InnoDB의 경우 가능한 해결 방법은 데이터 파일을 복사하거나, binlog를 백업하거나, mysqldump를 사용하는 것인데, 이는 데이터 용량이 수십 기가바이트에 달할 경우 상대적으로 번거롭습니다.
  4. 행 수준 잠금이 지원되는지 여부입니다 . MyISAM은 테이블 수준 잠금만 지원하며, 사용자가 myisam 테이블을 조작할 때 select, update, delete, insert 문이 자동으로 테이블을 잠급니다. 잠긴 테이블이 삽입 동시성 조건을 만족하면 새로운 데이터를 테이블 끝에 삽입할 수 있습니다. table.data. InnoDB는 행 수준 잠금과 테이블 수준 잠금을 지원하며 기본값은 행 수준 잠금입니다. 행 잠금은 다중 사용자 동시 작업의 성능을 크게 향상시킵니다.
  5. 거래 및 충돌 후 안전한 복구 지원 여부 . MyISAM은 트랜잭션 지원을 제공하지 않습니다. InnoDB는 트랜잭션 지원을 제공하며 트랜잭션, 롤백 및 충돌 복구 기능을 갖추고 있습니다.
  6. 외래 키 지원 여부 . MyISAM은 이를 지원하지 않지만 InnoDB는 지원합니다.
  7. MVCC 지원 여부 . MyISAM은 이를 지원하지 않지만 InnoDB는 지원합니다. 동시성이 높은 트랜잭션을 처리하려면 MVCC가 단순 잠금보다 더 효율적입니다.
  8. 클러스터형 인덱스가 지원되는지 여부입니다 . MyISAM은 클러스터형 인덱스를 지원하지 않지만 InnoDB는 클러스터형 인덱스를 지원합니다.
  9. 전체 텍스트 색인 . MyISAM은 FULLTEXT 유형의 전체 텍스트 인덱스를 지원합니다. InnoDB는 FULLTEXT 유형의 전체 텍스트 인덱스를 지원하지 않지만 innodb는 스핑크스 플러그인을 사용하여 전체 텍스트 인덱스를 지원할 수 있으며 효과가 더 좋습니다.
  10. 테이블 기본 키 . MyISAM을 사용하면 인덱스와 기본 키 없이 테이블이 존재할 수 있습니다. 인덱스는 행이 저장되는 주소입니다. InnoDB의 경우 기본 키가 없거나 비어 있지 않은 고유 인덱스 세트가 있으면 6바이트 기본 키가 자동으로 생성됩니다(사용자에게 표시되지 않음).
  11. 테이블의 행 수입니다 . MyISAM은 테이블의 총 행 수를 저장하며, select count(*) from table;인 경우 해당 값을 직접 가져옵니다. InnoDB는 테이블의 전체 행 수를 저장하지 않으며, select count(*) from table을 사용하면 테이블 전체를 순회하게 되므로 많은 비용이 소모되지만, where 조건을 추가한 후에는 MyISAM과 InnoDB가 처리하게 된다. 같은 방식으로요.

MySQL에는 어떤 잠금 장치가 있나요?

잠금 단위에 따라 분류되는 잠금에는 행 수준 잠금, 테이블 수준 잠금, 페이지 수준 잠금이 있습니다.

  1. 행 수준 잠금은 MySQL에서 가장 세부적인 잠금입니다. 현재 연산 중인 행만 잠겨 있음을 나타냅니다. 행 수준 잠금은 데이터베이스 작업의 충돌을 크게 줄일 수 있으며 잠금 세분성은 가장 작지만 잠금 오버헤드도 가장 큽니다. 행 수준 잠금에는 세 가지 주요 유형이 있습니다.
    • 레코드 잠금, 레코드 잠금, 즉 하나의 레코드만 잠그는 것입니다.
    • 간격 잠금, 간격 잠금은 범위를 잠그지만 레코드 자체는 포함하지 않습니다.
    • Next-Key Lock: Record Lock + Gap Lock의 조합으로, 범위를 잠그고 레코드 자체를 잠급니다.
  2. 테이블 레벨 잠금은 MySQL에서 가장 세밀한 잠금으로 현재 작업의 테이블 전체를 잠그는 것을 의미하며, 구현이 간단하고 리소스 소모가 적으며 대부분의 MySQL 엔진에서 지원됩니다. 가장 일반적으로 사용되는 MyISAM 및 InnoDB는 테이블 수준 잠금을 지원합니다.
  3. 페이지 수준 잠금은 행 수준 잠금과 테이블 수준 잠금 사이에 잠금 세분성이 있는 MySQL의 잠금 유형입니다. 테이블 수준 잠금은 빠르지만 충돌이 많습니다. 행 수준 잠금은 충돌이 적지만 느립니다. 따라서 손상된 페이지 수준 잠금이 채택되어 한 번에 인접한 레코드 그룹을 잠급니다.

잠금 수준에 따라 분류하면 공유 잠금, 배타적 잠금, 의도 잠금이 있습니다.

  1. 읽기 잠금이라고도 하는 공유 잠금은 읽기 작업에 의해 생성되는 잠금입니다. 다른 사용자는 동시에 데이터를 읽을 수 있지만 모든 공유 잠금이 해제될 때까지 어떤 트랜잭션도 데이터를 수정할 수 없습니다(데이터에 대한 배타적 잠금 획득).
  2. 배타적 잠금은 쓰기 잠금 및 배타적 잠금이라고도 하며, 트랜잭션 T가 데이터 A에 배타적 잠금을 추가하면 다른 트랜잭션은 A에 어떠한 유형의 차단도 추가할 수 없습니다. 배타적 잠금이 부여된 트랜잭션은 데이터를 읽고 수정할 수 있습니다.
  3. 의도 잠금은 주로 트랜잭션의 다음 행에 대해 요청되는 잠금 유형을 표시하기 위해 설계된 테이블 수준 잠금입니다. InnoDB의 두 가지 테이블 잠금:

의도 공유 잠금(IS): 트랜잭션이 데이터 행에 공유 잠금을 추가할 준비를 하고 있음을 나타냅니다. 즉, 데이터 행에 공유 잠금을 추가하기 전에 먼저 테이블의 IS 잠금을 획득해야 합니다.

의도 배타적 잠금(IX): 위와 유사하게 트랜잭션이 데이터 행에 배타적 잠금을 추가할 준비를 하고 있음을 나타내며, 트랜잭션이 데이터에 배타적 잠금을 추가하기 전에 먼저 테이블의 IX 잠금을 획득해야 함을 나타냅니다. 열.

의도 잠금은 InnoDB에 의해 자동으로 추가되며 사용자 개입이 필요하지 않습니다.

INSERT, UPDATE 및 DELETE의 경우 InnoDB는 관련된 데이터에 자동으로 배타적 잠금을 추가합니다. 일반적인 SELECT 문의 경우 InnoDB는 잠금을 추가하지 않으며 트랜잭션은 다음 문을 통해 명시적으로 공유 잠금 또는 배타적 잠금을 추가할 수 있습니다.

공유 잠금:SELECT … LOCK IN SHARE MODE;

전용 잠금장치:SELECT … FOR UPDATE;

MVCC 구현 원리는 무엇입니까?

MVCC( Multiversion concurrency control)는 동일한 데이터의 여러 버전을 유지하여 동시성 제어를 달성하는 방법입니다. 쿼리 시 read view버전 체인을 통해 해당 버전의 데이터를 찾아냅니다.

기능: 동시성 성능을 향상시킵니다. 동시성이 높은 시나리오의 경우 MVCC는 행 수준 잠금보다 비용이 저렴합니다.

MVCC의 구현 원리는 다음과 같습니다.

MVCC의 구현은 테이블의 세 가지 숨겨진 필드를 통해 구현되는 버전 체인에 의존합니다.

  • DB_TRX_ID: 현재 거래 ID, 거래의 시간 순서는 거래 ID의 크기로 판단됩니다.
  • DB_ROLL_PTR: 롤백 포인터는 현재 행 레코드의 이전 버전을 가리키며, 이 포인터를 통해 여러 버전의 데이터가 함께 연결되어 버전 undo log체인을 형성합니다.
  • DB_ROW_ID: 기본 키: 데이터 테이블에 기본 키가 없으면 InnoDB는 자동으로 기본 키를 생성합니다.

각 테이블 레코드는 다음과 같습니다.

행 레코드를 업데이트하기 위해 트랜잭션을 사용하면 버전 체인이 생성되며 실행 프로세스는 다음과 같습니다.

  1. 배타적 잠금으로 행을 잠급니다.
  2. 롤백을 위해 행의 원래 값을 undo log이전 버전으로 복사합니다.
  3. 현재 행의 값을 수정하고, 새 버전을 생성하고, 트랜잭션 ID를 업데이트하고, 롤백 포인터가 이전 버전의 레코드를 가리키도록 만들어 버전 체인을 형성합니다.

다음은 모든 사람이 이해할 수 있는 예입니다.

1. 초기 데이터는 다음과 같으며 DB_ROW_ID합 은 DB_ROLL_PTR비어있습니다.

2. 트랜잭션 A가 행 데이터를 수정하여 age12로 변경했습니다. 효과는 다음과 같습니다.

3. 나중에 트랜잭션 B도 행 레코드를 수정하여 age8로 변경했습니다. 효과는 다음과 같습니다.

4. 이때 Undo 로그에는 두 줄의 레코드가 있으며, 이는 롤백 포인터를 통해 연결됩니다.

다음으로 Read View의 개념을 이해한다.

read view매 순간의 데이터 상태를 기록하기 위해 "사진"을 찍는 것으로 이해될 수 있습니다. 특정 시간 t에서 데이터를 얻을 때, 시간 t에 촬영된 "사진"에서 데이터를 얻습니다.

read view활성 트랜잭션 목록은 내부적으로 유지되며 read view생성 시 여전히 활성 상태인 트랜잭션을 나타 냅니다. 이 연결된 목록에는 read view생성 전에 커밋되지 않은 트랜잭션이 포함되지만 read view생성 후에 커밋된 트랜잭션은 포함되지 않습니다.

격리 수준에 따라 읽기 보기를 생성하는 타이밍이 다릅니다.

  • 커밋된 읽기: select가 실행될 때마다 다른 트랜잭션에 의해 제출된 수정 사항을 읽을 수 있도록 새로운 read_view가 생성됩니다.

  • 반복 읽기: 트랜잭션 범위 내에서 이 read_view는 첫 번째 선택 중에 업데이트되고 다시 업데이트되지 않습니다. 모든 후속 선택은 이전 read_view를 재사용합니다. 이렇게 하면 트랜잭션 범위 내에서 읽은 내용이 매번 동일하고 반복적으로 읽을 수 있음을 보장합니다.

읽기 보기의 기록 필터링 방법

전제조건 : DATA_TRX_ID각 데이터 행의 최신 트랜잭션 ID를 나타내며, up_limit_id현재 스냅샷에서 가장 먼저 시작된 트랜잭션을 나타내며, low_limit_id현재 스냅샷에서 가장 느리게 시작된 트랜잭션, 즉 마지막 트랜잭션을 나타냅니다.

  • DATA_TRX_ID< 인 경우 : 데이터 행을 수정한 트랜잭션이 생성 시 커밋되었으며, 현재 트랜잭션에서 이 버전의 레코드를 읽을 수 있음을 up_limit_id의미합니다 .read view
  • DATA_TRX_ID>= 인 경우 : 현재 버전의 레코드 트랜잭션 이 생성 후 생성되었으며 현재 트랜잭션에서 이 버전의 데이터 행에 액세스할 수 없음을 low_limit_id의미합니다 . read view이때, 버전 체인을 통해 이전 버전을 찾은 후 현재 거래에 대한 이 버전의 기록의 가시성을 다시 판단해야 합니다.
  • up_limit_id<= DATA_TRX_ID< 인 경우 low_limit_i:
    1. 활성 거래 목록에 ID 값을 갖는 거래가 있는지 확인해야 합니다 DATA_TRX_ID.
    2. 존재하는 경우 활성 트랜잭션 목록의 트랜잭션이 커밋되지 않았기 때문에 레코드가 표시되지 않습니다. 이때, 버전 체인을 통해 이전 버전을 찾아본 후, 이 버전의 가시성을 다시 판단해야 합니다.
    3. 존재하지 않으면 트랜잭션 trx_id가 커밋되었으며 이 레코드 행이 표시된다는 의미입니다.

요약 : InnoDB는 버전 체인을 MVCC통해 read view구현되며 버전 체인은 과거 버전 기록 read view을 저장합니다. 현재 버전의 데이터가 보이는지 여부를 판단하여 보이지 않으면 버전 체인에서 이전 버전을 찾아서 나올 때까지 계속 판단합니다. 표시 버전을 찾습니다.

스냅샷 읽기 및 현재 읽기

테이블 레코드를 읽는 방법에는 두 가지가 있습니다.

  • 스냅샷 읽기: 스냅샷 버전을 읽습니다. 일반적인 것은 SELECT스냅샷 읽기입니다. 동시성 제어는 잠금 없이 mvcc를 통해 수행됩니다.

  • 현재 읽기: 최신 버전을 읽습니다. UPDATE、DELETE、INSERT、SELECT … LOCK IN SHARE MODE、SELECT … FOR UPDATE현재 읽고 있습니다.

스냅샷 읽기의 경우 InnoDB는 mvcc메커니즘을 통해 팬텀 읽기를 방지합니다. 메커니즘은 mvcc현재 독서 상황에서 발생하는 팬텀 독서 현상을 피할 수 없습니다. 현재 읽기는 매번 최신 데이터를 읽기 때문에 두 쿼리 사이에 데이터를 삽입하는 다른 트랜잭션이 있으면 팬텀 읽기가 발생합니다.

설명하기 위한 예는 다음과 같습니다.

1. 우선 사용자 테이블에는 다음과 같이 두 개의 레코드만 있습니다.

2. 거래 a와 거래 b가 동시에 거래를 개시합니다 start transaction.

3. 트랜잭션 A가 데이터를 삽입한 후 제출합니다.

insert into user(user_name, user_password, user_mail, user_state) values('tyson', 'a', 'a', 0);

4. 트랜잭션 b는 전체 테이블의 업데이트를 실행합니다.

update user set user_name = 'a';

5. 그런 다음 트랜잭션 b는 쿼리를 실행하고 트랜잭션 a에 삽입된 데이터를 찾습니다. (아래 그림의 왼쪽이 트랜잭션 b, 오른쪽이 트랜잭션 a입니다. 트랜잭션이 시작되기 전에는 레코드가 2개밖에 없었습니다. 트랜잭션 a가 1개의 데이터를 삽입한 후, 트랜잭션 b가 3개의 데이터를 쿼리했습니다.)

[외부 링크 이미지 전송에 실패했습니다. 원본 사이트에 리칭 방지 메커니즘이 있을 수 있습니다. 이미지를 저장하고 직접 업로드하는 것이 좋습니다. (img-c6OMxuPD-1691456619399) (http://img.topjavaer.cn/img/ 팬텀리딩 1.png)]

위의 내용은 현재 독서에서 발생하는 팬텀 독서 현상입니다.

그렇다면 MySQL은 팬텀 읽기를 어떻게 방지합니까?

  • 스냅샷 읽기의 경우 MySQL은 mvcc팬텀 읽기를 방지합니다.
  • 현재 읽기 상황에서 MySQL은 next-key팬텀 읽기(행 잠금 및 간격 잠금을 추가하여 구현됨)를 방지합니다.

next-key는 행 잠금과 간격 잠금의 두 부분으로 구성됩니다. 행 잠금은 인덱스에 추가되는 잠금이고, 갭 잠금은 인덱스 사이에 추가되는 잠금입니다.

Serializable격리 수준은 또한 전체 테이블을 잠그는 팬텀 읽기를 방지할 수 있으며 동시성은 매우 낮으므로 일반적으로 사용되지 않습니다.

공유 잠금 및 배타적 잠금

SELECT의 읽기 잠금은 크게 공유 잠금과 배타적 잠금의 두 가지 방법으로 나뉜다.

select * from table where id<6 lock in share mode;--共享锁
select * from table where id<6 for update;--排他锁

이 두 방법의 주요 차이점은 LOCK IN SHARE MODE 여러 트랜잭션이 동시에 동일한 양식을 업데이트할 때 교착 상태가 발생하기 쉽다는 것입니다.

배타적 잠금을 적용하기 위한 전제 조건은 어떤 스레드도 결과 집합의 행 데이터에 대해 배타적 잠금이나 공유 잠금을 사용하지 않는다는 것입니다. 그렇지 않으면 애플리케이션이 차단됩니다. 트랜잭션 작업을 수행할 때 MySQL은 쿼리 결과 집합의 각 데이터 행에 배타적 잠금을 추가합니다. 다른 스레드에 의한 이러한 데이터의 변경 또는 삭제는 명령문의 트랜잭션이 실행될 때까지 차단됩니다(읽기 작업만). 진술이나 commit진술 rollback.끝까지.

SELECT... FOR UPDATE사용상의 주의사항:

  1. for updateinnodb에만 적용되며 적용하려면 트랜잭션 범위 내에 있어야 합니다.
  2. 기본 키를 기반으로 한 쿼리 쿼리 조건이 같 like거나 같지 않으면 기본 키 필드가 테이블 잠금을 생성합니다 .
  3. 색인화되지 않은 필드를 기반으로 쿼리하면 테이블 잠금이 생성됩니다 .

bin 로그/다시 실행 로그/실행 취소 로그

MySQL 로그에는 주로 쿼리 로그, 느린 쿼리 로그, 트랜잭션 로그, 오류 로그, 바이너리 로그 등이 포함됩니다. 더 중요한 것은 bin log(바이너리 로그), redo log(리두 로그) 및 undo log(롤백 로그)입니다.

빈 로그

bin logMySQL 데이터베이스 레벨의 파일로, MySQL 데이터베이스를 수정하는 모든 작업을 기록하며, select 및 show 문은 기록하지 않으며, 주로 데이터베이스 복원 및 동기화에 사용됩니다.

다시 실행 로그

redo loginnodb 엔진 레벨로 innodb 스토리지 엔진의 트랜잭션 로그를 기록하는 데 사용되며, 데이터 복구를 위해 트랜잭션 제출 여부와 관계없이 기록됩니다. redo log데이터베이스 오류가 발생하면 innoDB 스토리지 엔진은 데이터 무결성을 보장하기 위해 오류 이전 시점으로 복구를 사용합니다 . 매개변수를 innodb_flush_log_at_tx_commit1로 설정하면 커밋이 redo log동기적으로 디스크에 기록됩니다.

실행 취소 로그

기록 외에도 redo log데이터 수정 시 데이터 불러오기 작업을 위해 기록되며 undo log, undo log기록 수정 전의 내용을 유지합니다. undo log트랜잭션 롤백이 가능하며 undo log특정 버전의 데이터 로의 역추적을 기반으로 MVCC를 구현할 수 있습니다 .

bin 로그와 redo 로그의 차이점은 무엇입니까?

  1. bin logInnoDB, MyISAM 등 스토리지 엔진의 로그를 포함한 모든 로그 기록이 기록되며, redo loginnoDB 자체 트랜잭션 로그만 기록됩니다.
  2. bin logredo log트랜잭션이 커밋되기 전에만 디스크에 기록되고 트랜잭션은 한 번만 기록됩니다. 트랜잭션이 진행되는 동안에는 디스크에 계속해서 기록 됩니다 .
  3. bin logSQL 문의 원래 논리를 기록하는 논리 로그이고, redo log특정 데이터 페이지에 어떤 수정 사항이 적용되었는지 기록하는 물리 로그입니다.

MySQL 아키텍처에 대해 알려주세요.

MySQL은 주로 서버 계층과 스토리지 엔진 계층으로 구분됩니다.

  • 서버 계층 : 주로 커넥터, 쿼리 캐시, 분석기, 최적화 프로그램, 실행기 등이 포함됩니다. 저장 프로시저, 트리거, 뷰, 함수 등과 같은 모든 교차 스토리지 엔진 기능이 이 계층에서 구현되며 일반 계층도 있습니다. 로그 모듈 binglog 로그 모듈.
  • 스토리지 엔진 : 주로 데이터 저장 및 읽기를 담당합니다. 서버 계층은 API를 통해 스토리지 엔진과 통신합니다.

서버 계층 기본 구성 요소

  • 커넥터: 클라이언트가 MySQL에 연결되면 서버 계층에서 ID 인증 및 권한 확인을 수행합니다.
  • Query Cache : Query 문 실행 시 먼저 캐시를 쿼리하여 SQL이 실행되었는지 확인하고, SQL이 캐시된 경우 클라이언트에 직접 반환하고, 적중이 없으면 후속 작업을 수행한다. .
  • 분석기: 캐시에 맞지 않으면 SQL 문이 분석기를 거치는데, 이는 주로 어휘 분석과 구문 분석의 두 단계로 나누어집니다. 먼저 SQL 문이 무엇을 하는지 확인한 다음 SQL 구문이 맞는지 확인합니다. 진술이 정확합니다.
  • 옵티마이저 (Optimizer): 쿼리 재작성, 테이블 읽기 및 쓰기 순서 결정, 적절한 인덱스 선택, 실행 계획 생성 등 쿼리를 최적화합니다.
  • Executor: 먼저 실행 전에 사용자에게 권한이 있는지 확인하고, 권한이 없으면 오류 메시지를 반환하고, 권한이 있으면 실행 계획에 따라 엔진 인터페이스를 호출하여 결과를 보여줍니다. 돌아왔다.

하위 데이터베이스 및 하위 테이블

단일 테이블의 데이터 볼륨이 1000W나 100G에 도달하면 인덱스 최적화, 슬레이브 데이터베이스 추가 등이 데이터베이스 성능 향상에 큰 영향을 미치지 않을 수 있으므로 분할을 고려해야 합니다. 세분화의 목적은 데이터베이스에 대한 부담을 줄이고 쿼리 시간을 단축하는 것입니다.

데이터 분할은 수직 분할과 수평 분할의 두 가지 방법으로 나눌 수 있습니다.

수직 분할

데이터베이스의 수직 분할은 비즈니스를 기반으로 하며, 예를 들어 쇼핑 시나리오에서 데이터베이스의 제품, 주문, 사용자에 관한 테이블을 각각 하나의 데이터베이스로 나누어 단일 데이터베이스의 크기를 줄여 성능을 향상시킬 수 있습니다. 마찬가지로 테이블 분할의 경우는 큰 테이블을 기본 상품정보, 상품 설명 등 업무 기능을 기준으로 하위 테이블로 분할하는 것으로, 일반적으로 기본 상품 정보는 상품 목록에 표시되며, 상품 설명은 에 표시됩니다. 상품 상세 페이지 상품 기본 정보와 상품 설명이 두 개의 테이블로 나누어져 있습니다.

[외부 링크 이미지 전송에 실패했습니다. 원본 사이트에 리칭 방지 메커니즘이 있을 수 있습니다. 이미지를 저장하고 직접 업로드하는 것이 좋습니다. (img-cSyfknhd-1691456619400) (http://img.topjavaer.cn/img/ 세로분할.png)]

장점 : 행 레코드가 더 작아지고 데이터 페이지에 더 많은 레코드를 저장할 수 있으며 쿼리 중 I/O 시간이 줄어듭니다.

단점 :

  • 기본 키는 중복되어 있으며 중복된 열을 관리해야 합니다.
  • 데이터베이스 압력을 줄이기 위해 비즈니스 서버에서 수행할 수 있는 테이블 연결 JOIN 작업이 발생합니다.
  • 여전히 단일 테이블에 데이터 양이 과도하게 발생하는 문제가 있습니다.

수평 분할

수평 분할은 시간 또는 ID 시퀀스 값과 같은 특정 규칙에 따라 데이터를 분할하는 것입니다. 예를 들어 연도를 기준으로 서로 다른 데이터베이스를 분할합니다. 각 데이터베이스는 동일한 구조를 가지고 있지만 성능 향상을 위해 데이터를 분할합니다.

[외부 링크 이미지 전송에 실패했습니다. 원본 사이트에 리칭 방지 메커니즘이 있을 수 있습니다. 이미지를 저장하고 직접 업로드하는 것이 좋습니다. (img-Q97IJSOD-1691456619401) (http://img.topjavaer.cn/img/ 가로 분할.png)]

장점 : 단일 데이터베이스(테이블)의 데이터 양이 줄어들고 성능이 향상되며, 분할된 테이블은 동일한 구조를 가지며 프로그램 변경이 적습니다.

단점 :

  • 샤딩 트랜잭션 일관성은 해결하기 어렵습니다.
  • 낮은 노드 간 join성능과 복잡한 로직
  • 확장 시 데이터 샤딩을 마이그레이션해야 함

파티션 테이블이란 무엇입니까?

파티셔닝은 테이블의 데이터를 N개의 블록으로 나누는 것입니다. 분할된 테이블은 독립적인 논리적 테이블이지만 기본 계층은 여러 개의 물리적 하위 테이블로 구성됩니다.

쿼리 조건의 데이터가 특정 파티션에 분산되어 있는 경우 쿼리 엔진은 테이블 전체를 순회하지 않고 특정 파티션에만 쿼리합니다. 관리 수준에서 특정 파티션의 데이터를 삭제해야 하는 경우 해당 파티션만 삭제하면 됩니다.

파티션은 일반적으로 단일 시스템에 배치되며 시간 범위 파티셔닝은 보관을 용이하게 하기 위해 더 일반적으로 사용됩니다. 단지 하위 데이터베이스와 테이블을 코드로 구현해야 하고 파티셔닝은 MySQL에서 내부적으로 구현하면 됩니다. 서브 데이터베이스, 서브 테이블, 파티션은 충돌하지 않으며 함께 사용할 수 있습니다.

파티션 테이블 유형

범위 분할은 범위 분할을 기반으로 합니다. 예를 들어 시간 범위별로 파티션을 나누는 경우

CREATE TABLE test_range_partition(
       id INT auto_increment,
       createdate DATETIME,
       primary key (id,createdate)
   ) 
   PARTITION BY RANGE (TO_DAYS(createdate) ) (
      PARTITION p201801 VALUES LESS THAN ( TO_DAYS('20180201') ),
      PARTITION p201802 VALUES LESS THAN ( TO_DAYS('20180301') ),
      PARTITION p201803 VALUES LESS THAN ( TO_DAYS('20180401') ),
      PARTITION p201804 VALUES LESS THAN ( TO_DAYS('20180501') ),
      PARTITION p201805 VALUES LESS THAN ( TO_DAYS('20180601') ),
      PARTITION p201806 VALUES LESS THAN ( TO_DAYS('20180701') ),
      PARTITION p201807 VALUES LESS THAN ( TO_DAYS('20180801') ),
      PARTITION p201808 VALUES LESS THAN ( TO_DAYS('20180901') ),
      PARTITION p201809 VALUES LESS THAN ( TO_DAYS('20181001') ),
      PARTITION p201810 VALUES LESS THAN ( TO_DAYS('20181101') ),
      PARTITION p201811 VALUES LESS THAN ( TO_DAYS('20181201') ),
      PARTITION p201812 VALUES LESS THAN ( TO_DAYS('20190101') )
   );

/var/lib/mysql/data/해당 데이터 파일을 찾을 수 있습니다. 각 파티션 테이블에는 #을 사용하여 구분하는 이름의 테이블 파일이 있습니다 .

   -rw-r----- 1 MySQL MySQL    65 Mar 14 21:47 db.opt
   -rw-r----- 1 MySQL MySQL  8598 Mar 14 21:50 test_range_partition.frm
   -rw-r----- 1 MySQL MySQL 98304 Mar 14 21:50 test_range_partition#P#p201801.ibd
   -rw-r----- 1 MySQL MySQL 98304 Mar 14 21:50 test_range_partition#P#p201802.ibd
   -rw-r----- 1 MySQL MySQL 98304 Mar 14 21:50 test_range_partition#P#p201803.ibd
...

목록 파티션

목록 분할은 범위 분할과 유사하지만 주요 차이점은 목록은 열거된 값 목록의 모음이고 범위는 연속적인 간격 값의 모음이라는 점입니다. 리스트 파티셔닝을 위해서는 파티셔닝 필드를 알아야 하며, 파티셔닝 시 삽입된 필드가 열거값에 없으면 삽입되지 않는다.

create table test_list_partiotion
   (
       id int auto_increment,
       data_type tinyint,
       primary key(id,data_type)
   )partition by list(data_type)
   (
       partition p0 values in (0,1,2,3,4,5,6),
       partition p1 values in (7,8,9,10,11,12),
       partition p2 values in (13,14,15,16,17)
   );

해시 파티션

데이터는 미리 정의된 파티션에 고르게 분산될 수 있습니다.

create table test_hash_partiotion
   (
       id int auto_increment,
       create_date datetime,
       primary key(id,create_date)
   )partition by hash(year(create_date)) partitions 10;

파티션 문제?

  1. 모든 기본 테이블을 열고 잠그는 데는 비용이 많이 들 수 있습니다. 쿼리가 분할된 테이블에 액세스할 때 MySQL은 모든 기본 테이블을 열고 잠가야 합니다. 이 작업은 파티션 필터링 전에 발생하므로 파티션 필터링을 사용하여 이 오버헤드를 줄일 수 없으며 이는 쿼리 속도에 영향을 미칩니다. LOAD DATA INFILE이 오버헤드는 한 번에 여러 행의 데이터를 일괄 삽입 및 삭제하는 등의 일괄 작업을 통해 줄일 수 있습니다 .
  2. 파티션을 유지하는 데 비용이 많이 들 수 있습니다. 예를 들어, 파티션을 재구성하려면 임시 파티션이 먼저 생성된 다음 데이터가 해당 파티션에 복사되고 마지막으로 원래 파티션이 삭제됩니다.
  3. 모든 파티션은 동일한 스토리지 엔진을 사용해야 합니다.

쿼리문 실행 과정은?

쿼리문의 실행 과정은 권한 확인, 쿼리 캐시, 분석기, 옵티마이저, 권한 확인, 실행기, 엔진의 순서로 진행됩니다.

예를 들어 쿼리 문은 다음과 같습니다.

select * from user where id > 1 and name = '大彬';
  1. 먼저 권한을 확인하세요. 권한이 없으면 오류가 반환됩니다.
  2. MySQL 8.0 이전에는 캐시를 쿼리하여 캐시에 도달하면 바로 반환하고 그렇지 않으면 다음 단계를 실행했습니다.
  3. 어휘 분석 및 구문 분석. 테이블 이름과 쿼리 조건을 추출하고 구문 오류가 있는지 확인합니다.
  4. 두 가지 실행 계획을 먼저 확인 id > 1하거나 name = '大彬'최적화 프로그램이 자체 최적화 알고리즘을 기반으로 실행 효율성이 가장 높은 계획을 선택합니다.
  5. 권한 확인 권한이 있는 경우 데이터베이스 엔진 인터페이스를 호출하고 엔진 실행 결과를 반환합니다.

명령문 실행 프로세스를 업데이트하시겠습니까?

업데이트 문 실행 과정은 분석기, 권한 확인, 실행기, 엔진, redo log( prepare상태), binlog, redo log( commit상태) 입니다.

예를 들어 업데이트 문은 다음과 같습니다.

update user set name = '大彬' where id = 1;
  1. 먼저 ID가 1인 레코드를 쿼리합니다. 캐시가 있으면 캐시가 사용됩니다.
  2. 쿼리 결과를 받아 이름을 Dabin으로 업데이트한 후 엔진 인터페이스를 호출하여 업데이트된 데이터를 쓰는데, innodb 엔진은 데이터를 메모리에 저장하는 동시에 기록하는 상태로 redo log진입 redo log한다 prepare.
  3. 실행자는 알림을 받은 후 이를 기록한 binlog다음 엔진 인터페이스를 호출하고 이를 상태 redo log로 제출합니다 commit.
  4. 업데이트가 완료되었습니다.

녹음 후 바로 제출하지 말고 redo log, prepare먼저 상태를 입력해 보시는 건 어떨까요?

redo log먼저 직접 작성하고 제출한 다음 작성한다고 가정해 보겠습니다 . binlog작성 후 redo log기기가 정지되고 binlog로그가 기록되지 않습니다. 그런 다음 기기를 다시 시작한 후 기기가 데이터를 복원하지만 redo log현재 binlog데이터는 기록되지 않습니다 . 머신은 나중에 백업될 예정입니다. 시간이 지나면 이 데이터 조각이 손실되고 동시에 마스터-슬레이브 동기화에서도 이 데이터 조각이 손실됩니다.

이들존재하다그리고 존재하다의 차이점은 무엇인가요?

exists출현 기록을 필터링하는 데 사용됩니다. exists외부 테이블이 순회되고 외부 쿼리 테이블의 각 행이 판단을 위해 내부 쿼리로 대체됩니다. 내부의 조건문이 레코드 행을 반환할 수 있으면 exists조건이 true이고 테이블의 현재 레코드가 반환됩니다. 반면, exists내부의 조건문이 레코드 행을 반환할 수 없고 조건이 false인 경우 테이블의 현재 레코드가 삭제됩니다.

select a.* from A awhere exists(select 1 from B b where a.id=b.id)

in방법은 먼저 다음 문장을 찾아 임시 테이블에 넣은 후 임시 테이블을 순회하여 임시 테이블의 각 행을 외부 쿼리에 대입하여 검색하는 것입니다.

select * from Awhere id in(select id from B)

하위 쿼리의 테이블이 상대적으로 클 경우 이를 사용하면 exists총 루프 수를 효과적으로 줄여 속도를 향상시킬 수 있으며, 외부 쿼리의 테이블이 상대적으로 클 경우 이를 사용하면 in외부 쿼리 테이블의 루프 순회를 효과적으로 줄일 수 있습니다. 속도를 향상시키세요.

MySQL에서 int(10)와 char(10)의 차이점은 무엇입니까?

int(10)의 10은 표시된 데이터의 길이를 나타내고, char(10)은 저장된 데이터의 길이를 나타냅니다.

잘라내기, 삭제, 삭제의 차이점은 무엇인가요?

같은 점:

  1. truncatewhere없이 테이블의 데이터를 삭제합니다 delete.drop

  2. drop실행 후 자동으로 제출되는 truncate모든 명령문(데이터 정의 언어)입니다 .DDL

차이점:

  1. 잘라내기 및 삭제는 테이블 구조를 삭제하지 않고 데이터만 삭제하며, drop 문은 테이블 구조가 의존하는 제약 조건, 트리거 및 인덱스를 삭제합니다.
  2. 일반적으로 실행 속도는 삭제 > 자르기 > 삭제입니다.

이들갖다그리고 어디서의 차이점은 무엇인가요?

  • 작동하는 개체는 다르며, where절은 테이블, 뷰 및 having그룹에 작동합니다.
  • where데이터 그룹화 전 필터링 및 having데이터 그룹화 후 필터링.

마스터-슬레이브 동기화를 수행해야 하는 이유는 무엇입니까?

  1. 읽기와 쓰기를 분리하면 데이터베이스가 더 큰 동시성을 지원할 수 있습니다.
  2. 마스터 서버에서 실시간 데이터를 생성하고 슬레이브 서버에서 분석하여 마스터 서버의 성능을 향상시킵니다.
  3. 데이터 보안을 보장하기 위한 데이터 백업.

MySQL 마스터-슬레이브 동기화란 무엇입니까?

마스터-슬레이브 동기화를 통해 한 데이터베이스 서버에서 다른 서버로 데이터를 복사할 수 있으며, 데이터 복사 시 한 서버는 마스터 서버( ) 역할을 master하고 나머지 서버는 슬레이브 서버( ) 역할을 합니다 slave.

복제는 비동기식으로 이루어지기 때문에 슬레이브 서버가 마스터 서버에 항상 연결될 필요는 없으며, 슬레이브 서버는 다이얼업을 통해 간헐적으로 마스터 서버에 연결될 수도 있습니다. 구성 파일을 통해 모든 데이터베이스, 특정 데이터베이스 또는 특정 데이터베이스의 특정 테이블을 복사하도록 지정할 수 있습니다.

낙관적 잠금과 비관적 잠금이란 무엇입니까?

데이터베이스의 동시성 제어는 여러 트랜잭션이 동시에 데이터베이스의 동일한 데이터에 액세스할 때 트랜잭션의 격리 및 통일성과 데이터베이스의 통일성이 파괴되지 않도록 보장합니다. 낙관적 잠금과 비관적 잠금은 동시성 제어에 사용되는 주요 기술 수단입니다.

  • 비관적 잠금(Pessimistic lock): 동시성 충돌이 발생할 것으로 가정하여 운영 중인 데이터를 잠그고, 트랜잭션이 제출될 때까지 잠금이 해제되지 않으며 다른 트랜잭션이 이를 수정할 수 있습니다. 구현 방법: 데이터베이스에서 잠금 메커니즘을 사용합니다.
  • 낙관적 잠금: 동시성 충돌이 발생하지 않는다고 가정하고 작업을 제출할 때 데이터가 수정되었는지 여부만 확인합니다. 테이블에 필드를 추가 하고 version수정 사항을 제출하기 전에 version원래 값과 동일한지 확인합니다 version. 동일하면 데이터가 수정되지 않았으므로 업데이트할 수 있음을 의미하고, 그렇지 않으면 해당 데이터는 더티 데이터이므로 업데이트할 수 없습니다. 업데이트되었습니다. 구현 방법: 낙관적 잠금은 일반적으로 버전 번호 메커니즘이나 CAS알고리즘을 사용하여 구현됩니다.

프로세스리스트를 사용해 본 적이 있나요?

show processlist또는 show full processlistMySQL이 현재 압박을 받고 있는지, 실행 중인지 SQL, SQL느리게 실행되고 있는지 확인할 수 있습니다. 반환 매개변수는 다음과 같습니다:

  1. idkill id : 스레드 ID, 스레드를 종료하는 데 사용할 수 있습니다.
  2. db : 데이터베이스 이름
  3. 사용자 : 데이터베이스 사용자
  4. 호스트 : 데이터베이스 인스턴스의 IP
  5. commandSleep : , 등 현재 실행되는 명령 입니다 Query.Connect
  6. time : 소비시간, 단위 초
  7. state : 주로 다음 상태를 포함하는 실행 상태:
    • 절전 모드, 스레드는 클라이언트가 새 요청을 보내기를 기다리고 있습니다.
    • 잠김, 스레드가 잠금을 기다리고 있습니다.
    • 데이터 전송, 쿼리 기록 처리 SELECT, 결과를 동시에 클라이언트에 전송
    • Kill, 실행 kill명령문은 지정된 스레드를 종료합니다.
    • 연결, 슬레이브 노드가 마스터 노드에 연결됩니다.
    • 종료하세요. 스레드가 종료됩니다.
    • 그룹별로 정렬, GROUP BY정렬
    • 순서대로 정렬, ORDER BY정렬
  8. info : 실행 중인 SQL명령문

MySQL 쿼리 제한 1000,10이 제한 10만큼 빠릅니까?

두 가지 쿼리 방법. limit offset, size및 의 두 가지 방법에 해당합니다 limit size.

실제로 limit size는 와 동일합니다 limit 0, size. 즉, 크기 데이터를 0부터 가져오기 시작합니다.

즉, 두 방법의 차이점은 offset이 0인지 아닌지 입니다.

먼저 Limit SQL의 내부 실행 로직을 살펴보겠습니다.

MySQL은 내부적으로 서버 레이어스토리지 엔진 레이어 로 구분됩니다 . 일반적인 상황에서 스토리지 엔진은 innodb를 사용합니다.

서버 계층에는 많은 모듈이 있는데, 주목해야 할 점은 실행기가 스토리지 엔진을 처리하는 데 사용되는 구성 요소라는 점입니다.

실행자는 스토리지 엔진이 제공하는 인터페이스를 호출하여 데이터 행을 검색할 수 있으며, 데이터가 요구 사항(예: 다른 where 조건 충족)을 완전히 충족하면 결과 집합 에 배치되고 마지막으로 mysql을 호출하는 클라이언트에 반환 됩니다 .

기본 키 인덱스의 제한 실행 프로세스를 예로 들어 보겠습니다.

실행 시 select * from xxx order by id limit 0, 10;선택 뒤에는 별표가 표시됩니다. 이는 행 데이터의 모든 필드 정보가 필요함을 의미합니다.

서버 계층은 innodb의 인터페이스를 호출하고 innodb의 기본 키 인덱스에서 0부터 10까지의 전체 행 데이터를 얻은 다음 이를 서버 계층에 반환하고 이를 서버 계층의 결과 집합에 넣고 반환합니다. 클라이언트에게.

예를 들어 오프셋을 더 크게 만듭니다. 실행은 다음과 같습니다.select * from xxx order by id limit 500000, 10;

서버 계층은 innodb의 인터페이스를 호출합니다. 이때 오프셋=500000이므로 0에서 (500000 + 10)까지 의 전체 행 데이터는 innodb의 기본 키 인덱스에서 가져옵니다. 서버 계층으로 반환 후 오프셋 값에 따라 하나씩 폐기되고, 마지막으로 마지막 크기 항목 인 10개의 데이터만 서버 계층의 결과 세트에 남아 클라이언트로 반환됩니다.

오프셋이 0이 아닌 경우 서버 계층은 엔진 계층에서 쓸모 없는 데이터를 많이 얻게 되며 이러한 쓸모 없는 데이터를 얻는 데 시간이 많이 걸리는 것을 알 수 있습니다 .

따라서 mysql 쿼리의 제한 1000,10은 제한 10보다 느립니다. 그 이유는 1000,10을 제한하면 1000+10개 데이터 조각을 꺼내고 처음 1000개 조각을 삭제하므로 시간이 더 많이 걸리기 때문입니다.

높이가 3인 B+ 트리에는 얼마나 많은 데이터를 저장할 수 있습니까?

InnoDB 스토리지 엔진에는 자체 최소 저장 단위(페이지)가 있습니다.

InnoDB 페이지 크기를 쿼리하는 명령은 다음과 같습니다.

mysql> show global status like 'innodb_page_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| Innodb_page_size | 16384 |
+------------------+-------+

innodb의 기본 페이지 크기는 16384B = 16384/1024 = 16kb임을 알 수 있습니다.

MySQL에서는 B+ 트리의 노드 크기를 한 페이지 또는 페이지의 배수로 설정하는 것이 가장 적합합니다. 노드의 크기가 1페이지 미만인 경우 이 노드를 읽을 때 실제로 한 페이지를 읽어 리소스 낭비가 발생하기 때문입니다.

B+ 트리의 리프 가 아닌 키 + 포인터를 저장 하고 리프 노드는 데이터 행을 저장합니다 .

리프 노드의 경우 행의 데이터 크기가 1k이면 한 페이지에 16개의 데이터를 저장할 수 있습니다.

리프가 아닌 노드의 경우 키가 bigint를 사용하면 8바이트이고, MySQL에서는 포인터가 6바이트이므로 총 14바이트이므로 16k는 16*1024/14=1170개의 인덱스 포인터를 저장할 수 있다.

따라서 높이가 2인 B+ 트리의 경우 루트 노드는 인덱스 포인터 노드를 저장하고 데이터를 저장하는 리프 노드는 1170개이며 각 리프 노드는 16개의 데이터를 저장할 수 있으므로 총 1170개를 저장할 수 있습니다. x 16 = 18720개의 데이터. 높이가 3인 B+ 트리의 경우 1170 x 1170 x 16 = 21902400개의 데이터( 2천만 개가 넘는 데이터 )를 저장할 수 있습니다. 즉, 2천만 개가 넘는 데이터에는 B+ 하나만 있으면 됩니다. 높이가 3인 트리입니다. 완료할 수 있으며 기본 키 쿼리를 통해 해당 데이터를 찾는 데 3번의 IO 작업만 필요합니다.

따라서 InnoDB에서는 B+ 트리의 높이가 일반적으로 3레벨이면 수천만 개의 데이터 저장 요구를 충족할 수 있습니다.

딥 페이징을 최적화하는 방법은 무엇입니까?

또는 위의 SQL을 비어 있는 것으로 간주합니다.select * from xxx order by id limit 500000, 10;

방법 1 :

위 분석에서 알 수 있듯이 오프셋이 매우 클 경우 서버 계층은 엔진 계층에서 쓸모 없는 데이터를 많이 얻게 되며 선택 뒤에 * 숫자가 오면 전체 행 정보를 복사해야 합니다. 전체 데이터를 복사하는 것 보다 행 데이터에서 하나 또는 두 개의 열 필드만 복사하는 것이 시간이 더 많이 걸립니다.

결국 이전 오프셋 데이터가 필요하지 않기 때문에 전체 필드를 복사할 필요가 없으므로 SQL 문을 다음과 같이 수정할 수 있습니다.

select * from xxx  where id >=(select id from xxx order by id limit 500000, 1) order by id limit 10;

먼저 하위 쿼리를 실행합니다 . 이 작업은 실제로 innodb의 기본 키 인덱스에서 데이터 조각을 select id from xxx by id limit 500000, 1가져옵니다 . 그런 다음 서버 계층은 처음 500,000개 조각을 버리고 마지막 데이터 조각의 ID만 유지합니다.500000+1

다만 차이점은 서버 레이어로 복귀하는 과정에서 데이터 행의 id 컬럼만 복사되고, 데이터 행의 모든 ​​컬럼은 복사되지 않는다는 점이다. 아주 분명합니다. .

위의 ID를 얻은 후 이 ID가 정확히 500000과 같다고 가정하면 SQL은 다음과 같습니다.

select * from xxx  where id >=500000 order by id limit 10;

이런 식으로 innodb는 기본 키 인덱스를 다시 거쳐 B+ 트리를 통해 id=500000인 행 데이터를 빠르게 찾아내고, 시간 복잡도는 lg(n)이 되며, 10개의 데이터를 뒤로 가져옵니다.

방법 2:

ID의 기본 키에 따라 모든 데이터를 정렬한 후 일괄적으로 검색하고, 현재 배치의 최대 ID를 쿼리의 다음 필터링 조건으로 사용합니다.

select * from xxx where id > start_id order by id limit 10;

기본키 인덱스를 통해 매번 start_id의 위치를 ​​찾아 10개의 데이터를 순회하므로, 데이터의 양이 아무리 많아도 쿼리 성능은 비교적 안정적이다.

느린 경우 대형 테이블 쿼리를 최적화하는 방법은 무엇입니까?

특정 테이블에 천만개에 가까운 데이터가 있는데 쿼리 속도가 느립니다. 어떻게 최적화하나요?

단일 MySQL 테이블의 레코드 수가 너무 많으면 데이터베이스 성능이 크게 저하됩니다. 몇 가지 일반적인 최적화 조치는 다음과 같습니다.

  • 색인을 올바르게 작성하십시오. 해당 필드에 인덱스를 생성합니다(예: WHERE 및 ORDER BY 명령에 포함된 열에 인덱스를 생성합니다. EXPLAIN을 사용하면 인덱스 또는 전체 테이블 스캔이 사용되는지 확인할 수 있습니다.
  • 인덱스 최적화, SQL 최적화. 가장 왼쪽 일치 원칙 등은 https://topjavaer.cn/database/mysql.html#%E4%BB%80%E4%B9%88%E6%98%AF%E8%A6%86%E7을 참조하세요. %9B %96%E7%B4%A2%E5%BC%95
  • 파티션을 생성합니다. 시간 필드와 같은 주요 필드에 대해 수평 파티셔닝을 설정합니다. 시간 범위를 통해 쿼리 조건을 자주 쿼리하는 경우 성능이 크게 향상될 수 있습니다.
  • 캐싱을 활용하세요. Redis 및 기타 캐시 핫스팟 데이터를 사용하여 쿼리 효율성 향상
  • 데이터의 범위를 제한하십시오. 예를 들어, 사용자가 과거 정보를 쿼리할 때 한 달의 시간 범위 내에서 이를 제어할 수 있습니다.
  • 읽기와 쓰기의 분리. 클래식 데이터베이스 분할 방식, 마스터 데이터베이스는 쓰기를 담당하고 슬레이브 데이터베이스는 읽기를 담당합니다.
  • 최적화는 하위 데이터베이스와 하위 테이블을 통해 이루어지며 주로 수직 분할과 수평 분할을 포함합니다.
  • 색인을 올바르게 작성하십시오. WHERE 및 ORDERBY 명령과 관련된 열에 대한 색인화와 같은 적절한 필드에 대한 색인화
  1. es에 대한 데이터 이질성
  2. 핫 데이터와 콜드 데이터의 분리. 몇 달 전에는 일반적으로 사용되지 않았던 데이터를 콜드 스토리지에 보관하고, 최신 데이터는 핫 스토리지에 보관합니다.
  3. 데이터베이스 유형을 MySQL과 호환되는 데이터베이스(OceanBase, tidb)로 업그레이드하세요.

데이터베이스와 테이블을 분할하기 위한 MySQL의 단일 테이블 크기는 얼마나 됩니까?

현재 두 가지 주류 이론이 있습니다.

  1. 단일 MySQL 테이블의 데이터 볼륨이 2천만 행을 초과하면 성능이 크게 저하되므로 데이터베이스 및 테이블을 샤딩하는 것을 고려하십시오.
  2. Alibaba의 "Java 개발 매뉴얼"에는 단일 테이블의 행 수가 500만 개를 초과하거나 단일 테이블의 용량이 2GB를 초과하는 경우에만 데이터베이스 및 테이블 샤딩을 권장한다고 명시되어 있습니다.

실제로 이 값은 실제 레코드 수와는 아무런 관련이 없으며 MySQL의 구성 및 머신의 하드웨어와 관련이 있습니다. MySQL은 성능 향상을 위해 테이블의 인덱스를 메모리에 로드하기 때문입니다. InnoDB 버퍼 크기가 충분하면 메모리에 완전히 로드될 수 있으며 쿼리에 문제가 없습니다. 그러나 단일 테이블 데이터베이스가 특정 크기의 상한에 도달하면 메모리가 인덱스를 저장할 수 없어 후속 SQL 쿼리에서 디스크 IO가 발생하여 성능이 저하됩니다. 물론 이는 특정 테이블 구조의 설계와도 관련이 있으며, 궁극적인 문제는 메모리 제한이다.

따라서 서브 데이터베이스와 테이블에 대해서는 무리한 설계가 아닌 실제 요구 사항을 결합하는 것이 필요하며, 프로젝트 초기에는 서브 데이터베이스 및 서브 테이블 디자인을 사용하지 않습니다. 지속적인 최적화가 불가능할 경우 하위 데이터베이스를 고려하십시오. 하위 테이블을 사용하여 시스템 성능을 향상시키십시오. 이에 대해 알리바바의 '자바 개발 매뉴얼'에는 "데이터 양이 3년 안에 이 수준에 도달하지 못할 것으로 예상된다면 테이블 생성 시 데이터베이스를 테이블로 나누지 말라"고 덧붙였다.

데이터베이스와 테이블로 구분할 단일 MySQL 테이블의 크기는 머신 리소스를 기준으로 평가해야 합니다.

count(1), count(*) 및 count(필드 이름)의 차이점에 대해 이야기해 보겠습니다.

자, 먼저 count(1)과 count(필드 이름)의 차이점에 대해 이야기해 보겠습니다.

둘 사이의 주요 차이점은

  1. count(1)은 null 필드가 있는 레코드를 포함하여 테이블의 모든 레코드 수를 계산합니다.
  2. count(필드 이름)은 필드가 null인 경우를 무시하고 이 필드가 테이블에 나타나는 횟수를 계산합니다. 즉, null 필드가 있는 레코드는 계산되지 않습니다.

다음으로 세 가지의 차이점을 살펴보겠습니다.

실행 효과 측면에서:

  • count(*)에는 행 수에 해당하는 모든 열이 포함되며, 결과 계산 시 NULL 열 값은 무시되지 않습니다.
  • count(1)에는 1을 사용하여 코드 라인을 표현하는 등 모든 열을 무시하는 기능이 포함되어 있으며, 결과를 계산할 때 NULL인 열 값은 무시되지 않습니다.
  • count(필드명)에는 컬럼 이름만 포함되며 결과 계산 시 빈 컬럼 값의 개수(여기서 비어 있다는 것은 단순히 빈 문자열이나 0을 의미하는 것이 아니라 null을 의미함)는 무시됩니다. 특정 필드 값은 NULL인 경우 통계가 수집되지 않습니다 .

실행 효율성 측면에서:

  • 열 이름은 기본 키이며 count(필드 이름)은 count(1)보다 빠릅니다.
  • 열 이름이 기본 키가 아닙니다. count(1)이 count(열 이름)보다 빠릅니다.
  • 테이블에 여러 열이 있고 기본 키가 없는 경우 count(1)이 count(*)보다 더 나은 성능을 발휘합니다.
  • 기본 키가 있는 경우 선택 횟수(기본 키)의 실행 효율성이 최적입니다.
  • 테이블에 필드가 하나만 있는 경우 select count(*)가 최적입니다.

MySQL에서 DATETIME과 TIMESTAMP의 차이점은 무엇입니까?

TIMESTAMP는 모두 DATETIME시간을 저장하는 데 사용할 수 있으며 다음과 같은 주요 차이점이 있습니다.

1. 표현범위

  • 날짜/시간: 1000-01-01 00:00:00.000000 ~ 9999-12-31 23:59:59.999999
  • 타임스탬프: '1970-01-01 00:00:01.000000' UTC 到 '2038-01-09 03:14:07.999999' UTC

TIMESTAMP지원되는 시간 범위는 비교적 DATATIME작으며 쉽게 초과될 수 있습니다.

2. 우주점령

  • 타임스탬프: 4바이트
  • DATETIME: MySQL 5.6.4 이전에는 8바이트를 차지했으나, 이후 버전에서는 5바이트를 차지한다.

3.입금시간이 자동으로 전환되나요?

TIMESTAMP기본적으로 데이터를 삽입하거나 업데이트할 때 TIMESTAMP해당 열은 자동으로 현재 시간( )으로 채워지거나 업데이트됩니다 CURRENT_TIMESTAMP. DATETIME어떤 변환도 수행하지 않으며 시간대도 감지하지 않으며, 사용자가 제공하는 모든 데이터를 저장합니다.

4. TIMESTAMP서버의 시간대, MYSQL 버전, SQL MODE의 영향을 더 많이 받습니다. 타임스탬프를 저장하기 때문에 TIMESTAMP서로 다른 시간대에서 얻은 시간은 일관성이 없습니다.

5. NULL이 저장되면 둘의 실제 저장값은 다르다.

  • TIMESTAMP: 현재 시간 now()가 자동으로 저장됩니다.
  • DATETIME: 현재 시간은 자동으로 저장되지 않고, NULL 값이 직접 저장됩니다.

외래 키를 사용하지 않는 것이 왜 권장되지 않는지 알려주세요.

외래 키는 제약 조건으로, 이 제약 조건이 존재하면 테이블 간의 데이터 관계가 항상 완전하다는 것을 보장합니다. 외래 키가 존재한다고 해서 장점이 전혀 없는 것은 아닙니다.

외래 키는 데이터 무결성과 일관성을 보장할 수 있으며 계단식 작업이 편리합니다. 또한 외래 키를 사용하면 데이터 무결성 판단을 데이터베이스에 맡길 수 있어 프로그램의 코드 양을 줄일 수 있습니다.

외래 키는 데이터 무결성을 보장할 수 있지만 시스템에 많은 결함을 가져올 수 있습니다.

1. 동시성 문제. 외래키를 사용할 경우 데이터를 수정할 때마다 다른 테이블의 데이터를 확인하고 추가 잠금을 획득해야 한다. 동시성이 높고 트래픽이 많은 트랜잭션 시나리오에서는 외래 키를 사용하면 교착 상태가 발생할 가능성이 더 높습니다.

2. 확장성 문제. 예를 들어 MySQL새로운 데이터베이스로 마이그레이션할 때 Oracle외래키는 데이터베이스 자체의 특성에 따라 달라지므로 마이그레이션이 불편할 수 있다.

3. 하위 데이터베이스 및 하위 테이블에는 도움이 되지 않습니다. 수평 분할 및 샤딩의 경우 외래 키가 적용되지 않습니다. 데이터 간의 관계 유지 관리를 애플리케이션에 넣으면 향후 데이터베이스 및 테이블 세분화에 대한 많은 문제를 줄일 수 있습니다.

자동 증가 기본 키를 사용하면 어떤 이점이 있나요?

자동 증가 기본 키를 사용하면 기본 키 인덱스가 증분 삽입 순서를 최대한 유지하여 페이지 분할을 방지할 수 있으므로 쿼리 시 인덱스가 더 컴팩트해지고 효율성이 높아집니다.

InnoDB의 스스로 증가하는 가치를 왜 재활용할 수 없나요?

주로 데이터 삽입의 효율성과 병렬성을 향상시킵니다.

두 개의 트랜잭션이 병렬로 실행된다고 가정하면, 자동 증가 값을 적용할 때 두 트랜잭션이 동일한 자동 증가 ID를 적용하는 것을 방지하기 위해 잠금을 걸어 순차적으로 적용해야 합니다.

id=2에 트랜잭션 A가 적용되고, id=3에 트랜잭션 B가 적용된다고 가정하면, 이때 테이블 t의 자동 증가 값은 4가 되고 이후부터 계속 실행된다.

트랜잭션 B는 올바르게 커밋되었지만 트랜잭션 A에는 고유 키 충돌이 있었습니다.

트랜잭션 A가 자동 증가 ID를 롤백할 수 있는 경우, 즉 테이블 t의 현재 자동 증가 값을 다시 2로 변경하면 다음과 같은 상황이 발생합니다. 이미 id=3인 행이 있습니다. 테이블이며 현재 자동 증가 ID 값은 2입니다.

다음으로 계속 실행되는 다른 트랜잭션은 id=2를 적용한 후 id=3을 적용합니다. 이때 삽입문 오류 "기본 키 충돌"이 나타납니다.

이 기본 키 충돌을 해결하려면 다음 두 가지 방법이 있습니다.

  • ID를 신청할 때마다 먼저 해당 ID가 테이블에 이미 존재하는지 확인합니다. 존재하는 경우 이 ID를 건너뛰십시오. 그러나 이 방법은 비용이 많이 듭니다. 원래 ID를 신청하는 것은 빠른 작업이었지만 이제는 기본 키 인덱스 트리로 가서 ID가 존재하는지 확인해야 합니다.
  • 자동 증가 ID의 잠금 범위를 확장하려면 다음 트랜잭션이 자동 증가 ID를 신청할 수 있기 전에 트랜잭션이 완료되고 제출될 때까지 기다려야 합니다. 이 방법의 문제점은 잠금 세분성이 너무 크고 시스템의 동시성 성능이 크게 감소한다는 것입니다.

두 방법 모두 성능 문제를 야기한다는 것을 알 수 있습니다.

따라서 InnoDB는 "자동 증가 ID의 롤백을 허용"하는 설계를 포기했으며, 명령문 실행에 실패하면 자동 증가 ID는 롤백되지 않습니다.

자동 증가 기본 키는 어디에 저장됩니까?

엔진마다 자동 증가 값에 대한 저장 전략이 다릅니다.

  • MyISAM 엔진의 자동 증가 값은 데이터 파일에 저장됩니다.
  • MySQL 8.0 이전에는 InnoDB 엔진의 자동 증가 값이 메모리에 저장되었습니다. MySQL이 재시작되면 메모리에 있는 이 값은 사라지게 되며, 재시작 후 처음으로 테이블을 열면 self-increment max(id)의 최대값을 찾아 최대값에 self로 1을 더하게 된다. - 테이블의 증가 값, MySQL8 .0 버전은 리두 로그에 자체 증가 변경 사항을 기록하고, 재시작 시 리두 로그를 사용하여 복구합니다.

자동 증가 기본 키는 연속적이어야 합니까?

반드시 그런 것은 아니지만 자동 증가 기본 키가 불연속적으로 되는 상황이 여러 가지 있습니다.

1. 고유 키 충돌로 인해 자동 증가 기본 키가 불연속됩니다. 자동 증가 기본 키를 사용하여 InnoDB 테이블에 데이터를 삽입할 때 테이블에 정의된 고유 인덱스의 고유 제약 조건을 위반하면 데이터 삽입이 실패합니다. 이때 테이블의 자동 증가 기본 키의 키 값은 1씩 롤백됩니다. 다음에 다시 데이터를 삽입할 때에는 데이터 삽입 실패로 인해 마지막 스크롤로 생성된 키값을 더 이상 사용할 수 없으며, 반드시 새로운 스크롤로 생성된 키값을 사용해야 합니다.

2. 트랜잭션 롤백으로 인해 자동 증가 기본 키가 중단됩니다. 자동 증가 기본 키를 사용하여 InnoDB 테이블에 데이터를 삽입할 때 트랜잭션이 명시적으로 활성화된 후 어떤 이유로 트랜잭션이 최종적으로 롤백되면 테이블의 자동 증가 값도 이때 롤백됩니다. 다음에 새로 삽입되는 데이터는 롤링된 자동 증가 값을 사용할 수 없지만 새로운 자동 증가 값을 다시 적용해야 합니다.

3. 일괄 삽입으로 인해 불연속적인 자체 증가 값이 발생합니다. MySQL에는 자체 증가 ID를 일괄 적용하는 전략이 있습니다.

  • 명령문 실행 중 최초로 자동증가 ID를 신청하면 1개의 자동증가 ID가 할당됩니다.
  • 1개 소진 후, 2번째 신청 시 자동증가되는 2개의 ID가 할당됩니다.
  • 2개 소진 후, 3번째 신청 시 자동증가되는 4개의 ID가 할당됩니다.
  • 등등, 각 애플리케이션은 이전 애플리케이션의 두 배입니다(마지막 애플리케이션이 모두 사용되지 않을 수도 있음).

다음 트랜잭션에서 다시 데이터를 삽입하면 이전 트랜잭션 적용 이후의 자체 증가분을 기준으로 적용됩니다. 이때 자체 증가 값은 불연속적입니다.

4. 자동 증가 단계 크기가 1이 아닌 경우에도 자동 증가 기본 키가 불연속됩니다.

MySQL 데이터를 Redis 캐시에 동기화하는 방법은 무엇입니까?

참고: https://cloud.tencent.com/developer/article/1805755

두 가지 옵션이 있습니다:

1. Redis는 MySQL 트리거 + UDF 기능 으로 구현된 MySQL을 통해 동기적으로 자동으로 새로 고쳐집니다 .

프로세스는 대략 다음과 같습니다.

  1. 동작할 데이터에 대해 MySQL에 트리거를 설정하고 동작을 모니터링
  2. 클라이언트가 MySQL에 데이터를 쓰면 트리거가 트리거되고, 트리거 후에 MySQL의 UDF 함수가 호출됩니다.
  3. UDF 기능은 동기화 효과를 달성하기 위해 Redis에 데이터를 쓸 수 있습니다.

2. MySQL의 binlog를 구문 분석하여 데이터베이스의 데이터를 Redis와 동기화합니다. 이것은 운하를 통해 달성될 수 있습니다. Canal은 데이터베이스 증분 로그 분석을 기반으로 증분 데이터 구독 및 소비를 제공하는 Alibaba 산하의 오픈 소스 프로젝트입니다.

운하의 원리는 다음과 같습니다.

  1. Canal은 mysql 슬레이브의 상호작용 프로토콜을 시뮬레이션하고, 자신을 mysql 슬레이브로 위장하고, 덤프 프로토콜을 mysql 마스터로 보냅니다.
  2. mysql 마스터는 덤프 요청을 수신하고 바이너리 로그를 운하로 푸시하기 시작합니다.
  3. canal은 바이너리 로그 객체(원래 바이트 스트림)를 구문 분석하고 데이터를 Redis에 동기적으로 씁니다.

Alibaba Java 매뉴얼에서 저장 프로시저 사용을 금지하는 이유는 무엇입니까?

먼저 저장 프로시저가 무엇인지 살펴보겠습니다.

저장 프로시저는 대규모 데이터베이스 시스템에서 특정 기능을 완료하는 데 사용되는 SQL 문의 집합입니다. 데이터베이스에 저장되며 한 번 컴파일된 후에는 영구적으로 유효합니다. 사용자가 저장 프로시저의 이름을 지정하고 매개변수를 제공합니다. (저장 프로시저에 매개변수가 있는 경우) 이를 실행합니다.

저장 프로시저에는 주로 다음과 같은 단점이 있습니다.

  1. 저장 프로시저는 디버그하기 어렵습니다 . 저장 프로시저 개발에는 항상 효과적인 IDE 환경이 부족했습니다. SQL 자체가 매우 긴 경우가 많으며, 디버깅하려면 문장을 분할하여 독립적으로 실행해야 하므로 매우 번거롭습니다.
  2. 휴대성이 좋지 않습니다 . 저장 프로시저를 이식하는 것은 어렵습니다. 일반적으로 비즈니스 시스템에서는 필연적으로 데이터베이스의 고유한 특성과 구문을 사용하게 되며, 데이터베이스를 교체할 때 코드 중 이 부분을 다시 작성해야 하므로 비용이 많이 듭니다.
  3. 관리상의 어려움 . 저장 프로시저의 디렉토리는 파일 시스템과 같은 트리 구조가 아닌 플랫(Flat)한 구조로 스크립트가 적을 때는 다루기 쉽지만 너무 많으면 디렉토리가 혼란스러워집니다.
  4. 저장 프로시저는 한 번만 최적화 되며 때로는 데이터 양이 증가하거나 데이터 구조가 변경됨에 따라 원래 저장 프로시저에서 선택한 실행 계획이 최적이 아닐 수 있으므로 이때 수동 개입이나 재컴파일이 필요합니다.

마지막으로 C 언어, C++, Java, Python, 프런트 엔드, 데이터베이스, 운영 체제, 컴퓨터 네트워크, 데이터 구조를 포함하여 Dabin이 편집한 300개 이상의 고전 컴퓨터 서적 PDF가 포함된 Github 저장소를 공유하고 싶습니다. 그리고 알고리즘, 머신러닝, 프로그래밍라이프 등 다음번에 책을 찾을 때 별표표시하고 바로 검색할 수 있습니다. 창고는 지속적으로 업데이트 중입니다! Github 주소

Github에 접근할 수 없는 경우, 코드 클라우드 주소에 접근할 수 있습니다. 코드 클라우드 주소

추천

출처blog.csdn.net/Tyson0314/article/details/132159169