fix: SQLite 멀티스레드 I/O 에러 해결

- 요청마다 새 SQLite 연결 생성 (new_connection=True)
- 사용 후 명시적 close
- 간헐적 'I/O operation on closed file' 에러 방지
This commit is contained in:
thug0bin 2026-02-27 15:43:52 +09:00
parent 870e40a6db
commit 76da7d9cd1
2 changed files with 42 additions and 27 deletions

View File

@ -3029,9 +3029,10 @@ def api_member_history(phone):
transaction_ids = [] # 적립된 거래번호 수집
# 1. 마일리지 내역 조회 (SQLite)
# 1. 마일리지 내역 조회 (SQLite) - 새 연결 사용 (멀티스레드 안전)
sqlite_conn = None
try:
sqlite_conn = db_manager.get_sqlite_connection()
sqlite_conn = db_manager.get_sqlite_connection(new_connection=True)
cursor = sqlite_conn.cursor()
# 사용자 정보 조회
@ -3108,6 +3109,13 @@ def api_member_history(phone):
except Exception as e:
logging.warning(f"마일리지 조회 실패: {e}")
finally:
# SQLite 연결 닫기
if sqlite_conn:
try:
sqlite_conn.close()
except:
pass
# 2. 전화번호로 POS 고객코드 조회 (MSSQL)
cuscode = None

View File

@ -185,18 +185,23 @@ class DatabaseManager:
# 새 세션 생성
return self.get_session(database)
def get_sqlite_connection(self):
def get_sqlite_connection(self, new_connection=False):
"""
SQLite mileage.db 연결 반환 (싱글톤 패턴)
최초 호출 스키마 자동 초기화
SQLite mileage.db 연결 반환
Args:
new_connection: True면 항상 연결 생성 (멀티스레드 안전)
Returns:
sqlite3.Connection: SQLite 연결 객체
"""
# 연결 유효성 체크 강화
# 새 연결 요청 시 항상 새로 생성
if new_connection:
return self._create_sqlite_connection()
# 기존 싱글톤 방식 (하위 호환)
if self.sqlite_conn is not None:
try:
# 연결 상태 확인
cursor = self.sqlite_conn.cursor()
cursor.execute("SELECT 1")
cursor.fetchone()
@ -210,28 +215,30 @@ class DatabaseManager:
self.sqlite_conn = None
if self.sqlite_conn is None:
# 파일 존재 여부 확인
is_new_db = not self.sqlite_db_path.exists()
# 연결 생성
self.sqlite_conn = sqlite3.connect(
str(self.sqlite_db_path),
check_same_thread=False, # 멀티스레드 허용
timeout=10.0 # 10초 대기
)
# Row Factory 설정 (dict 형태로 결과 반환)
self.sqlite_conn.row_factory = sqlite3.Row
# 신규 DB면 스키마 초기화
if is_new_db:
self.init_sqlite_schema()
print(f"[DB Manager] SQLite 신규 DB 생성 완료: {self.sqlite_db_path}")
else:
print(f"[DB Manager] SQLite 기존 DB 연결: {self.sqlite_db_path}")
self._migrate_sqlite()
self.sqlite_conn = self._create_sqlite_connection()
return self.sqlite_conn
def _create_sqlite_connection(self):
"""새 SQLite 연결 생성"""
is_new_db = not self.sqlite_db_path.exists()
conn = sqlite3.connect(
str(self.sqlite_db_path),
check_same_thread=False,
timeout=10.0
)
conn.row_factory = sqlite3.Row
if is_new_db:
# 스키마 초기화 (임시로 self.sqlite_conn 설정)
old_conn = self.sqlite_conn
self.sqlite_conn = conn
self.init_sqlite_schema()
self.sqlite_conn = old_conn
print(f"[DB Manager] SQLite 신규 DB 생성 완료: {self.sqlite_db_path}")
return conn
def init_sqlite_schema(self):
"""