l9791185890302

원문 : 『그림으로 공부하는 오라클 구조 개정판』 , 스기타 아츠시 외 4명 지음, 제이펍

오라클 접속 동작

오라클은 TCP/IP의 소켓(socket)을 네트워크 통신 수단으로 사용하고 있다. 소켓을 사용하면 전화처럼 다른 장비에 있는 프로그램과 통신할 수 있다. 장비 안에는 프로그램(프로세스)이 작동하고 있고, 그 프로그램이 수화기에 해당하는 소켓을 가지고 있는 모습을 머릿속에 그리면 된다.

socket

소켓

프로그램이 네트워크에서 데이터를 주고받을 수 있도록 네트워크 환경에 연결할 수 있게 만들어진 연결부. 소켓에서 계층별 프로토콜 구현을 위해 들어갈 함수들의 body를 제공 따라서 별도의 구현없이 소켓을 사용할 수 있음

  • 소프트웨어와 소프트웨어를 연결: IP와 서비스 포트를 통해 찾음
  • 소프트웨어간 데이터 통신: 인터넷에서 소켓을 찾아 연결하고 데이터를 송수신

오라클에서 소켓 동작

오라클에서도 소켓을 사용하고 있는 이상 위와 같이 동작을 한다. 오라클에서는 수신을 기다리는 프로세스를 리스너(listener)라고 한다.

커넥션 처리 - 리스너 기동

listener.ora 파일은 오라클 리스너가 가지고 있는 접속 IP와 포트번호이며 하나의 리스너는 여러개의 데이터베이스로 안내할 수 있다. 일반적인 상황에서는 하나의 리스너가 데이터베이스 한개를 담당한다.

오라클의 기본포트는 1521이고 필요에 따라 다른 포트를사용할 수 있다. 리스너 설정이 끝나면 lsnrctl이라는 도구를 사용해서 리스너를 기동한다. 리스너가 자신이 안내해야 하는 데이터베이스를 인식하는 방법으로는 listener.ora파일에 있는 설정을 읽거나 DB가 자동으로 등록하는 방법이 있다.

  • DB서버 : 자신이 listen해야할 포트 번호와 IP 등을 listnerer.ora에서 확인하고 listen을 시작함
  • 애플리케이션 서버: tnsnames.ora 파일을 확인해서 리스너의 주소나 포트 번호, 서비스 이름 등을 확인함. 확인한 내용을 사용해서 연결(커넥션)을 확립시킴
  • DB서버: 소켓이 확립되면 서버 프로세스를 생성함. 소켓은 서버 프로세스에게 전달해줌. 일부 OS에서는 소켓을 공유하는 경우도 있음

커넥션 처리 - 애플리케이션의 커넥션

데이터베이스에 연결할 때 필요한 정보를 오라클 클라이언트에 전달할 필요가 있고, 그 정보를 ‘커넥션 디스크립터(connection descriptor)’라고 한다. 커넥션 디스크럽터 안에는 주소는 XXX이며 포트가 XXX이고 서비스이름이 XXX이다 와 같은 정보가 포함되어 있다. 연결할 때마다 정보를 입력할 수는 없으므로 일반적으로 tnsnames.ora에 커넥션 디스크립터를 작성해 놓고 커넥션 식별자를 커넥션 디스크립터마다 붙인다.

ORA18C =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP) (HOST = XXXX) (PORT = 1521)) # 소켓을 생성하는데 필요한 정보
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = orcl) # 리스너에게 전달하기 위한 정보
    )
  )
// 애플리케이션에서 오라클에 연결하기 위한 명령
void main() {
  OracleDataSource ods = new OracleDataSource();
  ods.setUrl("jdbc:oracle:oci:@ORA18C"); // 커넥션 식별자가 있음
  ods.setUser("scott");
  ods.setPassword("tiger");
  Connection conn = ods.getConnection();
}

커넥션 처리 - 서버 프로세스 생성

마지막 과정으로 서버프로세스를 생성하고 소켓을 인계받는 것이다. 소켓을 생성하면 리스너가 그대로 SQL 처리를 해도 될 것처럼 보이지만, 한번 SQL 처리를 시작하면 요청받은 SQL 처리하느라 다른 처리를 할 수 없게 되므로 전담 영업 담당자인 서버 프로세스를 생성해서 SQL 처리를 즉시 인계한다.

한번 SQL 처리를 시작하면 요청받은 SQL을 처리하느라 다른 처리를 할 수 없으므로 서버 프로세스를 생성해서 SQL 처리를 즉시 인계한다.

먼저 OS상에서도 프로세스를 생성해야 하며 서버 프로세스가 사용할 수 있는 공유메모리를 확보해야한다. 또한 서버프로세스용 전용 메모리(PGA)도 확보해야한다. 그 외에 데이터 베이스 내부의 처리도 여러가지가 남아있다. 따라서 서버 프로세스를 한번 생성하는데는 가벼운 SQL문을 처리할 때 사용하는 CPU 시간보다 몇 배에서 몇 십배 많은 CPU를 사용한다.

