【Python】SQLAlchemy长时间未请求,数据库连接断开的原因、解决方案
這個問題好像和長時間連接數(shù)據(jù)庫但不打開網(wǎng)頁時,報錯lost connection是一個原因
問題:
寫了一個基于apscheduler的定時任務,里面的任務使用了sqlalchemy,大致如下:
scheduler.py
# ... # 此處省略 import# 示例任務1 def example_job1():exalple_query()# 示例任務2 def example_job2():exalple_query()# 2050-01-01前,每天定時運行sched.add_job(example_job1, 'cron', hour=19, minute=10, second=00, end_date='2050-01-01') sched.add_job(example_job2, 'cron', hour=20, minute=00, second=30, end_date='2050-01-01') # sched.add_job(job_function, 'interval', seconds=10)sched.start()使用python scheduler.py跑起來之后,每次都是:
- 當天可以正常運行兩個任務;
- 第二天跑的時候,第一個任務不能正常運行(在某條query語句上卡住,沒有任何輸出),但第二個任務可以正常運行。
- 第三天仍然是,第一個任務不能正常運行,但第二個任務可以正常運行。
原因猜想:
解決方案:
分析了一下,覺得SQLAlchemy長時間未請求數(shù)據(jù)庫連接斷開的可能性較大。
臨時解決方案:在正式運行定時任務之前,先跑一個session.query(),相當于喚醒連接。
修改后如下:
# ... # 此處省略 import# 保持連接 def keep_sqlalchemy_connected_job():result_no_use = session.query(Example_table).first()# 示例任務1 def example_job1():exalple_query()# 示例任務2 def example_job2():exalple_query()# 2050-01-01前,每天定時運行 sched.add_job(keep_sqlalchemy_connected_job, 'cron', hour=18, minute=55, second=00, end_date='2050-01-01') # 保持連接 sched.add_job(example_job1, 'cron', hour=19, minute=10, second=00, end_date='2050-01-01') sched.add_job(example_job2, 'cron', hour=20, minute=00, second=30, end_date='2050-01-01') # sched.add_job(job_function, 'interval', seconds=10)sched.start()拓展閱讀:SQLAlchemy長時間未請求數(shù)據(jù)庫連接斷開
當較長時間沒有去訪問網(wǎng)站,再次打開時就會報一個數(shù)據(jù)庫連接失敗的錯誤。這也解釋了之前遇到過的lost connection問題。
連接池連接mysql數(shù)據(jù)庫失敗,應該是mysql數(shù)據(jù)庫連接超時,mysql數(shù)據(jù)庫配置文件存在以下兩個參數(shù),是負責管理連接超時的。
所謂的交互式連接,即在mysql_real_connect()函數(shù)中使用了CLIENT_INTERACTIVE選項。說得直白一點,通過mysql客戶端連接數(shù)據(jù)庫是交互式連接,通過jdbc連接數(shù)據(jù)庫是非交互式連接。
這兩個參數(shù)默認都是28800秒,即8小時,也就是超過8小時的連接就會自動失效。這本身并沒什么問題,真正的問題是:我們做項目一般使用數(shù)據(jù)庫連接池來獲取連接,連接池里的連接可能會較長時間不關閉,等待被使用,這就與mysql連接超時機制起沖突了,當連接池配置永不關閉或者關閉時間超過8小時就會出現(xiàn)我所遇到的問題。
當超過8個小時沒有新的數(shù)據(jù)庫請求的時候,數(shù)據(jù)庫連接就會斷開,如果我們連接池的配置是用不關閉或者關閉時間超過8小時,這個時候連接池沒有回收并且還認為連接池與數(shù)據(jù)庫之間的連接還存在,就會繼續(xù)連接,但是數(shù)據(jù)庫連接斷開了,就會報錯數(shù)據(jù)庫連接失敗!
解決辦法:
只需要在調用 create_engine 是指定連接池為 NullPool,SQLAlchemy就會在執(zhí)行 session.close() 后立刻斷開數(shù)據(jù)庫連接。當然,如果 session 對象被析構但是沒有被調用 session.close(),則數(shù)據(jù)庫連接不會被斷開,直到程序終止。
引用一下別人的總結 (Java版)
原文:一個由session.close()引發(fā)的血案
問題很明顯了。如果不調用close 方法,
當前連接不會釋放回空閑連接池中,一直存在于 活動連接池中,當空閑連接池耗光之后 pop 會從 活動連接池中選取第一個連接,
返回給應用.而這個時候 這個連接從最后次使用到拿出來可能過了好幾分鐘了。就真的是個處于關閉狀態(tài)的連接了。
總結
以上是生活随笔為你收集整理的【Python】SQLAlchemy长时间未请求,数据库连接断开的原因、解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Python】import xxx 文
- 下一篇: 【Python】zip函数的使用