Azure SQLの接続ポリシーをデフォルトで作るとそういった設定になる。TCP KeepAliveだけでは接続を維持できないのでコネクションをプールするならなんかしらのクエリを実行してあげる必要がある。または接続ポリシーをリダイレクトという直接DBに接続しにいく設定にすることで回避することができる。
なんかたまにRSTでアプリがリトライしてるなと思って調べてみたらこんなことが起きていた...(ハーフクローズなのでCLOSE_WAITが溜まりまくっているというところから発覚)
リトライを書いてあげる
import time from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.exc import OperationalError, InterfaceError DATABASE_URL = "mssql+pyodbc://username:password@localhost:1433/database_name?driver=ODBC+Driver+17+for+SQL+Server" engine = create_engine( DATABASE_URL, echo=True, pool_size=5, max_overflow=10, pool_timeout=30, pool_recycle=1800 ) Session = sessionmaker(bind=engine) def execute_query_with_retry(query, max_retries=3, delay=5): session = Session() retries = 0 while retries < max_retries: try: result = session.execute(query) for row in result: print(row) session.commit() return result except (OperationalError, InterfaceError) as e: print(f"接続エラーが発生しました。リトライします... (試行回数: {retries + 1})") retries += 1 session.close() time.sleep(delay) except Exception as e: print(f"予期しないエラーが発生しました: {e}") session.close() break print(f"最大試行回数に達しました。クエリ実行に失敗しました。") session.close() return None query = "SELECT * FROM customers WHERE company_id = '100148' LIMIT 10 OFFSET 0" execute_query_with_retry(query)
あとは別スレッド立ててそこでファイルディスクリプタをreadしておいて閉じてたらそのコネクションプールを破棄するとかでも動きそう。