리스너는 서버 프로세스 생성이 끝나면 소켓을 서버 프로세스에 인계한다. 리스너가 인계한 후부터 서버 프로세스와 오라클 클라이언트는 직접 송수신하므로 리스너는 자유로워 진다. 이것은 병렬 처리를 가능케하고 높은 처리량을 실현하는 방법에 해당한다.

/**
* 커넥션을 닫지 않고 계속사용한다면, SQL보다 부하가 몇십 배나 높은 커넥션 처리를 하지 않아도 된다. 이런식으로 사용하는 것은 시스템의 응답 시간을 나쁘게 만들고 있다고 말해도 과언이 아니다. 커넥션 풀이라고 불리는 기술을 사용하고 있다면 문제가 되지는 않는다.
*/
public void main() {
  Connection conn = ods.getConnection();
  ...executeQuery("select ...");
  conn.close(); // 서버 프로세스 종료
  
  Connection conn = ods.getConnection(); // 다시 서버 프로세스 생성
  ...executeQuery("select ...");
  conn.close();
}

접속 동작 확인

DB서버의 동작

# 리스너가 기동하지 않을 때
$ sqlplus scott/tiger@XXXX

SQL*Plus: Release XX.X.
...
ERROR:
ORA-12541: TNS:no listener # 지정한 포트로 listen하고 있는 리스너가 없었으므로 'no listener'라고 표시함. 이 메시지가 나타났을 때는 리스너가 기동하지 않았다든가 잘못된 주소를 지정한 경우가 많다.
# 리스너가 가진 데이터베이스의 정보가 일치하지 않을 때
$ sqlplus scott/tiger@XXXX

SQL*Plus: Release XX.X.
...
ERROR:
ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
# 리스너가 커넥션 디스크립터에서 요청받은 서비스를 찾을 수 없다고 응답하고 있음. 요청이 리스너까지는 도달했다는 것을 의미함.

데이터베이스에 접속하지 못하는 장애는 현장에서 빈번하게 일어난다. 장애가 발생했을때 무엇이 어떤 역할을 가지고 있고 어떤 식으로 동작하며 어디에 정보가 기록되어 있는지를 꼭 알아 두어야한다.

정지나 리스너의 상태 확인

일반적으로 애플리케이션에서 접속을 종료하는 처리를 수행하면 서버 프로세스도 함께 종료된다. 리스너는 lsnrctl의 stop 명령어를 사용해 정지할 수 있다. 또한 lsnrctl의 status 명령어로 현재의 리스너 기동 상태나 listen하고 있는 포트의 번호, 보유하고 있는 데이터베이스의 정보 등을 알 수 있으므로 데이터베이스에 접속할 수 없는 장애가 발생할때 활용할 수 있다.

접속을 강제로 중지하는 명령어

오라클은 TCP/IP를 사용하고있고 TCP/IP에서 에러가 반환되지 않으면 오라클은 문제가 발생한 것을 눈치채지 못할 수 있다.

성능 개선법

커넥션을 맺는것과 서버 프로세스를 생성하는 것은 오라클에게 무거운 작업이다. 이런 힘든 방법을 개선할 수 있는 방법이 있다. ‘현실의 실제 시스템에서 서버 프로세스는 긴 시간 동안 아무것도 하지 않는다’가 힌트다. 대부분 서버 프로세스는 가동 시간 중 일부만이 SQL을 처리한다. 또한 클라이언트와 서버 프로세스는 일대일로 대응하기 때문에 프로세스의 수를 줄일 수는 없다.

그래서 효율을 높이기 위한 방법 중 하나로 여러 서버 프로세스를 몇 개의 풀로 구성해두고 여러 애플리케이션이 쓰고 싶을 때만 풀에서 꺼내서 사용하는 방법이다. 이것이라면 대부분의 대기 상태이던 서버 프로세스의 가동률을 높일 수 있다. 이러한 구성을 ‘공유 서버 구성’이나 ‘커넥션 풀’이라는 구성을 사용할 수 있다.

요약

  • DB에 접속하기 위해서는 데이터베이스 서버의 주소와 리스너의 포트 번호가 필요하다.
  • tnsnames.ora라는 파일 안에 접속하기 위한 정보를 기록해둔다.
  • 리스너라고 하는 프로세스가 접속 요청을 받으며, 서버 프로세스의 생성도 같이 수행한다.
  • listener.ora라는 파일 안에 리스너의 설정을 기록해둔다.
  • 서버 프로세스의 생성은 무거운 작업이므로 줄이는 것이 좋다.

리스너가 정지되어도 DB와의 커넥션은 유지가 된다. 소켓의 역할은 서버 프로세스에 인계하고 이후로는 클라이언트와 서버 프로세스가 주고 받기때문에 리스너가 멈춰도 커넥션은 계속 유지가 된다.

DB Connection Pool에 대한 이야기 · 안녕 프로그래밍

출처

[기본] 소켓(SOCKET)통신 이란? (tistory.com)