日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

【Python】SQLAlchemy长时间未请求,数据库连接断开的原因、解决方案

發(fā)布時間:2024/2/28 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Python】SQLAlchemy长时间未请求,数据库连接断开的原因、解决方案 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

這個問題好像和長時間連接數(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語句上卡住,沒有任何輸出),但第二個任務可以正常運行。
  • 第三天仍然是,第一個任務不能正常運行,但第二個任務可以正常運行。
原因猜想:
  • 數(shù)據(jù)庫死鎖,導致一直等待?每天到點就鎖表,不是很能說得通,也手工排除了一下這種可能:在第二天自動跑的時候,用show processlist一直監(jiān)視數(shù)據(jù)庫進程,沒有看到鎖表情況。
  • 上一次運行過程中的某一個 session 沒 commit ?檢查代碼,沒有發(fā)現(xiàn)遺漏。
  • 當進行過一輪增/刪/改/查操作后,不使用 sqlalchemy 的時候,session 需要 close?(未測試,代碼中沒有使用 close,只是用了 commit,所以有可能是這個原因)
  • SQLAlchemy長時間未請求數(shù)據(jù)庫連接斷開?(可能性較大)
  • 解決方案:

    分析了一下,覺得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ù),是負責管理連接超時的。

  • interactive_timeout:針對交互式連接
  • wait_timeout:針對非交互式連接。
  • 所謂的交互式連接,即在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ù)庫連接失敗!

    解決辦法:

  • 修改mysql配置文件里wait_timeout參數(shù),讓這個時間大于連接池的回收時間(修改配置文件需要重啟數(shù)據(jù)庫,不推薦!)
  • 修改數(shù)據(jù)庫連接池的配置,數(shù)據(jù)庫連接池都會帶有一個參數(shù):回收時間(就是一定時間內不使用就會回收),修改這個參數(shù)的值,不要大于wait_timeout的值即可。在flask-SQLAlchemy中有個配置是SQLALCHEMY_POOL_RECYCLE(多之后對線程池中的線程進行一次連接的回收),如果這個值是-1代表永不回收,Flask-SQLALchemy 自動設定這個值為2小時,我們可以將這個值設置的小于wait_timeout參數(shù)的值也就是8小時即可。
  • 禁用SQLAlchemy提供的數(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长时间未请求,数据库连接断开的原因、解决方案的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內容還不錯,歡迎將生活随笔推薦給好友。