Python 에서 DB Pool 사용하기
데이터베이스와 애플리케이션을 효율적으로 연결하는 커넥션 플 라이브러리는 애플리케이션에서 필수 요소 입니다. 일반적인 프로그램에서 데이터베이스에 연결(Connection 객체를 얻는 작업)은 많은 시간이 소요 됩니다. 따라서 Connection을 미리 생성시켜 저장소에 저장 했다가 프로그램에서 요청이 있으면 저장소에서 꺼내 제공하면 시간과 리소스를 절약 할 수 있습니다. 이러한 기법을 Connection Pool이라 합니다.
Python 에서 사용할수 있는 MariaDB Connection Pool은 몇가지가 있다.
- Oracle Mysql Pool(mysql 5.5 이상 설치시 사용 가능)
- SQLAlchemy
- python-mysql-pool
이중 Oracle 에서 제공되는 Pool을 테스트 진행시 Pool 개수 이상을 요구 시, 대기 없이 다음과 같은 오류가 발생한다.
mysql.connector.errors.PoolError: Failed getting connection; pool exhausted
때문에 SQLAlchemy는 Python에 대한 SQL 툴킷과 객체 관계 매퍼를 사용하여 구현 하였다.
우선 JAVA 7의 try-with-resources과 같은 기능이 Python의 with 로 있다.
따라서 with 를 이용해서 처리 할수 있는 DB에 대한 connection을 얻고 닫는 것을 다음처럼 자동화 할 수 있다.
# _Session
with _Session(config['MARIADB']['MARIADB_CONNECT_INFO']) as s:
onion_count = s.query(OnionsInfo).count()
return onion_count
#Connection
with Connector(config['MARIADB']['MARIADB_CONNECT_INFO']) as con:
onion_count = con.execute("select count(*) from onions_info").fetchall()[0]
return onion_count
session 의 경우 SQLAlchemy와 곂치기 때문에 _를 이용함
with 절을 이용해 with 절이 시작 할때 enter 가 호출 되고, 종료 될때 exit 가 호출 되어 connection을 시작 하고 종료 한다.
class _Session(Singleton):
session = None
def __init__(self, connect_info=None):
global engine
if engine is None:
engine = sqlalchemy.create_engine(
connect_info, pool_size=5,
max_overflow=5, pool_recycle=500)
Session.configure(bind=engine)
def __enter__(self):
self.session = Session()
print "enter = " + str(self.session)
return self.session
def __exit__(self, exc_type, exc_val, exc_tb):
if exc_type is not None:
self.session.rollback()
print "rollback()" + str(self.session)
else:
self.session.commit()
print "close() : " + str(self.session)
self.session.close_all()
class Connector(Singleton):
con = None
def __init__(self, connect_info=None):
global engine
if engine is None:
engine = sqlalchemy.create_engine(
connect_info, pool_size=5,
max_overflow=5, pool_recycle=500)
def __enter__(self):
self.conn = engine.connect()
return self.conn
def __exit__(self, exc_type, exc_val, exc_tb):
self.conn.close();