연결 관리하기
연결 관리하기
대부분의 프로그램에서는 sql.DB 연결 풀 기본값을 조정할 필요가 없어요. 하지만 일부 고급 프로그램에서는 연결 풀 매개변수를 튜닝하거나 연결을 명시적으로 다뤄야 할 때가 있습니다. 이 글은 그 방법을 설명합니다. sql.DB 데이터베이스 핸들은 여러 고루틴이 동시에 써도 안전합니다(다른 언어에서 '스레드-세이프'라고 부르는 그런 속성과 같아요). 반면 일부 다른 데이터베이스 접근 라이브러리는 연결 하나가 한 번에 하나의 연산에만 쓰일 수 있게 설계되어 있죠. 그 간극을 메우기 위해 각 sql.DB는 기저 데이터베이스에 대한 활성 연결 풀을 관리하면서, Go 프로그램의 병렬 처리를 위해 필요에 따라 새 연결을 만들어 냅니다.
출처: Go 공식 문서
연결 풀은 대부분의 데이터 접근 요구에 적합합니다. sql.DB의 Query나 Exec 메서드를 호출하면 sql.DB 구현은 풀에서 사용 가능한 연결을 꺼내거나, 필요하면 새로 만듭니다. 패키지는 더 이상 필요 없어지면 그 연결을 풀에 돌려줘요. 이 덕분에 데이터베이스 접근에서 높은 수준의 병렬 처리가 가능해집니다.
연결 풀 속성 설정하기
sql 패키지가 연결 풀을 관리하는 방식을 안내하는 속성을 설정할 수 있어요. 이 속성들의 효과에 대한 통계를 보려면 DB.Stats를 사용합니다.
최대 열린 연결 수 설정하기
DB.SetMaxOpenConns는 열려 있는 연결 수에 상한을 둡니다. 이 상한을 넘어서면 새 데이터베이스 연산은 기존 연산이 끝날 때까지 기다렸다가, 그때 sql.DB가 다른 연결을 만듭니다. 기본적으로 sql.DB는 연결이 필요할 때 모든 기존 연결이 사용 중이면 새 연결을 만듭니다.
상한을 설정하면 데이터베이스 사용이 락이나 세마포어를 획득하는 것과 비슷해진다는 점을 기억하세요. 그 결과 애플리케이션이 새 데이터베이스 연결을 기다리다가 교착 상태(deadlock) 에 빠질 수도 있습니다.
최대 유휴 연결 수 설정하기
DB.SetMaxIdleConns는 sql.DB가 유지하는 최대 유휴 연결 수의 상한을 바꿉니다. 특정 데이터베이스 연결에서 SQL 연산이 끝나면 그 연결은 보통 즉시 닫히지 않아요. 애플리케이션이 곧 다시 필요할 수도 있으니까요. 열린 연결을 유지해 두면 다음 연산을 위해 데이터베이스에 다시 연결할 필요가 없어집니다. 기본적으로 sql.DB는 항상 유휴 연결 두 개를 유지합니다. 상한을 높이면 병렬 처리가 많은 프로그램에서 잦은 재연결을 피할 수 있어요.
연결이 유휴 상태로 있을 수 있는 최대 시간 설정하기
DB.SetConnMaxIdleTime은 연결이 닫히기 전에 유휴 상태로 있을 수 있는 최대 시간을 설정합니다. 그러면 sql.DB가 주어진 기간보다 오래 유휴 상태였던 연결을 닫게 되죠. 기본적으로 유휴 연결이 풀에 추가되면 다시 필요해질 때까지 그 자리에 남아 있습니다. DB.SetMaxIdleConns로 병렬 활동이 몰리는 동안 허용 유휴 연결 수를 늘렸다면, DB.SetConnMaxIdleTime도 함께 써서 시스템이 한가할 때 그 연결들을 나중에 해제하도록 조정할 수 있어요.
연결의 최대 수명 설정하기
DB.SetConnMaxLifetime은 연결이 닫히기 전에 열려 있을 수 있는 최대 시간을 설정합니다. 기본적으로 연결은 위에서 설명한 상한에 제약을 받을 뿐, 임의로 오랫동안 사용·재사용될 수 있어요. 로드 밸런싱되는 데이터베이스 서버를 쓰는 시스템 같은 경우에는 문자열 그대로 애플리케이션이 특정 연결을 너무 오래 재연결 없이 쓰지 않도록 하는 게 도움이 될 수 있습니다.
전용 연결 사용하기 (Using dedicated connections)
특정 연결에서 실행되는 일련의 연산에 데이터베이스가 암묵적 의미를 부여하는 경우가 있습니다. database/sql 패키지에는 그런 경우에 쓸 수 있는 함수들이 있어요.
가장 흔한 예는 트랜잭션입니다. 트랜잭션은 보통 BEGIN 명령으로 시작해 COMMIT이나 ROLLBACK 명령으로 끝나며, 그 사이에 그 연결에서 실행된 모든 명령을 전체 트랜잭션에 포함합니다. 이런 경우에는 sql 패키지의 트랜잭션 지원을 쓰면 됩니다. → "Executing transactions" 참고.
개별 연산의 연속이 모두 같은 연결에서 실행되어야 하는 다른 경우에는 sql 패키지가 전용 연결(dedicated connection) 을 제공합니다. DB.Conn은 전용 연결인 sql.Conn을 얻어 줍니다. sql.Conn에는 BeginTx, ExecContext, PingContext, PrepareContext, QueryContext, QueryRowContext 메서드가 있는데, DB의 같은 이름 메서드처럼 동작하되 전용 연결만 사용해요. 전용 연결을 다 쓴 뒤에는 Conn.Close로 반드시 해제해야 합니다.
더 알아보기 (Learn more)
- 트랜잭션 실행은 'Executing transactions' 문서를 참고하세요.
- 데이터베이스 핸들을 여는 기본적인 방법은 'Opening a database handle'을 보세요.
database/sql패키지 전체 API는 표준 라이브러리 문서를 확인하세요.