SQL이 느린 이유
프로세스가 일을 하지 않는 이유는 I/O 떄문이다.
프로세스가 I/O를 요청하고 CPU를 반환한다. 그리고 응답이 올때까지 기다린다.
프로세스는 응답이 올때까지 기다리기에, 기다리는 동안 프로세스는 일을 하지 않아 성능이 비효율적이기 된다.
I/O 대기
프로세스가 SQL을 실행하면, 데이터베이스 시스템은 디스크에서 데이터를 읽거나 쓰기 위해 I/O 요청을 보냅니다. 이때, 프로세스는 I/O가 완료될 때까지 기다리게 됩니다. 이 기간 동안 CPU는 해당 프로세스에 대한 작업을 중단하고, 다른 프로세스나 스레드에 작업을 할당할 수 있습니다. 이로 인해 다음과 같은 현상이 발생합니다:
- I/O 대기로 인한 지연: I/O 작업이 완료될 때까지 시간이 걸리기 때문에, 프로세스는 이 기간 동안 비활성 상태가 됩니다. 특히, 디스크 I/O는 상대적으로 느리기 때문에 지연이 발생할 수 있습니다.
- CPU 활용 비효율성: 프로세스가 I/O 대기를 하는 동안 CPU는 다른 작업을 수행할 수 있지만, 대기 중인 프로세스는 아무런 작업도 하지 않기 때문에 CPU 활용이 비효율적일 수 있습니다.
이로 인해 프로세스는 실행하고 대기를 하게 되고(I/O 응답이 올때까지 대기) 응답을 받으면 준비상태로 되었다가 다시 실행되기를 반복한다.
- 실행 상태(Running): 프로세스가 CPU에서 실제로 작업을 수행하고 있는 상태입니다. 이 단계에서 프로세스는 실행 중인 코드를 처리하고 있습니다.
- 대기 상태(Waiting): 프로세스가 I/O 요청을 보낸 후, 응답이 올 때까지 기다리는 상태입니다. 이때 프로세스는 CPU를 반환하고, 디스크 또는 네트워크 작업이 완료되기를 기다립니다.
- 준비 상태(Ready): I/O 응답을 받거나, 다른 조건이 충족되었을 때 프로세스가 다시 실행될 수 있는 상태입니다. 이 단계에서는 CPU 스케줄러가 해당 프로세스를 선택할 때까지 대기합니다.
아래는 프로세스의 실행주기입니다.
데이터 베이스의 저장 구조
데이터 베이스는 테이블스페이스, 세그먼트, 익스텐트, 블럭 이렇게 구성되어 있다.
제일 큰 개념으로 분류를 하자면 테이블 스페이스 > 세그먼트 > 익스텐트 > 블럭이다,
테이블스페이스
테이블스페이스는 데이터베이스 내에서 세그먼트(테이블, 인덱스 등)를 저장하는 논리적 컨테이너입니다. 하나의 데이터베이스는 여러 테이블스페이스를 가질 수 있으며, 각 테이블스페이스는 특정한 목적으로 사용됩니다.
세그먼트
세그먼트는 테이블, 인덱스, LOB(Large Object), 파티션 등으로 구분지어 저장하는 데이터베이스의 논리적 구조입니다. 세그먼트는 테이블스페이스 내에서 특정한 객체를 나타내며, 해당 객체의 모든 데이터는 이 세그먼트에 포함됩니다.
익스텐트
익스텐트는 데이터베이스에서 블럭의 집합을 나타냅니다. 익스텐트는 하나 이상의 연속된 블럭으로 구성되며, 세그먼트가 확장될 때 새로운 익스텐트가 할당됩니다. 익스텐트는 세그먼트의 저장 공간을 확장하는 기본 단위입니다.
블럭
블럭은 데이터베이스 I/O의 최소 단위이며, 블럭 안에는 레코드나 데이터 페이지가 있습니다. 데이터베이스가 데이터를 읽거나 쓸 때, 블럭 단위로 I/O 작업이 수행됩니다. 이로 인해 한 레코드를 읽더라도 해당 레코드가 포함된 전체 블럭을 읽게 됩니다.
일반적으로 데이터베이스에서 익스텐트와 블럭은 특정 테이블이나 세그먼트와 1:1 관계를 갖습니다. 이 말은, 특정 익스텐트와 블럭이 오직 한 개의 테이블이나 세그먼트에 속한다는 뜻입니다. 이 구조를 통해 데이터베이스는 각 테이블의 데이터가 독립적으로 관리되고, 다른 테이블과 혼동되지 않도록 할 수 있습니다.
그러나 몇 가지 주의해야 할 점과 예외사항이 있습니다:
- 세그먼트: 세그먼트는 일반적으로 하나의 테이블이나 인덱스를 나타내는 데이터베이스의 논리적 단위입니다. 각 세그먼트는 여러 익스텐트로 구성되며, 각 익스텐트는 여러 블럭을 포함합니다.
- 익스텐트와 블럭: 익스텐트는 여러 블럭으로 구성됩니다. 일반적으로, 하나의 세그먼트가 여러 익스텐트와 블럭을 가지므로, 익스텐트와 블럭은 하나의 세그먼트(또는 테이블)에 속합니다.
- 다중 클러스터: 일부 데이터베이스 환경에서는 클러스터링이나 파티셔닝 같은 개념이 도입되어, 여러 테이블이나 세그먼트가 동일한 익스텐트나 블럭을 공유할 수 있습니다. 그러나 일반적인 데이터베이스 구조에서는 익스텐트와 블럭은 하나의 테이블(또는 세그먼트)에 속합니다.
Data Block Address (DBA)
DBA는 데이터 블럭의 위치를 나타냅니다. 일반적으로 이 주소는 다음과 같이 구성됩니다:
- 데이터 파일 번호: 특정 데이터 블럭이 포함된 데이터 파일을 식별합니다.
- 블럭 번호: 해당 파일 내에서 데이터 블럭의 위치를 나타냅니다.
테이블 스캔과 세그먼트 헤더
테이블을 스캔할 때, 데이터베이스는 해당 테이블이 속한 세그먼트의 정보를 이용합니다. 세그먼트 헤더에는 해당 세그먼트에 대한 메타데이터가 저장되어 있습니다. 이 정보에는 세그먼트에 포함된 익스텐트들의 맵이 포함됩니다.
익스텐트 맵
익스텐트 맵은 세그먼트에 속한 익스텐트들의 목록을 나타냅니다. 이 맵에는 각 익스텐트의 시작 위치, 즉 첫 번째 DBA가 저장되어 있습니다. 이를 통해 테이블을 스캔하거나, 특정 데이터를 찾을 때 효율적으로 접근할 수 있습니다.
순차적 스캔
테이블을 순차적으로 스캔할 때, 데이터베이스는 세그먼트 헤더에 저장된 익스텐트 맵을 통해 각 익스텐트의 첫 번째 DBA를 찾습니다. 그런 다음, 해당 익스텐트의 블럭들을 순차적으로 스캔하여 데이터를 읽거나 처리합니다.
블럭 I/O
- DBMS는 데이터를 읽거나 쓸 때, 개별 레코드가 아닌 블럭 단위로 작업합니다.
- 블럭 하나는 여러 레코드로 구성될 수 있으며, 레코드의 개수는 블럭 크기와 레코드의 크기에 따라 달라집니다.
- 예를 들어, Oracle에서는 일반적으로 블럭 크기가 8KB입니다. 이 경우, 데이터를 읽거나 쓸 때 8KB 단위로 작업합니다.
블럭 단위 읽기/쓰기
- 하나의 레코드를 읽고 싶더라도, DBMS는 해당 레코드가 포함된 블럭 전체를 읽어 메모리(버퍼 캐시)에 로드합니다.
- 블럭 단위로 작업하기 때문에, 작은 크기의 데이터(예: 4바이트)를 읽거나 쓸 때도 블럭 크기만큼 I/O가 발생합니다.
- 블럭 크기가 클수록 한 번의 I/O로 더 많은 데이터를 읽을 수 있지만, 동시에 메모리와 스토리지 사용량이 늘어날 수 있습니다.
시퀀셜 엑세스 vs 랜덤 엑세스
시퀀셜 엑세스
- 시퀀셜 엑세스는 물리적 또는 논리적으로 연결된 순서에 따라 데이터를 읽는 것을 의미합니다. 시퀀셜 엑세스의 주요 이점은 디스크의 헤드 이동을 최소화하고, 연속적으로 데이터를 읽어들임으로써 I/O 성능을 향상시킬 수 있다는 점입니다.
- 테이블 세그먼트의 경우, 익스텐트 내의 블럭들은 일반적으로 물리적으로 순차적으로 저장됩니다. 따라서 익스텐트의 첫 블럭부터 시작하여 순차적으로 읽는 방식이 가능합니다. 이는 **테이블 전체를 스캔하는 경우(Full Table Scan)**에 해당합니다.
- 인덱스 세그먼트의 경우, 인덱스 리프 블럭은 더블 링크드 리스트(double-linked list)로 연결되어 있습니다. 이 구조 덕분에 인덱스 범위 스캔(Index Range Scan) 등에서 시퀀셜 엑세스를 수행할 수 있습니다. 인덱스 트리 구조를 따라 내려가며 리프 노드를 순차적으로 스캔할 수 있습니다.
랜덤 엑세스
- 랜덤 엑세스는 특정한 데이터나 레코드를 찾아 직접 해당 블럭을 읽는 접근 방식입니다. 이는 주로 인덱스를 사용하여 빠르게 특정 데이터를 찾거나, 특정 키 값에 해당하는 레코드를 조회할 때 발생합니다.
- 랜덤 엑세스는 디스크 헤드가 특정 위치로 이동하여 해당 블럭을 읽는 방식이므로, 시퀀셜 엑세스에 비해 디스크 I/O 오버헤드가 더 큽니다.
- 예를 들어, 인덱스를 사용하여 특정 키에 해당하는 레코드를 조회하려면, 인덱스를 따라가서 해당 블럭을 직접 읽는 랜덤 엑세스를 수행해야 합니다. 따라서 인덱스 탐색(Index Seek)이나 특정 블럭을 읽는 작업이 포함됩니다.
추가적인 고려사항
- 시퀀셜 엑세스는 블럭을 연속적으로 읽기 때문에 대량의 데이터를 효율적으로 처리할 때 유용합니다.
- 랜덤 엑세스는 특정 데이터나 소규모 레코드 집합을 효율적으로 찾아내는 데 적합합니다.
- 인덱스 사용 시, 특정 범위의 레코드를 시퀀셜하게 접근할 수 있습니다. 그러나 특정 레코드를 직접 찾을 때는 랜덤 엑세스를 하게 됩니다.
논리적 I/O vs 물리적 I/O vs 메모리 I/O?
논리적 I/O(메모리 I/O + 물리적 I/O)
- 논리적 I/O는 SQL을 처리하는 과정에서 발생한 전체 블럭 I/O를 나타냅니다. 이는 데이터베이스 시스템이 SQL을 실행하면서 버퍼 캐시를 포함한 메모리 영역과 디스크에서 읽거나 쓰는 모든 블럭 I/O를 합한 값입니다.
- SQL 쿼리를 실행할 때 데이터가 이미 버퍼 캐시에 존재하면, 해당 데이터를 메모리에서 읽게 됩니다. 이러한 메모리 I/O도 논리적 I/O에 포함됩니다.
물리적 I/O
- 물리적 I/O는 디스크에서 발생하는 I/O를 나타냅니다. 데이터베이스 시스템이 필요한 데이터를 디스크에서 읽거나 디스크에 쓰는 모든 작업이 물리적 I/O에 포함됩니다.
- 버퍼 캐시에 해당 블럭이 없는 경우, 데이터베이스 시스템은 디스크에서 데이터를 읽어와야 하므로 물리적 I/O가 발생합니다.
- 물리적 I/O는 디스크 암의 물리적 움직임을 포함하므로, 메모리 I/O에 비해 상대적으로 느립니다.
메모리 I/O
- 메모리 I/O는 데이터베이스의 버퍼 캐시와 같은 메모리 영역에서 발생하는 I/O입니다. 데이터베이스가 필요한 데이터를 버퍼 캐시에서 찾을 때 발생하며, 물리적 I/O에 비해 매우 빠릅니다.
버퍼 캐시와 I/O
- 버퍼 캐시는 디스크에서 읽어온 데이터 블럭을 메모리에 저장하는 역할을 합니다. 이를 통해 반복적인 디스크 I/O를 줄이고, 데이터 액세스 성능을 향상시킬 수 있습니다.
- SQL 쿼리를 실행할 때, 데이터베이스 시스템은 먼저 버퍼 캐시를 확인합니다. 블럭이 버퍼 캐시에 있으면 메모리 I/O로 처리되고, 그렇지 않으면 물리적 I/O를 통해 디스크에서 블럭을 읽어와 버퍼 캐시에 저장합니다.
- 모든 데이터 액세스는 버퍼 캐시를 거치기 때문에, 논리적 I/O와 물리적 I/O 모두 버퍼 캐시와 관련이 있습니다.
속도 비교
- 메모리 I/O는 전기적 신호를 이용하므로 디스크 I/O에 비해 매우 빠릅니다.
- 물리적 I/O는 디스크의 물리적 움직임을 포함하므로, 메모리 I/O에 비해 훨씬 느립니다
BCHR 버퍼 캐시히트율
버퍼 캐시 히트율(BCHR)
- BCHR은 데이터베이스 시스템이 I/O 작업을 수행할 때, 전체 I/O 중 물리적 I/O 없이 메모리 I/O로 처리한 비율을 의미합니다.
- BCHR이 높다는 것은 데이터베이스가 많은 데이터를 버퍼 캐시에서 찾고, 물리적 I/O가 적게 발생한다는 뜻입니다.
- BCHR = ((논리적 I/O - 물리적 I/O ) / 논리적 I/O) X 100
성능 개선을 위한 논리적 I/O 감소
-
- 물리적 I/O를 줄이려면 논리적 I/O를 최소화하는 것이 핵심입니다. 이는 데이터베이스 쿼리와 구조를 최적화하고, 반복적인 I/O를 줄여 효율적으로 데이터를 관리하는 것을 포함합니다.
- BCHR이 높다는 것은 물리적 I/O가 적다는 뜻이지만, 반복적인 블럭 접근이나 비효율적인 쿼리로 인해 메모리 I/O가 많아질 수 있습니다. 따라서 BCHR이 높다고 해서 반드시 성능이 좋다고 판단할 수는 없습니다.
- SQL 성능을 높이려면 I/O 자체를 최소화하고, 불필요한 쿼리 실행이나 반복적인 데이터 액세스를 줄이는 것이 중요합니다.
결론
BCHR은 데이터베이스 캐시 효율성을 평가하는 지표로 유용하지만, 이 지표 하나만으로 데이터베이스 성능을 판단하는 것은 위험합니다. 반복적인 블럭 읽기나 비효율적인 쿼리가 BCHR을 높일 수 있으므로, 성능을 향상시키려면 논리적 I/O를 줄이고 쿼리 최적화를 통해 I/O 자체를 최소화해야 합니다.
single block I/O vs multi block I/O
Single Block I/O
- Single Block I/O는 데이터베이스에서 한 번에 하나의 블럭을 읽는 것을 말합니다. 이 방식은 주로 인덱스 접근과 같은 상황에서 사용됩니다. 예를 들어, 인덱스를 통해 특정 레코드를 찾거나, 특정 키 범위의 데이터를 찾을 때 하나의 블럭씩 읽는 경우입니다.
- 인덱스 범위 스캔(Index Range Scan)이나 인덱스 탐색(Index Seek) 등의 작업이 주로 Single Block I/O를 활용합니다.
Single Block I/O
- Single Block I/O는 데이터베이스에서 한 번에 하나의 블럭을 읽는 것을 말합니다. 이 방식은 주로 인덱스 접근과 같은 상황에서 사용됩니다. 예를 들어, 인덱스를 통해 특정 레코드를 찾거나, 특정 키 범위의 데이터를 찾을 때 하나의 블럭씩 읽는 경우입니다.
- 인덱스 범위 스캔(Index Range Scan)이나 인덱스 탐색(Index Seek) 등의 작업이 주로 Single Block I/O를 활용합니다.
Multi Block I/O
- Multi Block I/O는 한 번에 여러 블럭을 읽는 것을 의미합니다. 이는 주로 테이블 전체를 스캔할 때 또는 많은 데이터를 연속적으로 읽어야 할 때 사용됩니다.
- Multi Block I/O는 Full Table Scan이나 Full Index Scan과 같은 작업에서 효율적입니다. 한 번에 여러 블럭을 읽음으로써 I/O 작업의 효율을 높이고, 디스크 헤드의 이동을 줄일 수 있습니다.
- 데이터베이스 환경에 따라 한 번에 읽을 수 있는 최대 블럭 수는 제한될 수 있습니다. 이 제한은 DBMS 설정, 데이터베이스 블럭 크기, 운영체제의 I/O 제한 등 다양한 요소에 영향을 받습니다.
블럭 크기와 OS I/O
- DBMS에서 사용하는 블럭 크기와 운영체제(OS)의 I/O 단위는 서로 다른 개념입니다. DBMS의 블럭 크기는 데이터베이스가 한 번에 읽거나 쓸 수 있는 최소 단위를 말하며, 일반적으로 4KB, 8KB, 16KB 등의 크기로 설정됩니다.
- 운영체제의 I/O 단위는 파일 시스템이나 디스크 드라이버의 최소 I/O 크기를 의미하며, 일반적으로 4KB에서 1MB까지 다양합니다.
- DBMS는 기본적으로 블럭 단위로 읽고 쓰지만, 실제 물리적 I/O는 OS I/O 단위에 따라 수행됩니다. 따라서 DBMS에서 한 번에 여러 블럭을 읽더라도, 실제로는 OS I/O 단위에 따라 데이터가 전송됩니다.
정리
- Single Block I/O는 한 번에 하나의 블럭을 읽는 방식으로, 인덱스 스캔이나 특정 데이터를 찾을 때 주로 사용됩니다.
- Multi Block I/O는 한 번에 여러 블럭을 읽는 방식으로, Full Table Scan이나 대량의 데이터를 읽을 때 효율적입니다.
- 운영체제의 I/O 단위와 DBMS의 블럭 크기는 서로 다르며, DBMS는 블럭 단위로 작업하지만 실제 물리적 I/O는 OS I/O 단위에 따라 수행됩니다.
Full Scan vs Index Range Scan
Index Range Scan
- Index Range Scan은 인덱스를 사용하여 특정 범위의 데이터 또는 키 값에 해당하는 레코드를 찾는 방법입니다. 이때 인덱스 내의 레코드를 하나씩 접근할 때마다 해당하는 데이터 블럭을 읽기 때문에, 인덱스 스캔을 통해 다수의 블럭 I/O가 발생할 수 있습니다.
- 인덱스 레코드를 하나씩 접근하기 때문에, 데이터베이스가 각 인덱스 레코드에 대응하는 테이블 블럭을 찾아 읽게 됩니다. 따라서 100개의 레코드를 읽으려면 100개의 인덱스 스캔과 100개의 테이블 블럭 읽기가 발생할 수 있습니다.
Full Scan
- Full Scan은 인덱스를 사용하지 않고, 테이블 전체를 순차적으로 스캔하는 방법입니다. 테이블 전체를 읽기 때문에, 물리적 I/O가 발생하지만, 한 번에 여러 블럭을 읽을 수 있어 연속적인 데이터 접근에 효율적입니다.
- 테이블 전체를 스캔하기 때문에 특정 키 값에 따라 데이터를 찾는 것보다는, 데이터베이스가 전체 데이터 범위를 다루는 작업에 유리합니다.
인덱스 스캔과 풀 스캔의 선택 기준
- 인덱스 스캔은 소량의 데이터 또는 특정 범위의 데이터를 빠르게 찾는 데 효과적입니다. 그러나 찾고자 하는 데이터의 양이 많을 경우, 여러 개의 블럭 I/O가 발생할 수 있습니다.
- 읽어야 할 데이터의 양이 많을 경우, 인덱스 스캔보다는 Full Scan이 더 효율적일 수 있습니다. Full Scan은 한 번에 여러 블럭을 읽을 수 있어 I/O를 줄이고, 디스크 헤드의 움직임을 최소화할 수 있습니다.
정리
- Index Range Scan은 인덱스를 사용하여 특정 키 값이나 데이터 범위를 찾는 방식으로, 소량의 데이터를 빠르게 찾는 데 유리합니다. 그러나 다수의 블럭 I/O가 발생할 수 있습니다.
- Full Scan은 테이블 전체를 순차적으로 스캔하는 방식으로, 대량의 데이터를 읽을 때 효율적입니다. 한 번에 여러 블럭을 읽을 수 있어 I/O 오버헤드를 줄일 수 있습니다.
- 따라서 데이터베이스의 성능 문제를 해결할 때, 무조건 인덱스를 사용하는 것보다, 데이터의 양과 쿼리의 특성을 고려하여 적절한 스캔 방식을 선택하는 것이 중요합니다.
캐시 탐색 메커니즘
캐시 탐색 메커니즘
- 데이터베이스에서 캐시가 중요한 이유는 디스크 I/O가 상대적으로 느리기 때문입니다. DBMS는 메모리 캐시를 활용하여 데이터 액세스 속도를 높이고, 물리적 I/O를 줄입니다.
- 버퍼 캐시는 데이터베이스의 디스크 블럭을 메모리에 저장하는 공간입니다. 이는 DBMS의 SGA(System Global Area) 내에 있으며, 모든 프로세스가 공유하는 자원입니다.
해시 체인을 이용한 블럭 검색
- 버퍼 캐시에서 블럭을 찾을 때, 해시 체인(Hash Chain)을 사용합니다. 데이터베이스는 각 블럭에 해시 함수를 적용하여 해시 체인에서 해당 블럭의 위치를 찾습니다.
- 해시 체인 내에서 해당 블럭의 존재를 확인하고, 블럭을 찾으면 이를 버퍼 캐시에서 읽습니다. 만약 찾을 수 없다면 디스크에서 블럭을 읽어와 버퍼 캐시에 저장한 후 데이터를 읽습니다.
직렬화 메커니즘
- SGA는 여러 프로세스가 공유하는 자원이므로, 데이터의 안정성과 경합 방지를 위해 직렬화 메커니즘이 필요합니다. 이는 여러 프로세스가 동시에 같은 자원에 접근하는 것을 방지하고, 데이터 무결성을 유지합니다.
- 버퍼 캐시에서는 래치(Latch)를 사용하여 직렬화를 구현합니다. 래치는 특정 자원(예: 해시 체인)에 대한 잠금 장치로, 프로세스가 래치를 얻으면 다른 프로세스는 해당 자원에 접근할 수 없습니다. 이를 통해 데이터 경합을 방지합니다.
캐시 경합과 성능
- 직렬화 메커니즘은 데이터의 무결성을 유지하는 데 필수적이지만, 래치 경합으로 인해 성능이 저하될 수 있습니다. 여러 프로세스가 같은 래치를 기다리게 되면 대기 시간이 증가하고, 전체 성능이 떨어질 수 있습니다.
- 캐시 경합을 줄이기 위해서는 SQL 튜닝과 같은 방법으로 논리적 I/O를 줄이는 것이 중요합니다. 이는 효율적인 쿼리 작성을 통해 버퍼 캐시 접근을 최소화하고, 물리적 I/O를 줄이는 것을 포함합니다.
보완 사항
- SGA는 여러 프로세스가 공유하는 영역이므로, 동시성 제어와 직렬화 메커니즘이 중요합니다. 래치 경합을 줄이기 위해 DBMS는 다양한 최적화 기법을 사용하며, SQL 튜닝을 통해 캐시 활용도를 높이고, 불필요한 I/O를 줄입니다.
- 데이터베이스의 성능 개선은 버퍼 캐시 활용뿐 아니라, 쿼리 최적화, 인덱스 사용, 물리적 설계 개선 등을 포함한 다양한 방법으로 접근해야 합니다.
캐시 버퍼 체인
- 캐시 버퍼 체인(Cache Buffer Chain)은 데이터베이스에서 버퍼 캐시 내 블럭을 찾기 위해 사용하는 해시 체인 구조를 의미합니다. 각 체인은 데이터 블럭의 해시 값에 따라 그룹화된 일련의 버퍼 블럭을 포함합니다.
- 데이터베이스는 캐시 버퍼 체인에 대한 래치(Latch)를 사용하여 동시성 제어를 수행합니다. 래치를 통해 여러 프로세스가 동시에 같은 체인을 수정하거나 접근하는 것을 방지합니다.
래치 해제와 버퍼 락
- 블럭을 찾은 후, 캐시 버퍼 체인의 래치를 빠르게 해제하는 것이 중요합니다. 이렇게 하면 다른 프로세스가 해당 해시 체인에 접근할 수 있습니다. 래치를 장기간 유지하면 다른 프로세스가 대기하게 되어, 성능 저하나 경합 문제가 발생할 수 있습니다.
- 그러나 래치를 해제하기 전에, 버퍼 자체에 대한 잠금(락)을 설정해야 합니다. 이를 버퍼 락(Buffer Lock) 또는 버퍼 핀(Buffer Pin)이라고 합니다. 이 잠금은 해당 버퍼 블럭에 대해 독점적 또는 공유적으로 접근하는 것을 제어합니다.
정리
- 래치를 통해 캐시 버퍼 체인을 제어하고, 블럭을 찾은 후에는 즉시 래치를 해제해야 다른 프로세스가 접근할 수 있습니다.
- 래치를 해제하기 전에, 해당 버퍼 블럭에 대한 락을 설정하여 동시성 제어를 보장합니다. 버퍼 락이 설정되면, 해당 버퍼 블럭을 수정할 수 있는 프로세스는 제한되며, 다른 프로세스는 읽기 전용으로 사용할 수 있습니다.
- 이러한 제어 메커니즘은 데이터베이스의 무결성과 동시성을 보장하는 데 필수적입니다.
버퍼 락의 해제
버퍼 락은 데이터베이스의 특정 작업이 완료된 후에 해제됩니다. 일반적으로 다음과 같은 상황에서 버퍼 락이 해제됩니다:
- 읽기 작업이 완료된 후: 버퍼 락이 공유 모드로 설정된 경우, 읽기 작업이 완료된 후 해제됩니다. 이는 다른 프로세스가 해당 블럭을 읽을 수 있도록 허용합니다.
- 쓰기 작업이 완료된 후: 버퍼 락이 독점 모드로 설정된 경우, 쓰기 작업이 완료된 후 해제됩니다. 이는 다른 프로세스가 해당 블럭을 수정할 수 있도록 허용합니다.
- 트랜잭션 종료 후: 트랜잭션이 커밋 또는 롤백된 후, 관련된 모든 버퍼 락이 해제됩니다. 이는 트랜잭션이 완료되어 데이터의 무결성을 보장한 후, 다른 프로세스가 버퍼에 접근할 수 있도록 합니다.
버퍼 락의 목적
버퍼 락은 데이터베이스에서 동시에 여러 프로세스가 버퍼 캐시를 사용하면서 발생할 수 있는 데이터 충돌과 무결성 문제를 방지하기 위한 장치입니다. 이를 통해 데이터베이스의 동시성과 무결성을 유지하고, 여러 프로세스가 버퍼 캐시에 효율적으로 접근할 수 있도록 합니다.
정리
버퍼 락은 데이터베이스 작업의 중요한 부분을 제어하기 위해 사용되며, 해당 작업이 완료된 후 해제됩니다. 일반적으로 읽기 작업, 쓰기 작업, 트랜잭션 종료 후에 버퍼 락이 해제되며, 이는 다른 프로세스가 해당 버퍼에 접근할 수 있도록 허용합니다.
'SQL 튜닝' 카테고리의 다른 글
SQL 공유 및 재사용 (0) | 2024.04.13 |
---|---|
SQL파싱과 최적화 (2) | 2024.04.12 |
댓글