이 기사는 MySQL의 InnoDB 스토리지 엔진에 대한 자세한 소개(코드 예제)를 제공합니다. 이는 특정 참고 가치가 있으므로 도움이 될 수 있습니다.
InnoDB는 MySQL의 스토리지 엔진 계층에 속하며 플러그인 형태로 데이터베이스에 통합됩니다. MySQL 5.5.8부터 InnoDB가 기본 스토리지 엔진이 됩니다. InnoDB 스토리지 엔진은 트랜잭션을 지원하며 설계 목표는 주로 OLTP 애플리케이션을 위한 것입니다. 주요 기능에는 트랜잭션 지원, 높은 동시성을 지원하는 행 잠금 설계, 외래 키 지원, 자동 충돌 복구, 클러스터형 인덱스 구성 테이블 구조 등이 포함됩니다. (관련 권장사항: MySQL 튜토리얼)
Architecture
InnoDB 스토리지 엔진은 메모리 풀, 백그라운드 스레드, 디스크 스토리지의 세 부분으로 구성됩니다.
Threads
InnoDB는 멀티스레딩 모델을 사용하며, InnoDB의 배경에는 다양한 작업을 처리하는 여러 개의 서로 다른 스레드가 있습니다.
Master Thread는 주로 데이터 처리를 담당하는 핵심 배경 스레드입니다. 버퍼 풀은 데이터 일관성을 보장하기 위해 비동기적으로 디스크에 플러시됩니다. 더티 페이지 새로 고침, 병합된 삽입 버퍼, UNDO 페이지 재활용 등을 포함합니다.
비동기 IO(Async IO)는 쓰기 IO 요청을 처리하기 위해 InnoDB 스토리지 엔진에서 광범위하게 사용됩니다. IO 스레드의 작업은 주로 이러한 IO 요청의 콜백을 담당합니다.
트랜잭션이 커밋된 후에는 트랜잭션에 사용된 실행 취소 로그가 더 이상 필요하지 않을 수 있으므로 할당되고 사용된 UNDO 페이지를 재활용하려면 퍼지 스레드가 필요합니다. InnoDB는 UNDO 페이지 재활용 속도를 높이고 CPU 사용량을 늘리며 스토리지 엔진 성능을 향상시킬 수 있는 다중 퍼지 스레드를 지원합니다.
페이지 클리너 스레드는 마스터 스레드의 더티 페이지 새로 고침 작업을 대체하는 데 사용됩니다. 그 목적은 원래 마스터 스레드의 작업과 사용자 쿼리 스레드의 차단을 줄이고 성능을 더욱 향상시키는 것입니다. InnoDB 스토리지 엔진.
Memory
InnoDB 스토리지 엔진 메모리 구조
InnoDB 스토리지 엔진은 디스크 스토리지를 기반으로 하며, 기록을 페이지 단위로 관리합니다. 그러나 CPU 속도와 디스크 속도 사이의 차이로 인해 디스크 기반 데이터베이스 시스템은 데이터베이스의 전반적인 성능을 향상시키기 위해 버퍼 풀 레코드를 사용하는 경우가 많습니다.
버퍼 풀은 실제로 메모리 속도를 사용하여 느린 디스크 속도가 데이터베이스 성능에 미치는 영향을 보상합니다. 데이터베이스가 읽기 작업을 수행하면 디스크의 페이지가 먼저 버퍼 풀에 저장됩니다. 다음에 동일한 페이지를 읽을 때 먼저 버퍼 풀에서 페이지 데이터를 가져와 캐시 역할을 합니다.
데이터 수정 작업은 먼저 버퍼 풀의 페이지 데이터를 수정한 다음 체크포인트라는 메커니즘을 사용하여 이를 디스크에 플러시합니다.
버퍼 풀의 크기는 데이터베이스의 전체 성능에 직접적인 영향을 미칩니다. InnoDB 스토리지 엔진의 경우 버퍼 풀 구성은 innodb_buffer_pool_size 매개변수를 통해 설정됩니다. SHOW VARIABLES LIKE 'innodb_buffer_pool_size'
명령을 사용하여 버퍼 풀 구성을 봅니다.
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size' \G *************************** 1. row *************************** Variable_name: innodb_buffer_pool_size Value: 134217728 1 row in set (0.01 sec)
버퍼 풀에 캐시된 데이터 페이지 유형은 인덱스 페이지, 실행 취소 페이지, 삽입 버퍼, 적응형 해시 인덱스, InnoDB 잠금 정보, 데이터 사전 정보 등입니다. 인덱스 페이지와 데이터 페이지는 버퍼 풀의 많은 부분을 차지합니다.
버퍼 풀의 페이지 데이터가 디스크보다 최신인 경우 새 데이터를 디스크에 플러시해야 합니다. InnoDB는 데이터를 새로 고치기 위해 Write Ahead Log 전략을 사용합니다. 즉, 트랜잭션이 제출되면 리두 로그 버퍼가 특정 빈도로 재설정 로그 파일에 먼저 기록되고 더티 페이지가 기록됩니다. 체크포인트 메커니즘에 따라 디스크로 플러시됩니다.
리두 로그 버퍼는 큰 크기로 설정할 필요가 없습니다. 일반적으로 8M는 대부분의 애플리케이션 시나리오를 충족할 수 있습니다. 리두 로그는 새로 고침을 트리거하는 다음 세 가지 상황을 지원합니다.
마스터 스레드는 매초마다 리두 로그 버퍼를 리두 로그 파일로 플러시합니다.
트랜잭션이 커밋될 때마다 리두 로그 버퍼를 리두 로그로 플러시합니다. 파일
리두 로그 버퍼 풀의 남은 공간이 1/2 미만이 되면 리두 로그 버퍼는 리두 로그 파일로 플러시됩니다.
InnoDB 스토리지 엔진에서는, 메모리는 메모리 힙이라는 것을 통해 관리됩니다. 일부 데이터 구조 자체의 메모리를 할당할 경우에는 추가 메모리 풀에서 적용해야 합니다. 이 영역의 메모리가 부족할 경우 버퍼 풀에서 적용됩니다.
잠금
InnoDB에서 지원하는 잠금은 다음과 같습니다:
공유 잠금 및 독점 잠금
의도 잠금
기록 잠금
간격 잠금
자동 증분 잠금
InnoDB 엔진은 공유(S) 잠금과 배타적(X) 잠금이라는 두 가지 표준 행 수준 잠금을 구현합니다. 공유 잠금을 사용하면 잠금을 보유한 트랜잭션이 데이터 행을 읽을 수 있으며, 배타적 잠금을 사용하면 트랜잭션이 레코드 행에 쓸 수 있습니다.
트랜잭션이 공유 잠금을 보유하는 경우 다른 트랜잭션은 여전히 이 레코드 행의 공유 잠금을 얻을 수 있지만 이 레코드 행의 배타적 잠금을 얻을 수는 없습니다. 트랜잭션이 행에 대한 배타적 잠금을 획득하면 다른 트랜잭션은 더 이상 이 행에 대한 공유 잠금 및 배타적 잠금을 획득할 수 없습니다.
InnoDB에서 의도 잠금은 테이블 수준 잠금으로 공유 잠금과 배타적 잠금으로 구분됩니다.
Record lock
Gap lock
자동 증분 잠금
ACID
Transaction은 OLTP로서 데이터베이스의 가장 중요한 기능이며 반드시 트랜잭션에 관해 언급할 때 언급됨 ACID의 네 가지 기본 특성:
일관성: 트랜잭션이 시작되고 끝난 후에도 데이터베이스의 무결성이 파괴되지 않습니다
격리: 서로 다른 트랜잭션을 수행합니다. 네 가지 격리 수준은 RU(커밋되지 않은 읽기), RC(커밋된 읽기), RR(반복 읽기) 및 SERIALIZABLE(직렬화)입니다.
Persistence (내구성): 트랜잭션이 제출된 후 데이터 수정 사항은 영구적이며 시스템이 실패하더라도 손실되지 않습니다.
InnoDB의 원자성, 지속성 및 일관성 주로 Redo Log, Undo Log 및 Force Log at Commit 메커니즘을 통해 수행됩니다. Redo Log는 충돌 발생 시 데이터를 복구하는 데 사용되며 Undo Log는 트랜잭션의 영향을 취소하는 데 사용되며 다중 버전 제어에도 사용할 수 있습니다. 커밋 시 강제 로그 메커니즘은 트랜잭션이 커밋된 후에도 리두 로그가 지속되도록 보장합니다. 잠금 및 MVCC를 통해 격리가 보장됩니다.
MySQL에서 트랜잭션에는 4가지 격리 수준이 있습니다.
Read Uncommitted Uncommitted Read
읽기 커밋됨 읽기 커밋됨
반복 읽기 반복 읽기
# 🎜🎜##🎜 🎜#Dirty read
반복 읽기, 이 수준은 동일한 트랜잭션에서 동일한 레코드를 여러 번 읽은 결과의 일관성을 보장하고 InnoDB 스토리지 엔진의 팬텀 읽기 및 반복 불가능 읽기 문제를 모두 해결합니다.
InnoDB 엔진은 Next-Key Lock
을 사용하여 팬텀 읽기 문제를 해결합니다. Next-Key Lock
은 행 잠금과 간격 잠금의 조합입니다. InnoDB는 인덱스 레코드를 스캔할 때 먼저 인덱스 레코드에 행 잠금(Record Lock)을 추가한 다음 행 잠금을 추가합니다. (레코드 잠금)을 인덱스 레코드의 양쪽 공백에 연결합니다. 갭 잠금을 추가한 후에는 다른 트랜잭션이 이 갭의 레코드를 수정하거나 삽입할 수 없습니다. Next-Key Lock
解决了幻读的问题。Next-Key Lock
是行锁和间隙锁的组合,当InnoDB扫描索引记录的时候,会首先对索引记录加上行锁(Record Lock),再对索引记录两边的间隙加上间隙锁(Gap Lock)。加上间隙锁之后,其他事务就不能在这个间隙修改或者插入记录。
Serializable 是最高的隔离级别,它通过强制事务串行执行,避免了幻读的问题,但是 Serializable 会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题,因此并发度急剧下降,在MySQL InnoDB同样不被建议使用。
BEGIN、BEGIN WORK、START TRANSACTION
执行BEGIN命令不会真正在引擎层开启新事务,仅仅是为当前线程设定标记,表示为显式开启的事务。
START TRANSACTION READ ONLY
开启只读事务,当MySQL Server接收到任何数据更改的SQL时,都会直接拒绝修改并返回错误,此错我不会进入引擎层。
START TRANSACTION READ WRITE
允许super用户在当前线程只读状态为true的情况下启动读写事务。
START TRANSACTION WITH CONSISTENT SNAPSHOT
开启事务会进入引擎层,并开启一个readview
。只有在RR隔离级别下,这种操作才有效,否则会报错。
在数据进行修改时会记录相应的undo日志,如果事务失败或者回滚,可以借助记录的undo日志进行回滚。Undo log是逻辑日志,记录更改前的数据镜像。在修改时如果同时需要读取当前数据的时候,它可以根据版本信息分析出该行记录以前版本的数据。另外Undo log也会产生重做日志,因为Undo log也要进行持久化保护。
使用全局事务ID产生器生成事务NO,将当前连接的事务指针(trx_t
)添加到全局提交事务链表(trx_serial_list
)中
标记undo,如果这个事务只使用了一个UndoPage且使用量小于3/4个Page,则把这个Page标记为TRX_UNDO_CACHED
,如果不满足且是insert undo
则标记为TRX_UNDO_TO_FREE
,否则undo为update undo则标记为TRX_UNDO_TO_PURGE
。标记为TRX_UNDO_CACHED
的undo会被引擎回收。
把update undo
放入所在undo segment
的history list
,并递增rseg_history_len
(全局)。同时更新Page上的TRX_UNDO_TRX_NO
, 如果删除了数据,则重置delete_mark
把undate undo
从update_undo_list
中删除,如果被标记为TRX_UNDO_CACHED
,则加入到update_undo_cached
队列中
mtr_commit
(日志undo/redo写入公共缓冲区),至此,在文件层次事务提交。这个时候即使crash,重启后依然能保证事务是被提交的。接下来要做的是内存数据状态的更新(trx_commit_in_memory
)
只读事务只需要把readview
从全局readview
链表中移除,然后重置trx_t
结构体里面的信息即可。读写事务首先需要是设置事务状态为TRX_STATE_COMMITTED_IN_MEMORY
,释放所有行锁并且将trx_t
从rw_trx_list
中移除,readview
从全局readview
链表中移除。如果有insert undo
则在这里移除,如果有update undo
则唤醒Purge线程进行垃圾清理,最后重置trx_t
里的信息,便于下一个事务使用
如果是只读事务,则直接返回
判断当前是回滚整个事务还是部分事务,如果是部分事务,则记录下需要保留多少个Undo log,多余的全进行回滚
从update undo
和insert undo
中找出最后一条undo,从这条undo开始回滚
如果是update undo
则将标记为删除的记录清理标记,更新过的数据回滚到最老的版本。如果是insert undo
읽기 보기
가 열립니다. > . 이 작업은 RR 격리 수준에서만 유효하며, 그렇지 않으면 오류가 보고됩니다. 🎜trx_t)전역 커밋 트랜잭션 목록에 추가합니다(<code>trx_serial_list
)🎜
TRX_UNDO_CACHED
로 표시하고, 만족하지 않고 실행 취소 삽입
인 경우 TRX_UNDO_TO_FREE
로 표시하고, 그렇지 않으면 실행 취소가 업데이트됩니다. 실행 취소한 다음 TRX_UNDO_TO_PURGE
로 표시하세요. TRX_UNDO_CACHED
로 표시된 실행 취소는 엔진에 의해 재활용됩니다. 🎜update undo
를 실행 취소 세그먼트
의 기록 목록
에 넣고 rseg_history_len
를 증가시킵니다. 코드>(글로벌). 동시에 페이지에서 TRX_UNDO_TRX_NO
를 업데이트하세요. 데이터가 삭제되면 delete_mark
🎜undate undo를 <code>update_undo_list
에서 삭제하세요. TRX_UNDO_CACHED
로 표시된 경우 update_undo_cached
대기열🎜
trx_commit_in_memory
)를 업데이트하는 것입니다🎜readview
만 변경하면 됩니다. readview
연결된 목록에서 제거한 다음 trx_t
구조의 정보를 재설정하세요. 읽기 및 쓰기 트랜잭션은 먼저 트랜잭션 상태를 TRX_STATE_COMMITTED_IN_MEMORY
로 설정하고, 모든 행 잠금을 해제하고, rw_trx_list
에서 trx_t
를 제거해야 합니다. readview 전역 <code>읽기 보기
목록에서 제거되었습니다. insert undo
가 있으면 여기서 제거하세요. update undo
가 있으면 Purge 스레드를 깨워서 쓰레기를 정리하고 마지막으로 의 정보를 재설정하세요. trx_t
, 다음 거래에 편리합니다🎜
update undo
및 insert undo
에서 마지막 실행 취소를 찾아 이 실행 취소에서 롤백을 시작하세요🎜업데이트 취소
인 경우 삭제 표시된 기록을 삭제하고 업데이트된 데이터를 가장 오래된 버전으로 롤백합니다. insert undo
라면 클러스터형 인덱스와 보조 인덱스를 직접 삭제하세요🎜모든 undo가 롤백되었거나 지정된 undo로 롤백된 경우 Undo 로그를 중지하고 삭제합니다.
Index
InnoDB 엔진은 B+ 트리를 인덱스 구조로 사용하고 리프 노드 데이터 필드는 기본 키 인덱스 전체 필드 데이터가 저장되고, 기본 키가 아닌 인덱스의 리프 노드는 기본 키를 가리키는 값 데이터를 저장합니다.
위 그림은 InnoDB 메인 인덱스(데이터 파일이기도 함)의 개략도입니다. 리프 노드에는 완전한 데이터 레코드가 포함되어 있는 것을 볼 수 있습니다. 이 인덱스를 클러스터형 인덱스라고 합니다. InnoDB의 데이터 파일 자체는 기본 키로 집계되기 때문에 InnoDB에서는 테이블에 기본 키가 있어야 합니다. 명시적으로 지정하지 않으면 MySQL 시스템은 기본 키로 데이터 레코드를 고유하게 식별할 수 있는 열을 자동으로 선택합니다. 열이 없으면 MySQL은 InnoDB 테이블의 기본 키로 암시적 필드를 자동으로 생성합니다. 이 필드의 길이는 6바이트이고 유형은 길다.
InnoDB의 보조 인덱스 데이터 필드에는 주소 대신 해당 레코드의 기본 키 값이 저장됩니다. 즉, InnoDB의 모든 보조 인덱스는 기본 키를 데이터 필드로 참조합니다. 클러스터형 인덱스를 구현하면 기본 키로 검색하는 것이 매우 효율적이지만 보조 인덱스 검색을 위해서는 인덱스를 두 번 검색해야 합니다. 먼저 보조 인덱스를 검색하여 기본 키를 얻은 다음 기본 키를 사용하여 기본 키에 있는 레코드를 검색합니다. 색인.
위 내용은 MySQL의 InnoDB 스토리지 엔진에 대한 자세한 소개(코드 예)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!