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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

【SQLAlchemy】MySQL server has gone away 原因分析、解决方法

發布時間:2024/2/28 数据库 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【SQLAlchemy】MySQL server has gone away 原因分析、解决方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

SQLAlchemy報錯:MySQL server has gone away

錯誤日志

2020-01-03 20:00:00,072 - update_example_table.py - get_pcodes_arr_by_kind_from_db[line:147] - ERROR: (pymysql.err.OperationalError) (2006, “MySQL server has gone away (error(10053, ‘’))”)
[SQL: SELECT example_menu.p_codes AS example_menu_p_codes
FROM example_menu
WHERE example_menu.isactive = %(isactive_1)s AND example_menu.kind = %(kind_1)s]
[parameters: {u’kind_1’: ‘BLACK’, u’isactive_1’: 1}]
(Background on this error at: http://sqlalche.me/e/e3q8)

錯誤原因

從字面理解,就是你連接的MySQL已經走人了,不在了。相當于你和另外一個人打電話,你一直沒有掛電話,但是你把電話放一邊了,直到你重新拎起電話想說點啥,才聽到里面『嘟,嘟,嘟,嘟…』的掛機聲,于是你就知道電話另一頭的人已經gone away了。

線上碰到這個問題時,通常就是拋一個異常,然后(主動/被動)重新連接一下,你下次就重新執行一下要執行的語句就行。這就像你覺得有一番話非說不可,然后重新撥了個電話過去。

什么情況下會gone away?就像剛才說的,當你拿著一個電話太久,又不說話的時候,對面肯定就把你掛了;

當sqlalchemy與MySQL建立了一個連接,而sqlalchemy又不對這個連接執行任何(有含義)的語句,這個連接對于MySQL而言就處于sleep,當sleep了太久,MySQL就把連接一頭關閉了(可能說了句"啥玩意兒")

這時,如果sqlalchemy在這個連接上嘗試執行語句,就會出現gone away的錯誤。

conn.close() 是把連接放回連接池,不是真正的關閉;池子里的空閑連接在MySQL線程里sleep,長時間不操作,MySQL把連接一端關閉了,所以第二天SQLAlchemy再用這個連接的時候,拋出MySQL server has gone away…

解決方法

1. 設置SQLAlchemy的連接有效期,在MySQL關閉它之前,我先關閉它

因為scoped_session是threadlocal的,相同線程會用到相同的session,如果session還持有connection,從pool里checkout connection時不會進行過期的檢查操作,直接使用,所以必須設置SQLAIchemy的有效期

SQLAlchemy連接池重新生成的周期默認為timeout是2小時,通過 SHOW VARIABLES 可以查看數據庫配置的timeout時間(如下圖所示),所以設置sqlalchemy的 "pool_recycle"參數小于360s,就會在數據庫服務器斷開連接之前,自己斷開并重新生成連接

2. 在Web框架的層面,每次請求處理完畢時,顯式地關閉session。

a. web框架顯示關閉session的方法有很多,常規方法如下,在finally中主動關閉seession
b. Django和Flask都有middleware機制,可以在接收請求之前和處理完請求之后對session進行remove
c. Flask有一類修飾器hook,可以在請求后或請求前做一些事情,使用hook顯示關閉session如下

了解其他hook修飾器:

before_first_request:注冊一個函數,在處理第一個請求之前運行。 before_request:注冊一個函數,在每次請求之前運行。 after_request:注冊一個函數,如果沒有未處理的異常拋出,在每次請求之后運行。 teardown_request:注冊一個函數,即使有未處理的異常拋出,也在每次請求之后運行。 在使用session之前,先檢查其有效性,無效則創建新的session以供使用

3. 在使用session之前,先檢查其有效性,無效則創建新的session以供使用


拓展:類似問題 - Lost connection to mysql server during query

(使用的是Flask-SQLAlchemy)

一般由以下四種情況造成, 通過SHOW VARIABLES LIKE ‘’查看一下字段:

1、查詢中大量數據被發送,由于數據傳輸時間不夠導致,可以增加net_read_timeout的值。

net_read_timeout : mysql服務端從客戶端讀取(接收)數據時,服務端等待客戶端響應的超時時間,當服務端正在從客戶端讀取數據時,net_read_timeout控制何時超時

2、初次連接時,連接時間設定太少,可以增加connect_timeout的值改善。

connect_timeout:在獲取連接階段(authenticate)起作用, 獲取MySQL連接是多次握手的結果,除了用戶名和密碼的匹配校驗外,還有IP->HOST->DNS->IP驗證,任何一步都可能因為網絡問題導致線程阻塞。為 了防止線程浪費在不必要的校驗等待上,超過connect_timeout的連接請求將會被拒絕。

3、有些少見的情況可以show global status like 'aborted_connets',這個全局變量在每一次服務器終止時會增加1,查看"reading authorization packet"獲取錯誤信息。

4、BLOB值太大的問題,調整配置文件max_allowed_packet。

mysql根據配置文件會限制server接受的數據包大小。有時候大的插入和更新會被max_allowed_packet 參數限制掉,導致失敗。


拓展:【Python】SQLAlchemy:session何時commit,何時close?

Engine 相當于一個創建連接的工廠,而不是連接本身。當使用conn.close()時,連接被放回到Engine的連接池當中,而不是真正的關閉了。

如果想要在調用conn.close()時,真正的關閉連接,可以使用poolclass=NullPool屬性:

from sqlalchemy.pool import NullPool db = create_engine('mysql://root@localhost/test_database', poolclass=NullPool)

拓展:初始問題 - 【Python】SQLAlchemy長時間未請求,數據庫連接斷開的原因、解決方案

一個基于apscheduler的定時任務,里面的任務使用了sqlalchemy,這個任務每天跑,但是第二天就連不上數據庫

總結

以上是生活随笔為你收集整理的【SQLAlchemy】MySQL server has gone away 原因分析、解决方法的全部內容,希望文章能夠幫你解決所遇到的問題。

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