뮤텍스란?
뮤텍스를 설명하기 전 직렬화의 개념부터 알고 가자.
i-1, i, i+1, i+2 와 같이 노드가 4개 연결돼 있을 때 node i와 i+1을 삭제하려면 node i를 먼저 지우고 각 노드를 다시 연결한 후 node i+1을 지우고 다시 연결한다. 스텝 바이 스텝으로 진행된다. 아무리 바빠도 node i와 i+1을 동시에 삭제할 수 는 없다.
뮤텍스(Mutex)는 mutual exclustion의 줄임말이고 미세 단위 (fine-grained) 직렬화 구조(Structure)이다.
기본적으로 latch가 작동하는 것과 동일한 방법으로 작동한다. 하지만 가볍고 종종 직접적으로 hardware-supported해서 빠르다. 이런 사실 덕부네 폭넓은 사용에 적합하다.
10gR2부터 오라클은 많은 래치를 뮤텍스로 대치했다. 빠르고 작은 풋프린트를 남겨서 뮤덱스는 성능을 두배로 개선한다. 속도와(구조가 작은 단위로 구성 돼 있어 공유할 구조가 덜 필요하기 때문에) 불필요한 경합(false contentions)을 줄인다. 래치는 종종 많은 구조의 셀들 사이에 공유된다. 뮤텍스는 일반적으로 하나의 논리적인 피스에 배타적으로 할당된다.
각 부모와 자식 커서는 각각의 뮤텍스를 갖는다. 많은 커서가 공동으로 사용하는 래치에 대해서 경쟁할 필요가 없다.
세션이 맺어지고 sql문을 실행하기 위해서는 세션 id가 SGA내의 메모리 구조(Memory Structure)을 할당 받아야 한다. 메모리 구조를 할당 받기 위해서는 컨트롤 구조를 할당 받아야한다. 컨트롤 구조를 할당할 때 대기가 오래발생하면 성능이 현저하게 저하된다.
컨트롤 구조를 할당 받기 위해서 래치/뮤텍스 가 사용된다. 일반적으로 잠금을 사용한다는 것은 enqueues에서 대기하는 것이다. 순차적으로 처리된다는 의미다. 하지만 래치/뮤텍스를 사용하는 것은 확률 게임이다. 일정 시간 간격으로 spinning(사용 시도)dhk sleeping(대기)를 반복하면서 메모리의 사용을 시도한다. spinning은 메모리 사용할 수 있도록 gimme,gimme,gimme 조르는 것이고, sleeping은 조르기를 잠시 멈추고 쉬는 것이다. spinning시에 메모리를 사용할 수 있는지는 운(확률)달려 있다.
뮤텍스 경합
그럼에도 불고하고 뮤텍스 경합은 여전히 발생할 수 있다. 그리고 아주 드문 경우도 아니다. 항상 그렇듯이, 병렬 실행이 직렬화되면서 경합이 발생한다. 두 개의 프로세스가 동일한 자원을 요청하고 있을 때 한개는 해당 자원을 잡고있고, 다른 한개는 원하고 (기다리고)있다.
위의 그림에서 session1은 LC object (cursor)를 사용한다. 때문에 그에 해당하는 뮤텍스를 잡고있다. 이것이 해당 작업을 책임지는 직렬화 구조이다. Session2가 동일한 LC obejct를 호환되지 않는 방식으로 사용하기를 원한다. 따라서 LCO/Cursor를 방어하는 뮤텍스에 대해서 경합이 발생한다. 반복적으로 뮤텍스의 상태를 질문하는 것을 Spinning이라 한다. 아주 작은 조각의 메모리에 반복적으로 질문을 던진다. 예측할 수 있듯이 이런 작업은 매우 강하게 cpu를 사용한다. 하지만 os 스케줄러와 다른 멀티테스킹 메카닉이 때떄로 cpu를 사용할 수 있는 시간을 정의한다. (오라클에서는 _spin_count 파라미터를 사용한다.) 최대 스핀 시간이 지나면 프로세스는 해당 뮤텍스에 대해서 sleeps 상태로 빠진다. 한 동안 기다리다가, 다시 돌아와서 Session1이 해당 뮤텍스를 놔줄때까지 스핀한다.
대기(Waits)
특히 10gR2와 11g부터 오라클 대기 인터페이스(wait interface)는 성능 분석을 위한 강력한 정보의 소스로 사용된다.
오라클 구현 코드에서 정보를 보여주고 오라클 커널 토드 자체가 그러한 waits를 보고하고 해당 순간에 무슨일이 진행되고 있는지 상당히 정확한 정보를 얻을 수 있다. 경합은 엑티브 스피닝을 야기한다. 즉 실제로 하는 일 없이 cpu 부하를 주는 것이다. 스피닝 상태가 sleep 상태가 되면 오라클은 wait event로 이것을 기록한다. 여기서는 커서 관련 뮤텍스 event에 집중한다.
cursor: mutex X
"X" wait event는 커서 관련 뮤텍스에 상호 배타적인 잠김(lock)이 발생하는 것을 알려준다. 프로세스들이 아래와 같은 일들을 수행하거나 원할 때 프로세스들은 해당 뮤텍스를 잡거나 해당 뮤텍스에 대해서 경합한다.
- 신규 자식 커서를 부모 커서 아래 입력한다.
- SQL 바인드 데이터를 Peeking 한다.
- 커서 관련된 통계 정보를 수정한다.
cursor: mutex S
"S" wait evnet는 커서 관련 뮤텍스에 공유 잠금을 발생하는것을 알려준다. 프로세스가 뮤텍 자체의 참조 횟수를 변경하거나 변경을 원할 때 프로세스들은해당 뮤텍스를 잡거나 해당 뮤텍스에 대해서 경합한다. 기본의미는 "새로운 녀셕이 관심있으니 스피닝/웨이팅" 이다.
cursor: pin X
"pin X" wait는 구조가 조작되는 동안 해당 구조를 삭제하지 못하도록 방어하는 상호 배타적인 뮤텍스 상태에서 sleep하는 것을 알려준다. 프로세스가 아래 작업을 하거나 원할 때 pin을 잡거나 pin x에 대해서 경합한다.
- 커서 생성 or 커서 변경시 발생
cursor: pin S
"pin S" wiat는 구조가 사용되는 동안 구조를 삭제하지 못하도록 방어하는 공유 뮤텍스 상에서 sleep하는 것을 알려준다. 프로세스가 컷를 사용하거나 원할 때 pin S를 잡거나 pin S에 대해서 경합한다. 누구도 SQL문이 수행되는 동안 해당 커서 정의가 삭제되는 것을 원하지 않는다.
cursor: pin S wait on X
"pin S wait on X" wait는 다른 누군가가 상호 배타적인 모드로 커서의 핀 뮤텍스를 잡고 있는 동안 해당 핀 뮤텍스 상에 공유 잠감을 걸기와한 경합을 알려준다. 이것은 일반적으로 하나의 세션이 커서를 실행하려고 하고 다른 세션이 커서를 변경하고 있을때 발생한다.
예를 들면 재 사용하려는 커서가 사용하는 객체에 동시에 DDL을 수행하는 경우 발생한다.
'Oracle > Admin' 카테고리의 다른 글
[Oracle] Row Size 구하기 (2) | 2024.07.24 |
---|---|
[Oracle] ora.diskmon offline (0) | 2024.07.15 |
[Oracle] 커서 생성과 무효화 (0) | 2024.06.14 |
[Oracle] v$sqlarea vs v$sql cusor sharing 테스트 (0) | 2024.06.14 |
[Oracle] 병렬 프로세스 간 데이터 분배 비교 방식과 PQ_DISTRIBUTE 힌트 사용 (1) | 2024.06.13 |