우아한테크코스 4기

[h2]DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;

giron 2022. 7. 10. 23:38
728x90

제이슨의 JPA수업 도중 application.properties의 설정에서 아래와 같은 h2 설정이 있었다.

spring.datasource.url=jdbc:h2:~/test;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE

h2설정할 때, 어쩔때는 h2:mem, h2:tcp였고 이번에는 그냥 h2:~였다. 또한 DB_CLOSE~라는 새로운 이름도 보여서 h2에 대해서 조금 공부해보려고 한다.

Connection Modes

  • Embedded mode (local connections using JDBC)
  • Server mode (remote connections using JDBC or ODBC over TCP/IP)
  • Mixed mode (local and remote connections at the same time)

이 3가지중 자주 사용하는 Embedded와 Server모드에 대해서만 알아보겠다.

Embedded mode

메인메모리 속의 JVM(애플리케이션)속에 h2가 있다.

임베디드 모드에서는 애플리케이션이 JDBC를 사용하여 동일한 JVM 내에서 데이터베이스를 엽니다.

장점으로는 가장 빠르고 쉬운 연결 모드이다.

단점은 데이터베이스가 한 번에 하나의 virtual machine(및 클래스 로더)에서만 열릴 수 있다는 것이다. 

I/O 작업은 SQL 명령을 실행하는 응용 프로그램의 스레드에 의해 수행될 수 있다. 애플리케이션이 이러한 스레드를 중단하지 않을 수 있으며, 스레드 중단 중에 JVM이 I/O 핸들을 닫기 때문에 데이터베이스가 손상될 수 있다. 

Server Mode

애플리케이션과 다른 디비 프로세스를 열어서 연결한다.

서버 모드를 사용할 때 응용 프로그램은 JDBC 또는 ODBC API를 사용하여 원격으로 데이터베이스를 연다.

많은 응용프로그램이 이 서버에 연결하여 동일한 데이터베이스에 동시에 연결할 수 있습니다. 내부적으로 서버 프로세스는 데이터베이스를 임베디드 모드로 엽니다.

모든 데이터가 TCP/IP를 통해 전송되기 때문에 서버 모드는 내장 모드보다 느리다.

Connecting to an Embedded (Local) Database

jdbc:h2:[file:][<path>]<databaseName>
jdbc:h2:~/test
jdbc:h2:file:/data/sample
jdbc:h2:file:C:/data/sample (Windows only)

와 같은 url 포멧일 때, 사용된다.

 

[file:]은 option으로 안 적거나 상대경로를 적어야 한다. path databaseName은 os마다 다르지만 소문자로 적는 것을 공식문서에서 추천한다. databaseName은 3글자 이상이어야 하고 이름에는 세미콜론을 사용할 수 없다.

사용자 홈 디렉토리를 가리키려면 다음과 같이 ~/를 사용한다. jdbc:h2:~/test.

In-Memory Databases

신속한 프로토타이핑, 테스트, 고성능 운영, 읽기 전용 데이터베이스와 같이 이터를 유지하거나 데이터를 변경하지 않아도 될때 사용하는게 좋다. 인메모리 디비는 데이터가 지속되지 않는다.

이터베이스 URL은 jdbc:h2:mem: 을 통해서 새로운 커넥션으로 새로운 (private)디비를 생성할 수 있다. 

하나의 디비에 다중 연결이 필요할 때는 jdbc:h2:mem:db1와 같이 이름을 붙여서 사용할 수 있다.

또 다른 컴퓨터에서 tcp를 통해 접근하려면 jdbc:h2:tcp://localhost/mem:db1와 같이 사용할 수 있다.

 

기본적으로 데이터베이스에 대한 마지막 연결을 닫으면 데이터베이스가 닫힌다. 인메모리 디비에서는 내용이 사라진다.

데이터베이스를 열린 상태로 유지하려면 데이터베이스 URL에;DB_CLOSE_DELAY=-1을 추가하면 된다.

 

즉, jvm이 살아있는 동안 메모리 내 데이터베이스의 내용을 유지하려면 jdbc:h2:mem:test;DB_CLOSE_DELay=-1을 하자.대신 이때 SHUTDOWN 명령을 사용하여 DB를 닫을때는 메모리 누수가 발생할 수 있다고 한다.(그런데 DB에 대한 마지막 커넥션이 닫히면 DB가 자동으로 닫히므로 SHUTDOWN명령어를 쓸 일은 없다고 보면 된다.)

;DB_CLOSE_ON_EXIT=FALSE(VM 종료 시 데이터베이스 닫기 안 함)

디비가 마지막 커넥션이 끊겼는데도 정상적으로 닫히지 않는다면 vm이 정상적으로 종료될 때, shutdown hook를 사용하여 디비를 닫는다고 한다.

 

이 경우 vm 종료 시 데이터베이스가 계속 사용되므로(예: 종료 프로세스를 데이터베이스에 저장하기 위해) 이 경우 데이터베이스를 닫지 않아야 한다.

이때 DB_CLOSE_ON_EXIT설정으로 데이터베이스 자동 닫기를 사용 불가능으로 설정할 수 있다. 즉, 예상치 못한 디비의 셧다운을 막아주도록 한다.

server mode

서버 모드도 내부적으로 서버 프로세스는 데이터베이스를 임베디드 모드로 열지만, 데이터의 처리 흐름이 TCP/IP를 통하여 전송되기 때문에 임베디드 모드보다는 느리다.

 

결론

h2는 용량이 작아서 상용보다는 주로 테스트에서 사용했다. 빠르게 테스트를 하고 결과를 구하기 위해서 서버 모드보다는 임베디드 모드가 더 좋은 것 같다. 

또한 jdbc:h2:~/test 로 임베디드 모드로 url을 적는 경우는 test.mv.db 라는 file이 남아서 나중에 다른 애플리케이션에서 h2로 테스트를 할 때, 파일 이름이 겹쳐서 안되는 경우가 발생할 수 있으므로 매번 다른 이름으로 설정해야 한다는 번거러움이 있을 것 같다.

 

또한 주로 테스트 용도로 h2를 사용하므로 공식문서에서도 말하듯 테스트를 할땐 인메모리 모드로 사용하는것을 추천한다.

그리고 아직까지 mv.db파일을 활용할 일이 없어서 jdbc:h2:mem:test와 같은 url 이름으로 인메모리 디비를 사용하여 파일을 남지 않게 하는 것도 방법일것같다.

 

또한 ;DB_CLOSE_DELAY=-1인메모리 디비에서만 사용된다. 커넥션이 다 끊겨도 디비가 닫히지 않는다면 디비는 자동으로 종료된다. 인메모리 디비에서 디비가 자동으로 종료되지 않도록 해준다.

 

;DB_CLOSE_ON_EXIT=FALSE임베디드 디비에서 사용하며 디비가 자동으로 종료되는 것을 막아준다. 이렇게 디비의 자동 종료를 비활성화하면 데이터베이스가 닫히는 시간을 스프링 부트가 제어할 수 있으므로 데이터베이스에 대한 액세스가 더 이상 필요하지 않을 때 발생하도록 보장한다.

@AutoConfigureTestDatabase

@AutoConfigureTestDatabase에서도 이렇게 설정된 이유가 위와 같은 이유때문일것 같다.

Reference

http://www.h2database.com/html/features.html#in_memory_databases

https://docs.spring.io/spring-boot/docs/1.4.3.RELEASE/reference/html/boot-features-sql.html

 

 

 

 

728x90